Skip to content

Commit

Permalink
types: Make use of the new time.ZoneBounds function in go-1.19 (pingc…
Browse files Browse the repository at this point in the history
  • Loading branch information
mjonss authored Nov 10, 2022
1 parent 9761e67 commit 7f9219c
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 81 deletions.
51 changes: 11 additions & 40 deletions types/core_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,42 +184,6 @@ func (t CoreTime) GoTime(loc *gotime.Location) (gotime.Time, error) {
return tm, nil
}

// FindZoneTransition check for one Time Zone transition within +/- 4h
// Currently the needed functions are not exported, if gotime.Location.lookup would be exported
// then it would be easy to use that directly
func FindZoneTransition(tIn gotime.Time) (gotime.Time, error) {
// Check most common case first, DST transition on full hour.
// round truncates away from zero!
t2 := tIn.Round(gotime.Hour).Add(-1 * gotime.Hour)
t1 := t2.Add(-1 * gotime.Second)
_, offset1 := t1.Zone()
_, offset2 := t2.Zone()
if offset1 != offset2 {
return t2, nil
}

// Check if any offset change?
t1 = tIn.Add(-4 * gotime.Hour)
t2 = tIn.Add(4 * gotime.Hour)
_, offset1 = t1.Zone()
_, offset2 = t2.Zone()
if offset1 == offset2 {
return tIn, errors.Trace(ErrWrongValue.GenWithStackByArgs(TimeStr, tIn))
}

// Check generic case, like for 'Australia/Lord_Howe'
for t2.After(t1.Add(gotime.Second)) {
t := t1.Add(t2.Sub(t1) / 2).Round(gotime.Second)
_, offset := t.Zone()
if offset == offset1 {
t1 = t
} else {
t2 = t
}
}
return t2, nil
}

// AdjustedGoTime converts Time to GoTime and adjust for invalid DST times
// like during the DST change with increased offset,
// normally moving to Daylight Saving Time.
Expand All @@ -230,11 +194,18 @@ func (t CoreTime) AdjustedGoTime(loc *gotime.Location) (gotime.Time, error) {
return tm, nil
}

tAdj, err2 := FindZoneTransition(tm)
if err2 == nil {
return tAdj, nil
// The converted go time did not map back to the same time, probably it was between a
// daylight saving transition, adjust the time to the closest Zone bound.
start, end := tm.ZoneBounds()
// time zone transitions are normally 1 hour, allow up to 4 hours before returning error
if start.Sub(tm).Abs().Hours() > 4.0 && end.Sub(tm).Abs().Hours() > 4.0 {
return tm, errors.Trace(ErrWrongValue.GenWithStackByArgs(TimeStr, tm))
}
// use the closest transition time
if tm.Sub(start).Abs() <= tm.Sub(end).Abs() {
return start, nil
}
return tm, err
return end, nil
}

// IsLeapYear returns if it's leap year.
Expand Down
43 changes: 2 additions & 41 deletions types/core_time_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,45 +293,6 @@ func TestWeekday(t *testing.T) {
}
}

func TestFindZoneTransition(t *testing.T) {
tests := []struct {
TZ string
dt string
Expect string
Success bool
}{
{"Australia/Lord_Howe", "2020-06-29 03:45:00", "", false},
{"Australia/Lord_Howe", "2020-10-04 02:15:00", "2020-10-04 02:30:00 +11 +1100", true},
{"Australia/Lord_Howe", "2020-10-04 02:29:59", "2020-10-04 02:30:00 +11 +1100", true},
{"Australia/Lord_Howe", "2020-10-04 02:29:59.99", "2020-10-04 02:30:00 +11 +1100", true},
{"Australia/Lord_Howe", "2020-10-04 02:30:00.0001", "2020-10-04 02:30:00 +11 +1100", true},
{"Australia/Lord_Howe", "2020-10-04 02:30:00", "2020-10-04 02:30:00 +11 +1100", true},
{"Australia/Lord_Howe", "2020-10-04 02:30:01", "2020-10-04 02:30:00 +11 +1100", true},
{"Europe/Vilnius", "2020-03-29 03:45:00", "2020-03-29 04:00:00 EEST +0300", true},
{"Europe/Vilnius", "2020-10-25 03:45:00", "2020-10-25 03:00:00 EET +0200", true},
{"Europe/Vilnius", "2020-06-29 03:45:00", "", false},
{"Europe/Amsterdam", "2020-03-29 02:45:00", "2020-03-29 03:00:00 CEST +0200", true},
{"Europe/Amsterdam", "2020-10-25 02:35:00", "2020-10-25 02:00:00 CET +0100", true},
{"Europe/Amsterdam", "2020-03-29 02:59:59", "2020-03-29 03:00:00 CEST +0200", true},
{"Europe/Amsterdam", "2020-03-29 02:59:59.999999999", "2020-03-29 03:00:00 CEST +0200", true},
{"Europe/Amsterdam", "2020-03-29 03:00:00.000000001", "2020-03-29 03:00:00 CEST +0200", true},
}

for _, tt := range tests {
loc, err := time.LoadLocation(tt.TZ)
require.NoError(t, err)
tm, err := time.ParseInLocation("2006-01-02 15:04:05", tt.dt, loc)
require.NoError(t, err)
tp, err := FindZoneTransition(tm)
if !tt.Success {
require.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, tt.Expect, tp.Format("2006-01-02 15:04:05.999999999 MST -0700"))
}
}
}

func TestAdjustedGoTime(t *testing.T) {
tests := []struct {
TZ string
Expand Down Expand Up @@ -361,9 +322,9 @@ func TestAdjustedGoTime(t *testing.T) {
require.NoError(t, err)
tp, err := tt.dt.AdjustedGoTime(loc)
if !tt.Success {
require.Error(t, err)
require.Error(t, err, tp.Format("2006-01-02 15:04:05.999999999 MST -0700"))
} else {
require.NoError(t, err)
require.NoError(t, err, tp.Format("2006-01-02 15:04:05.999999999 MST -0700"))
require.Equal(t, tt.Expect, tp.Format("2006-01-02 15:04:05.999999999 MST -0700"))
}
}
Expand Down

0 comments on commit 7f9219c

Please sign in to comment.