summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/spf13/cast/caste.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/spf13/cast/caste.go')
-rw-r--r--vendor/github.com/spf13/cast/caste.go148
1 files changed, 118 insertions, 30 deletions
diff --git a/vendor/github.com/spf13/cast/caste.go b/vendor/github.com/spf13/cast/caste.go
index 70c7291b..c04af6a9 100644
--- a/vendor/github.com/spf13/cast/caste.go
+++ b/vendor/github.com/spf13/cast/caste.go
@@ -20,13 +20,20 @@ var errNegativeNotAllowed = errors.New("unable to cast negative value")
// ToTimeE casts an interface to a time.Time type.
func ToTimeE(i interface{}) (tim time.Time, err error) {
+ return ToTimeInDefaultLocationE(i, time.UTC)
+}
+
+// ToTimeInDefaultLocationE casts an empty interface to time.Time,
+// interpreting inputs without a timezone to be in the given location,
+// or the local timezone if nil.
+func ToTimeInDefaultLocationE(i interface{}, location *time.Location) (tim time.Time, err error) {
i = indirect(i)
switch v := i.(type) {
case time.Time:
return v, nil
case string:
- return StringToDate(v)
+ return StringToDateInDefaultLocation(v, location)
case int:
return time.Unix(int64(v), 0), nil
case int64:
@@ -1129,8 +1136,43 @@ func ToStringSliceE(i interface{}) ([]string, error) {
return a, nil
case []string:
return v, nil
+ case []int8:
+ for _, u := range v {
+ a = append(a, ToString(u))
+ }
+ return a, nil
+ case []int:
+ for _, u := range v {
+ a = append(a, ToString(u))
+ }
+ return a, nil
+ case []int32:
+ for _, u := range v {
+ a = append(a, ToString(u))
+ }
+ return a, nil
+ case []int64:
+ for _, u := range v {
+ a = append(a, ToString(u))
+ }
+ return a, nil
+ case []float32:
+ for _, u := range v {
+ a = append(a, ToString(u))
+ }
+ return a, nil
+ case []float64:
+ for _, u := range v {
+ a = append(a, ToString(u))
+ }
+ return a, nil
case string:
return strings.Fields(v), nil
+ case []error:
+ for _, err := range i.([]error) {
+ a = append(a, err.Error())
+ }
+ return a, nil
case interface{}:
str, err := ToStringE(v)
if err != nil {
@@ -1204,37 +1246,83 @@ func ToDurationSliceE(i interface{}) ([]time.Duration, error) {
// predefined list of formats. If no suitable format is found, an error is
// returned.
func StringToDate(s string) (time.Time, error) {
- return parseDateWith(s, []string{
- time.RFC3339,
- "2006-01-02T15:04:05", // iso8601 without timezone
- time.RFC1123Z,
- time.RFC1123,
- time.RFC822Z,
- time.RFC822,
- time.RFC850,
- time.ANSIC,
- time.UnixDate,
- time.RubyDate,
- "2006-01-02 15:04:05.999999999 -0700 MST", // Time.String()
- "2006-01-02",
- "02 Jan 2006",
- "2006-01-02T15:04:05-0700", // RFC3339 without timezone hh:mm colon
- "2006-01-02 15:04:05 -07:00",
- "2006-01-02 15:04:05 -0700",
- "2006-01-02 15:04:05Z07:00", // RFC3339 without T
- "2006-01-02 15:04:05Z0700", // RFC3339 without T or timezone hh:mm colon
- "2006-01-02 15:04:05",
- time.Kitchen,
- time.Stamp,
- time.StampMilli,
- time.StampMicro,
- time.StampNano,
- })
+ return parseDateWith(s, time.UTC, timeFormats)
+}
+
+// StringToDateInDefaultLocation casts an empty interface to a time.Time,
+// interpreting inputs without a timezone to be in the given location,
+// or the local timezone if nil.
+func StringToDateInDefaultLocation(s string, location *time.Location) (time.Time, error) {
+ return parseDateWith(s, location, timeFormats)
}
-func parseDateWith(s string, dates []string) (d time.Time, e error) {
- for _, dateType := range dates {
- if d, e = time.Parse(dateType, s); e == nil {
+type timeFormatType int
+
+const (
+ timeFormatNoTimezone timeFormatType = iota
+ timeFormatNamedTimezone
+ timeFormatNumericTimezone
+ timeFormatNumericAndNamedTimezone
+ timeFormatTimeOnly
+)
+
+type timeFormat struct {
+ format string
+ typ timeFormatType
+}
+
+func (f timeFormat) hasTimezone() bool {
+ // We don't include the formats with only named timezones, see
+ // https://github.com/golang/go/issues/19694#issuecomment-289103522
+ return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone
+}
+
+var (
+ timeFormats = []timeFormat{
+ timeFormat{time.RFC3339, timeFormatNumericTimezone},
+ timeFormat{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
+ timeFormat{time.RFC1123Z, timeFormatNumericTimezone},
+ timeFormat{time.RFC1123, timeFormatNamedTimezone},
+ timeFormat{time.RFC822Z, timeFormatNumericTimezone},
+ timeFormat{time.RFC822, timeFormatNamedTimezone},
+ timeFormat{time.RFC850, timeFormatNamedTimezone},
+ timeFormat{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
+ timeFormat{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon
+ timeFormat{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon
+ timeFormat{"2006-01-02 15:04:05", timeFormatNoTimezone},
+ timeFormat{time.ANSIC, timeFormatNoTimezone},
+ timeFormat{time.UnixDate, timeFormatNamedTimezone},
+ timeFormat{time.RubyDate, timeFormatNumericTimezone},
+ timeFormat{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
+ timeFormat{"2006-01-02", timeFormatNoTimezone},
+ timeFormat{"02 Jan 2006", timeFormatNoTimezone},
+ timeFormat{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
+ timeFormat{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
+ timeFormat{time.Kitchen, timeFormatTimeOnly},
+ timeFormat{time.Stamp, timeFormatTimeOnly},
+ timeFormat{time.StampMilli, timeFormatTimeOnly},
+ timeFormat{time.StampMicro, timeFormatTimeOnly},
+ timeFormat{time.StampNano, timeFormatTimeOnly},
+ }
+)
+
+func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) {
+
+ for _, format := range formats {
+ if d, e = time.Parse(format.format, s); e == nil {
+
+ // Some time formats have a zone name, but no offset, so it gets
+ // put in that zone name (not the default one passed in to us), but
+ // without that zone's offset. So set the location manually.
+ if format.typ <= timeFormatNamedTimezone {
+ if location == nil {
+ location = time.Local
+ }
+ year, month, day := d.Date()
+ hour, min, sec := d.Clock()
+ d = time.Date(year, month, day, hour, min, sec, d.Nanosecond(), location)
+ }
+
return
}
}