Merge f31dc0aaab into 1ffadf5510
				
					
				
			This commit is contained in:
		
						commit
						352095c115
					
				@ -8,9 +8,14 @@ go:
 | 
				
			|||||||
  - tip
 | 
					  - tip
 | 
				
			||||||
os:
 | 
					os:
 | 
				
			||||||
  - linux
 | 
					  - linux
 | 
				
			||||||
 | 
					  - osx
 | 
				
			||||||
 | 
					  - windows
 | 
				
			||||||
matrix:
 | 
					matrix:
 | 
				
			||||||
  allow_failures:
 | 
					  allow_failures:
 | 
				
			||||||
    - go: tip
 | 
					    - go: tip
 | 
				
			||||||
 | 
					  exclude:
 | 
				
			||||||
 | 
					    - os: windows
 | 
				
			||||||
 | 
					      go: tip
 | 
				
			||||||
  fast_finish: true
 | 
					  fast_finish: true
 | 
				
			||||||
script:
 | 
					script:
 | 
				
			||||||
  - make check
 | 
					  - if [[ "$TRAVIS_OS_NAME" == "windows" ]]; then go test -v -race ./...; else make check; fi
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										12
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Makefile
									
									
									
									
									
								
							@ -1,15 +1,15 @@
 | 
				
			|||||||
GOVERSION := $(shell go version | cut -d ' ' -f 3 | cut -d '.' -f 2)
 | 
					GOVERSION := $(shell go version | cut -d ' ' -f 3 | cut -d '.' -f 2)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: check fmt lint test test-race vet test-cover-html help
 | 
					.PHONY: check fmt test test-race vet test-cover-html help
 | 
				
			||||||
.DEFAULT_GOAL := help
 | 
					.DEFAULT_GOAL := help
 | 
				
			||||||
 | 
					
 | 
				
			||||||
check: test-race fmt vet lint ## Run tests and linters
 | 
					check: test-race fmt vet ## Run tests and linters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test: ## Run tests
 | 
					test: ## Run tests
 | 
				
			||||||
	go test ./...
 | 
						go test ./...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test-race: ## Run tests with race detector
 | 
					test-race: ## Run tests with race detector
 | 
				
			||||||
	go test -race ./...
 | 
						go test -v -race ./...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fmt: ## Run gofmt linter
 | 
					fmt: ## Run gofmt linter
 | 
				
			||||||
ifeq "$(GOVERSION)" "12"
 | 
					ifeq "$(GOVERSION)" "12"
 | 
				
			||||||
@ -20,12 +20,6 @@ ifeq "$(GOVERSION)" "12"
 | 
				
			|||||||
	done
 | 
						done
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lint: ## Run golint linter
 | 
					 | 
				
			||||||
	@for d in `go list` ; do \
 | 
					 | 
				
			||||||
		if [ "`golint $$d | tee /dev/stderr`" ]; then \
 | 
					 | 
				
			||||||
			echo "^ golint errors!" && echo && exit 1; \
 | 
					 | 
				
			||||||
		fi \
 | 
					 | 
				
			||||||
	done
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
vet: ## Run go vet linter
 | 
					vet: ## Run go vet linter
 | 
				
			||||||
	@if [ "`go vet | tee /dev/stderr`" ]; then \
 | 
						@if [ "`go vet | tee /dev/stderr`" ]; then \
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8
									
								
								cast.go
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								cast.go
									
									
									
									
									
								
							@ -20,6 +20,14 @@ func ToTime(i interface{}) time.Time {
 | 
				
			|||||||
	return v
 | 
						return v
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ToTimeInDefaultLocationE casts an empty interface to time.Time,
 | 
				
			||||||
 | 
					// interpreting inputs without a timezone to be in the given location.
 | 
				
			||||||
 | 
					// To fall back to the local timezone, use time.Local as the last argument.
 | 
				
			||||||
 | 
					func ToTimeInDefaultLocation(i interface{}, location *time.Location) time.Time {
 | 
				
			||||||
 | 
						v, _ := ToTimeInDefaultLocationE(i, location)
 | 
				
			||||||
 | 
						return v
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ToDuration casts an interface to a time.Duration type.
 | 
					// ToDuration casts an interface to a time.Duration type.
 | 
				
			||||||
func ToDuration(i interface{}) time.Duration {
 | 
					func ToDuration(i interface{}) time.Duration {
 | 
				
			||||||
	v, _ := ToDurationE(i)
 | 
						v, _ := ToDurationE(i)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										149
									
								
								cast_test.go
									
									
									
									
									
								
							
							
						
						
									
										149
									
								
								cast_test.go
									
									
									
									
									
								
							@ -8,10 +8,12 @@ package cast
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"html/template"
 | 
						"html/template"
 | 
				
			||||||
 | 
						"path"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestToUintE(t *testing.T) {
 | 
					func TestToUintE(t *testing.T) {
 | 
				
			||||||
@ -1173,7 +1175,7 @@ func TestIndirectPointers(t *testing.T) {
 | 
				
			|||||||
	assert.Equal(t, ToInt(z), 13)
 | 
						assert.Equal(t, ToInt(z), 13)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestToTimeEE(t *testing.T) {
 | 
					func TestToTime(t *testing.T) {
 | 
				
			||||||
	tests := []struct {
 | 
						tests := []struct {
 | 
				
			||||||
		input  interface{}
 | 
							input  interface{}
 | 
				
			||||||
		expect time.Time
 | 
							expect time.Time
 | 
				
			||||||
@ -1285,3 +1287,148 @@ func TestToDurationE(t *testing.T) {
 | 
				
			|||||||
		assert.Equal(t, test.expect, v, errmsg)
 | 
							assert.Equal(t, test.expect, v, errmsg)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestToTimeWithTimezones(t *testing.T) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						est, err := time.LoadLocation("EST")
 | 
				
			||||||
 | 
						require.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						irn, err := time.LoadLocation("Iran")
 | 
				
			||||||
 | 
						require.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						require.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Test same local time in different timezones
 | 
				
			||||||
 | 
						utc2016 := time.Date(2016, time.January, 1, 3, 1, 0, 0, time.UTC)
 | 
				
			||||||
 | 
						est2016 := time.Date(2016, time.January, 1, 3, 1, 0, 0, est)
 | 
				
			||||||
 | 
						irn2016 := time.Date(2016, time.January, 1, 3, 1, 0, 0, irn)
 | 
				
			||||||
 | 
						loc2016 := time.Date(2016, time.January, 1, 3, 1, 0, 0, time.Local)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i, format := range timeFormats {
 | 
				
			||||||
 | 
							format := format
 | 
				
			||||||
 | 
							if format.typ == timeFormatShort {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							nameBase := fmt.Sprintf("%d;timeFormatType=%d;%s", i, format.typ, format.format)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							t.Run(path.Join(nameBase), func(t *testing.T) {
 | 
				
			||||||
 | 
								est2016str := est2016.Format(format.format)
 | 
				
			||||||
 | 
								loc2016str := loc2016.Format(format.format)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								t.Run("without default location", func(t *testing.T) {
 | 
				
			||||||
 | 
									assert := require.New(t)
 | 
				
			||||||
 | 
									converted, err := ToTimeE(est2016str)
 | 
				
			||||||
 | 
									assert.NoError(err)
 | 
				
			||||||
 | 
									if format.hasNumericTimezone() {
 | 
				
			||||||
 | 
										assertTimeEqual(t, est2016, converted)
 | 
				
			||||||
 | 
										assertLocationEqual(t, est, converted.Location())
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										assertTimeEqual(t, utc2016, converted)
 | 
				
			||||||
 | 
										assertLocationEqual(t, time.UTC, converted.Location())
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								t.Run("local timezone without a default location", func(t *testing.T) {
 | 
				
			||||||
 | 
									assert := require.New(t)
 | 
				
			||||||
 | 
									converted, err := ToTimeE(loc2016str)
 | 
				
			||||||
 | 
									assert.NoError(err)
 | 
				
			||||||
 | 
									if format.hasAnyTimezone() {
 | 
				
			||||||
 | 
										// Local timezone strings can be either named or numeric and
 | 
				
			||||||
 | 
										// time.Parse connects the dots.
 | 
				
			||||||
 | 
										assertTimeEqual(t, loc2016, converted)
 | 
				
			||||||
 | 
										assertLocationEqual(t, time.Local, converted.Location())
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										assertTimeEqual(t, utc2016, converted)
 | 
				
			||||||
 | 
										assertLocationEqual(t, time.UTC, converted.Location())
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								t.Run("nil default location", func(t *testing.T) {
 | 
				
			||||||
 | 
									assert := require.New(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									converted, err := ToTimeInDefaultLocationE(est2016str, nil)
 | 
				
			||||||
 | 
									assert.NoError(err)
 | 
				
			||||||
 | 
									if format.hasNumericTimezone() {
 | 
				
			||||||
 | 
										assertTimeEqual(t, est2016, converted)
 | 
				
			||||||
 | 
										assertLocationEqual(t, est, converted.Location())
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										assertTimeEqual(t, utc2016, converted)
 | 
				
			||||||
 | 
										assertLocationEqual(t, time.UTC, converted.Location())
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								t.Run("default location not UTC", func(t *testing.T) {
 | 
				
			||||||
 | 
									assert := require.New(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									converted, err := ToTimeInDefaultLocationE(est2016str, irn)
 | 
				
			||||||
 | 
									assert.NoError(err)
 | 
				
			||||||
 | 
									if format.hasNumericTimezone() {
 | 
				
			||||||
 | 
										assertTimeEqual(t, est2016, converted)
 | 
				
			||||||
 | 
										assertLocationEqual(t, est, converted.Location())
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										assertTimeEqual(t, irn2016, converted)
 | 
				
			||||||
 | 
										assertLocationEqual(t, irn, converted.Location())
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								t.Run("time in the local timezone default location not UTC", func(t *testing.T) {
 | 
				
			||||||
 | 
									assert := require.New(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									converted, err := ToTimeInDefaultLocationE(loc2016str, irn)
 | 
				
			||||||
 | 
									assert.NoError(err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if format.hasNumericTimezone() {
 | 
				
			||||||
 | 
										assertTimeEqual(t, loc2016, converted)
 | 
				
			||||||
 | 
										assertLocationEqual(t, time.Local, converted.Location())
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										assertTimeEqual(t, irn2016, converted)
 | 
				
			||||||
 | 
										assertLocationEqual(t, irn, converted.Location())
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func assertTimeEqual(t *testing.T, expected, actual time.Time) {
 | 
				
			||||||
 | 
						t.Helper()
 | 
				
			||||||
 | 
						require.True(t, expected.Equal(actual), fmt.Sprintf("expected\n%s\ngot\n%s", expected, actual))
 | 
				
			||||||
 | 
						format := "2006-01-02 15:04:05.999999999 -0700"
 | 
				
			||||||
 | 
						require.Equal(t, expected.Format(format), actual.Format(format))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func assertLocationEqual(t *testing.T, expected, actual *time.Location) {
 | 
				
			||||||
 | 
						t.Helper()
 | 
				
			||||||
 | 
						require.True(t, locationEqual(expected, actual), fmt.Sprintf("Expected location '%s', got '%s'", expected, actual))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func locationEqual(a, b *time.Location) bool {
 | 
				
			||||||
 | 
						// A note about comparing time.Locations:
 | 
				
			||||||
 | 
						//   - can't only compare pointers
 | 
				
			||||||
 | 
						//   - can't compare loc.String() because locations with the same
 | 
				
			||||||
 | 
						//     name can have different offsets
 | 
				
			||||||
 | 
						//   - can't use reflect.DeepEqual because time.Location has internal
 | 
				
			||||||
 | 
						//     caches
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if a == b {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						} else if a == nil || b == nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check if they're equal by parsing times with a format that doesn't
 | 
				
			||||||
 | 
						// include a timezone, which will interpret it as being a local time in
 | 
				
			||||||
 | 
						// the given zone, and comparing the resulting local times.
 | 
				
			||||||
 | 
						tA, err := time.ParseInLocation("2006-01-02", "2016-01-01", a)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tB, err := time.ParseInLocation("2006-01-02", "2016-01-01", b)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return tA.Equal(tB)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										121
									
								
								caste.go
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								caste.go
									
									
									
									
									
								
							@ -20,13 +20,20 @@ var errNegativeNotAllowed = errors.New("unable to cast negative value")
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ToTimeE casts an interface to a time.Time type.
 | 
					// ToTimeE casts an interface to a time.Time type.
 | 
				
			||||||
func ToTimeE(i interface{}) (tim time.Time, err error) {
 | 
					func ToTimeE(i interface{}) (tim time.Time, err error) {
 | 
				
			||||||
 | 
						return ToTimeInDefaultLocationE(i, nil)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ToTimeInDefaultLocationE casts an empty interface to time.Time,
 | 
				
			||||||
 | 
					// interpreting inputs without a timezone to be in the given location.
 | 
				
			||||||
 | 
					// To fall back to the local timezone, use time.Local as the last argument.
 | 
				
			||||||
 | 
					func ToTimeInDefaultLocationE(i interface{}, location *time.Location) (tim time.Time, err error) {
 | 
				
			||||||
	i = indirect(i)
 | 
						i = indirect(i)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch v := i.(type) {
 | 
						switch v := i.(type) {
 | 
				
			||||||
	case time.Time:
 | 
						case time.Time:
 | 
				
			||||||
		return v, nil
 | 
							return v, nil
 | 
				
			||||||
	case string:
 | 
						case string:
 | 
				
			||||||
		return StringToDate(v)
 | 
							return StringToDateInDefaultLocation(v, location)
 | 
				
			||||||
	case int:
 | 
						case int:
 | 
				
			||||||
		return time.Unix(int64(v), 0), nil
 | 
							return time.Unix(int64(v), 0), nil
 | 
				
			||||||
	case int64:
 | 
						case int64:
 | 
				
			||||||
@ -1204,43 +1211,97 @@ func ToDurationSliceE(i interface{}) ([]time.Duration, error) {
 | 
				
			|||||||
// predefined list of formats.  If no suitable format is found, an error is
 | 
					// predefined list of formats.  If no suitable format is found, an error is
 | 
				
			||||||
// returned.
 | 
					// returned.
 | 
				
			||||||
func StringToDate(s string) (time.Time, error) {
 | 
					func StringToDate(s string) (time.Time, error) {
 | 
				
			||||||
	return parseDateWith(s, []string{
 | 
						return parseDateWith(s, nil, timeFormats)
 | 
				
			||||||
		time.RFC3339,
 | 
					}
 | 
				
			||||||
		"2006-01-02T15:04:05", // iso8601 without timezone
 | 
					
 | 
				
			||||||
		time.RFC1123Z,
 | 
					// StringToDateInDefaultLocation to parse a string into a time.Time type using a
 | 
				
			||||||
		time.RFC1123,
 | 
					// predefined list of formats, interpreting inputs without a timezone to be in
 | 
				
			||||||
		time.RFC822Z,
 | 
					// the given location.
 | 
				
			||||||
		time.RFC822,
 | 
					// To fall back to the local timezone, use time.Local as the last argument.
 | 
				
			||||||
		time.RFC850,
 | 
					func StringToDateInDefaultLocation(s string, location *time.Location) (time.Time, error) {
 | 
				
			||||||
		time.ANSIC,
 | 
						return parseDateWith(s, location, timeFormats)
 | 
				
			||||||
		time.UnixDate,
 | 
					}
 | 
				
			||||||
		time.RubyDate,
 | 
					
 | 
				
			||||||
		"2006-01-02 15:04:05.999999999 -0700 MST", // Time.String()
 | 
					func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) {
 | 
				
			||||||
		"2006-01-02",
 | 
						for _, format := range formats {
 | 
				
			||||||
		"02 Jan 2006",
 | 
							if d, e = time.Parse(format.format, s); e == nil {
 | 
				
			||||||
		"2006-01-02T15:04:05-0700", // RFC3339 without timezone hh:mm colon
 | 
					
 | 
				
			||||||
		"2006-01-02 15:04:05 -07:00",
 | 
								// Some time formats have a zone name, but no offset, so it gets
 | 
				
			||||||
		"2006-01-02 15:04:05 -0700",
 | 
								// put in that zone name (not the default one passed in to us), but
 | 
				
			||||||
		"2006-01-02 15:04:05Z07:00", // RFC3339 without T
 | 
								// without that zone's offset. So set the location manually.
 | 
				
			||||||
		"2006-01-02 15:04:05Z0700",  // RFC3339 without T or timezone hh:mm colon
 | 
								// Note that we only do this when we get a location in the new *InDefaultLocation
 | 
				
			||||||
		"2006-01-02 15:04:05",
 | 
								// variants to avoid breaking existing behaviour in ToTime, however
 | 
				
			||||||
		time.Kitchen,
 | 
								// weird that existing behaviour may be.
 | 
				
			||||||
		time.Stamp,
 | 
								if location != nil && !format.hasNumericTimezone() {
 | 
				
			||||||
		time.StampMilli,
 | 
									year, month, day := d.Date()
 | 
				
			||||||
		time.StampMicro,
 | 
									hour, min, sec := d.Clock()
 | 
				
			||||||
		time.StampNano,
 | 
									d = time.Date(year, month, day, hour, min, sec, d.Nanosecond(), location)
 | 
				
			||||||
	})
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func parseDateWith(s string, dates []string) (d time.Time, e error) {
 | 
					 | 
				
			||||||
	for _, dateType := range dates {
 | 
					 | 
				
			||||||
		if d, e = time.Parse(dateType, s); e == nil {
 | 
					 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return d, fmt.Errorf("unable to parse date: %s", s)
 | 
						return d, fmt.Errorf("unable to parse date: %s", s)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type timeFormatType int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						timeFormatShort timeFormatType = iota // time or date only, no timezone
 | 
				
			||||||
 | 
						timeFormatNoTimezone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// All below have some kind of timezone information, a name and/or offset.
 | 
				
			||||||
 | 
						timeFormatNamedTimezone
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// All below have what we consider to be solid timezone information.
 | 
				
			||||||
 | 
						timeFormatNumericAndNamedTimezone
 | 
				
			||||||
 | 
						timeFormatNumericTimezone
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type timeFormat struct {
 | 
				
			||||||
 | 
						format string
 | 
				
			||||||
 | 
						typ    timeFormatType
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f timeFormat) hasNumericTimezone() bool {
 | 
				
			||||||
 | 
						return f.typ >= timeFormatNumericAndNamedTimezone
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (f timeFormat) hasAnyTimezone() bool {
 | 
				
			||||||
 | 
						return f.typ >= timeFormatNamedTimezone
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						timeFormats = []timeFormat{
 | 
				
			||||||
 | 
							{time.RFC3339, timeFormatNumericTimezone},
 | 
				
			||||||
 | 
							{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
 | 
				
			||||||
 | 
							{time.RFC1123Z, timeFormatNumericTimezone},
 | 
				
			||||||
 | 
							{time.RFC1123, timeFormatNamedTimezone},
 | 
				
			||||||
 | 
							{time.RFC822Z, timeFormatNumericTimezone},
 | 
				
			||||||
 | 
							{time.RFC822, timeFormatNamedTimezone},
 | 
				
			||||||
 | 
							{time.RFC850, timeFormatNamedTimezone},
 | 
				
			||||||
 | 
							{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
 | 
				
			||||||
 | 
							{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone},                        // RFC3339 without timezone hh:mm colon
 | 
				
			||||||
 | 
							{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone},                        // RFC3339 without T or timezone hh:mm colon
 | 
				
			||||||
 | 
							{"2006-01-02 15:04:05", timeFormatNoTimezone},
 | 
				
			||||||
 | 
							{time.ANSIC, timeFormatNoTimezone},
 | 
				
			||||||
 | 
							// Must try RubyDate before UnixDate, see:
 | 
				
			||||||
 | 
							// https://github.com/golang/go/issues/32358
 | 
				
			||||||
 | 
							{time.RubyDate, timeFormatNumericTimezone},
 | 
				
			||||||
 | 
							{time.UnixDate, timeFormatNamedTimezone},
 | 
				
			||||||
 | 
							{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
 | 
				
			||||||
 | 
							{"2006-01-02", timeFormatShort},
 | 
				
			||||||
 | 
							{"02 Jan 2006", timeFormatShort},
 | 
				
			||||||
 | 
							{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
 | 
				
			||||||
 | 
							{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
 | 
				
			||||||
 | 
							{time.Kitchen, timeFormatShort},
 | 
				
			||||||
 | 
							{time.Stamp, timeFormatShort},
 | 
				
			||||||
 | 
							{time.StampMilli, timeFormatShort},
 | 
				
			||||||
 | 
							{time.StampMicro, timeFormatShort},
 | 
				
			||||||
 | 
							{time.StampNano, timeFormatShort},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// jsonStringToObject attempts to unmarshall a string as JSON into
 | 
					// jsonStringToObject attempts to unmarshall a string as JSON into
 | 
				
			||||||
// the object passed as pointer.
 | 
					// the object passed as pointer.
 | 
				
			||||||
func jsonStringToObject(s string, v interface{}) error {
 | 
					func jsonStringToObject(s string, v interface{}) error {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user