Skip to content

Commit 89f8aa2

Browse files
committed
datetime: fix interval arithmetic with timezones
Tarantool used to ignore timezone difference (offset) for a datetime interval calculations due to a bug [1]. We have to fix it too since we relied on the wrong behavior. 1. tarantool/tarantool#7698
1 parent 64e41c5 commit 89f8aa2

File tree

4 files changed

+25
-14
lines changed

4 files changed

+25
-14
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.
3535
- Decimal package use a test function GetNumberLength instead of a
3636
package-level function getNumberLength (#219)
3737
- Datetime location after encode + decode is unequal (#217)
38+
- Wrong interval arithmetic with timezones (#221)
3839

3940
## [1.8.0] - 2022-08-17
4041

datetime/config.lua

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,6 @@ local function call_interval_testdata(interval)
6666
end
6767
rawset(_G, 'call_interval_testdata', call_interval_testdata)
6868

69-
local function call_datetime_interval(dtleft, dtright)
70-
return dtright - dtleft
71-
end
72-
rawset(_G, 'call_datetime_interval', call_datetime_interval)
73-
7469
-- Set listen only when every other thing is configured.
7570
box.cfg{
7671
listen = os.getenv("TEST_TNT_LISTEN"),

datetime/datetime.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@ func (dtime *Datetime) Sub(ival Interval) (*Datetime, error) {
220220
func (dtime *Datetime) Interval(next *Datetime) Interval {
221221
curIval := intervalFromDatetime(dtime)
222222
nextIval := intervalFromDatetime(next)
223+
_, curOffset := dtime.time.Zone()
224+
_, nextOffset := next.time.Zone()
225+
curIval.Min -= int64(curOffset-nextOffset) / 60
223226
return nextIval.Sub(curIval)
224227
}
225228

datetime/datetime_test.go

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,8 @@ func TestDatetimeAddOutOfRange(t *testing.T) {
321321
}
322322

323323
func TestDatetimeInterval(t *testing.T) {
324-
var first = "2015-03-20T17:50:56.000000009Z"
325-
var second = "2013-01-31T17:51:56.000000009Z"
324+
var first = "2015-03-20T17:50:56.000000009+02:00"
325+
var second = "2013-01-31T11:51:58.00000009+01:00"
326326

327327
tmFirst, err := time.Parse(time.RFC3339, first)
328328
if err != nil {
@@ -345,14 +345,23 @@ func TestDatetimeInterval(t *testing.T) {
345345
ivalFirst := dtFirst.Interval(dtSecond)
346346
ivalSecond := dtSecond.Interval(dtFirst)
347347

348-
expectedFirst := Interval{-2, -2, 0, 11, 0, 1, 0, 0, NoneAdjust}
349-
expectedSecond := Interval{2, 2, 0, -11, 0, -1, 0, 0, NoneAdjust}
348+
expectedFirst := Interval{-2, -2, 0, 11, -6, 61, 2, 81, NoneAdjust}
349+
expectedSecond := Interval{2, 2, 0, -11, 6, -61, -2, -81, NoneAdjust}
350350

351351
if !reflect.DeepEqual(ivalFirst, expectedFirst) {
352352
t.Errorf("Unexpected interval %v, expected %v", ivalFirst, expectedFirst)
353353
}
354354
if !reflect.DeepEqual(ivalSecond, expectedSecond) {
355-
t.Errorf("Unexpected interval %v, expected %v", ivalFirst, expectedSecond)
355+
t.Errorf("Unexpected interval %v, expected %v", ivalSecond, expectedSecond)
356+
}
357+
358+
dtFirst, err = dtFirst.Add(ivalFirst)
359+
if err != nil {
360+
t.Fatalf("Unable to add an interval: %s", err)
361+
}
362+
if !dtFirst.ToTime().Equal(dtSecond.ToTime()) {
363+
t.Errorf("Incorrect add an interval result: %s, expected %s",
364+
dtFirst.ToTime(), dtSecond.ToTime())
356365
}
357366
}
358367

@@ -363,12 +372,15 @@ func TestDatetimeTarantoolInterval(t *testing.T) {
363372
defer conn.Close()
364373

365374
dates := []string{
366-
"2015-03-20T17:50:56.000000009+01:00",
375+
// We could return tests with timezones after fix of the bug:
376+
// https://github.com/tarantool/tarantool/issues/7698
377+
//
378+
// "2010-02-24T23:03:56.0000013-04:00",
379+
// "2015-03-20T17:50:56.000000009+01:00",
380+
// "2020-01-01T01:01:01+11:30",
381+
// "2025-08-01T00:00:00.000000003+11:00",
367382
"2015-12-21T17:50:53Z",
368-
"2010-02-24T23:03:56.0000013-04:00",
369383
"1980-03-28T13:18:39.000099Z",
370-
"2025-08-01T00:00:00.000000003+11:00",
371-
"2020-01-01T01:01:01+11:30",
372384
}
373385
datetimes := []*Datetime{}
374386
for _, date := range dates {

0 commit comments

Comments
 (0)