Skip to content

Commit a42c3e4

Browse files
authored
Merge pull request #2503 from dolthub/daylon/dst
Fixed DST handling by moving to `timeofday`
2 parents bd0686c + a1ee1ca commit a42c3e4

28 files changed

Lines changed: 182 additions & 133 deletions

postgres/parser/timeofday/time_of_day.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,22 @@ func (t TimeOfDay) Add(d duration.Duration) TimeOfDay {
139139
return FromInt(int64(t) + d.Nanos()/nanosPerMicro)
140140
}
141141

142+
// Sub subtracts a Duration to a TimeOfDay, wrapping into the previous day if necessary.
143+
func (t TimeOfDay) Sub(d duration.Duration) TimeOfDay {
144+
return FromInt(int64(t) - d.Nanos()/nanosPerMicro)
145+
}
146+
147+
// Compare compares the calling TimeOfDay with the given one, returning a comparison integer.
148+
func (t TimeOfDay) Compare(other TimeOfDay) int {
149+
if t < other {
150+
return -1
151+
} else if t == other {
152+
return 0
153+
} else {
154+
return 1
155+
}
156+
}
157+
142158
// Difference returns the interval between t1 and t2, which may be negative.
143159
func Difference(t1 TimeOfDay, t2 TimeOfDay) duration.Duration {
144160
return duration.MakeDuration(int64(t1-t2)*nanosPerMicro, 0, 0)

postgres/parser/timetz/timetz.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ func (t TimeTZ) Before(other TimeTZ) bool {
215215
}
216216

217217
// After returns whether the TimeTZ is after the other TimeTZ.
218-
func (t *TimeTZ) After(other TimeTZ) bool {
218+
func (t TimeTZ) After(other TimeTZ) bool {
219219
return t.ToTime().After(other.ToTime()) || (t.ToTime().Equal(other.ToTime()) && t.OffsetSecs > other.OffsetSecs)
220220
}
221221

@@ -224,6 +224,17 @@ func (t TimeTZ) Equal(other TimeTZ) bool {
224224
return t.TimeOfDay == other.TimeOfDay && t.OffsetSecs == other.OffsetSecs
225225
}
226226

227+
// Compare compares the calling TimeTZ with the given one, returning a comparison integer.
228+
func (t TimeTZ) Compare(other TimeTZ) int {
229+
if t.Before(other) {
230+
return -1
231+
} else if t.After(other) {
232+
return 1
233+
} else {
234+
return 0
235+
}
236+
}
237+
227238
// ReplaceLibPQTimePrefix replaces unparsable lib/pq dates used for timestamps
228239
// (0000-01-01) with timestamps that can be parsed by date libraries.
229240
func ReplaceLibPQTimePrefix(s string) string {

server/ast/expr.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -568,11 +568,11 @@ func nodeExpr(ctx *Context, node tree.Expr) (vitess.Expr, error) {
568568
}, nil
569569
case *tree.DTime:
570570
return vitess.InjectedExpr{
571-
Expression: pgexprs.NewRawLiteralTime(timeofday.TimeOfDay(*node).ToTime()),
571+
Expression: pgexprs.NewRawLiteralTime(timeofday.TimeOfDay(*node)),
572572
}, nil
573573
case *tree.DTimeTZ:
574574
return vitess.InjectedExpr{
575-
Expression: pgexprs.NewRawLiteralTimeTZ(node.TimeTZ.ToTime()),
575+
Expression: pgexprs.NewRawLiteralTimeTZ(node.TimeTZ),
576576
}, nil
577577
case *tree.DTimestamp:
578578
return vitess.InjectedExpr{

server/cast/interval.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func intervalAssignment() {
3939
Function: func(ctx *sql.Context, val any, targetType *pgtypes.DoltgresType) (any, error) {
4040
dur := val.(duration.Duration)
4141
// the month and day of the duration are excluded
42-
return timeofday.FromInt(dur.Nanos() / functions.NanosPerMicro).ToTime(), nil
42+
return timeofday.FromInt(dur.Nanos() / functions.NanosPerMicro), nil
4343
},
4444
})
4545
}

server/cast/time.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
package cast
1616

1717
import (
18-
"time"
19-
2018
"github.com/dolthub/go-mysql-server/sql"
2119

20+
"github.com/dolthub/doltgresql/postgres/parser/timeofday"
21+
2222
"github.com/dolthub/doltgresql/server/functions"
2323
"github.com/dolthub/doltgresql/server/functions/framework"
2424
pgtypes "github.com/dolthub/doltgresql/server/types"
@@ -35,8 +35,8 @@ func timeImplicit() {
3535
FromType: pgtypes.Time,
3636
ToType: pgtypes.Interval,
3737
Function: func(ctx *sql.Context, val any, targetType *pgtypes.DoltgresType) (any, error) {
38-
t := val.(time.Time)
39-
dur := functions.GetIntervalDurationFromTimeComponents(0, 0, 0, int64(t.Hour()), int64(t.Minute()), int64(t.Second()), 0)
38+
t := val.(timeofday.TimeOfDay)
39+
dur := functions.GetIntervalDurationFromTimeComponents(0, 0, 0, int64(t.Hour()), int64(t.Minute()), int64(t.Second()), int64(t.Microsecond())*1000)
4040
return dur, nil
4141
},
4242
})

server/cast/timestamp.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func timestampAssignment() {
4848
FromType: pgtypes.Timestamp,
4949
ToType: pgtypes.Time,
5050
Function: func(ctx *sql.Context, val any, targetType *pgtypes.DoltgresType) (any, error) {
51-
return timeofday.FromTime(val.(time.Time)).ToTime(), nil
51+
return timeofday.FromTime(val.(time.Time)), nil
5252
},
5353
})
5454
}

server/cast/timestamptz.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/dolthub/doltgresql/postgres/parser/pgdate"
2323
"github.com/dolthub/doltgresql/postgres/parser/timeofday"
24+
"github.com/dolthub/doltgresql/postgres/parser/timetz"
2425
"github.com/dolthub/doltgresql/server/functions/framework"
2526
pgtypes "github.com/dolthub/doltgresql/server/types"
2627
)
@@ -48,7 +49,7 @@ func timestampTZAssignment() {
4849
FromType: pgtypes.TimestampTZ,
4950
ToType: pgtypes.Time,
5051
Function: func(ctx *sql.Context, val any, targetType *pgtypes.DoltgresType) (any, error) {
51-
return timeofday.FromTime(val.(time.Time)).ToTime(), nil
52+
return timeofday.FromTime(val.(time.Time)), nil
5253
},
5354
})
5455
framework.MustAddAssignmentTypeCast(framework.TypeCast{
@@ -63,7 +64,7 @@ func timestampTZAssignment() {
6364
FromType: pgtypes.TimestampTZ,
6465
ToType: pgtypes.TimeTZ,
6566
Function: func(ctx *sql.Context, val any, targetType *pgtypes.DoltgresType) (any, error) {
66-
return val.(time.Time), nil
67+
return timetz.MakeTimeTZFromTime(val.(time.Time)), nil
6768
},
6869
})
6970
}

server/cast/timetz.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@
1515
package cast
1616

1717
import (
18-
"time"
19-
2018
"github.com/dolthub/go-mysql-server/sql"
2119

20+
"github.com/dolthub/doltgresql/postgres/parser/timetz"
21+
2222
"github.com/dolthub/doltgresql/server/functions/framework"
2323
pgtypes "github.com/dolthub/doltgresql/server/types"
2424
)
@@ -35,7 +35,7 @@ func timeTZAssignment() {
3535
FromType: pgtypes.TimeTZ,
3636
ToType: pgtypes.Time,
3737
Function: func(ctx *sql.Context, val any, targetType *pgtypes.DoltgresType) (any, error) {
38-
return val.(time.Time), nil
38+
return val.(timetz.TimeTZ).TimeOfDay, nil
3939
},
4040
})
4141
}
@@ -46,7 +46,7 @@ func timeTZImplicit() {
4646
FromType: pgtypes.TimeTZ,
4747
ToType: pgtypes.TimeTZ,
4848
Function: func(ctx *sql.Context, val any, targetType *pgtypes.DoltgresType) (any, error) {
49-
return val.(time.Time), nil
49+
return val.(timetz.TimeTZ), nil
5050
},
5151
})
5252
}

server/expression/literal.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import (
2424

2525
"github.com/dolthub/doltgresql/core/id"
2626
"github.com/dolthub/doltgresql/postgres/parser/duration"
27+
"github.com/dolthub/doltgresql/postgres/parser/timeofday"
28+
"github.com/dolthub/doltgresql/postgres/parser/timetz"
2729
"github.com/dolthub/doltgresql/postgres/parser/uuid"
2830
pgtypes "github.com/dolthub/doltgresql/server/types"
2931
)
@@ -113,12 +115,12 @@ func NewRawLiteralDate(date time.Time) *expression.Literal {
113115
}
114116

115117
// NewRawLiteralTime returns a new *expression.Literal containing a TIME value.
116-
func NewRawLiteralTime(t time.Time) *expression.Literal {
118+
func NewRawLiteralTime(t timeofday.TimeOfDay) *expression.Literal {
117119
return expression.NewLiteral(t, pgtypes.Time)
118120
}
119121

120122
// NewRawLiteralTimeTZ returns a new *expression.Literal containing a TIMETZ value.
121-
func NewRawLiteralTimeTZ(ttz time.Time) *expression.Literal {
123+
func NewRawLiteralTimeTZ(ttz timetz.TimeTZ) *expression.Literal {
122124
return expression.NewLiteral(ttz, pgtypes.TimeTZ)
123125
}
124126

server/functions/binary/equal.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import (
2222

2323
"github.com/dolthub/doltgresql/core/id"
2424
"github.com/dolthub/doltgresql/postgres/parser/duration"
25+
"github.com/dolthub/doltgresql/postgres/parser/timeofday"
26+
"github.com/dolthub/doltgresql/postgres/parser/timetz"
2527
"github.com/dolthub/doltgresql/postgres/parser/uuid"
2628
"github.com/dolthub/doltgresql/server/compare"
2729
"github.com/dolthub/doltgresql/server/functions/framework"
@@ -572,7 +574,7 @@ var record_eq = framework.Function2{
572574

573575
// time_eq_callable is the callable logic for the time_eq function.
574576
func time_eq_callable(ctx *sql.Context, _ [3]*pgtypes.DoltgresType, val1 any, val2 any) (any, error) {
575-
res, err := pgtypes.Time.Compare(ctx, val1.(time.Time), val2.(time.Time))
577+
res, err := pgtypes.Time.Compare(ctx, val1.(timeofday.TimeOfDay), val2.(timeofday.TimeOfDay))
576578
return res == 0, err
577579
}
578580

@@ -677,7 +679,7 @@ var timestamptz_eq = framework.Function2{
677679

678680
// timetz_eq_callable is the callable logic for the timetz_eq function.
679681
func timetz_eq_callable(ctx *sql.Context, _ [3]*pgtypes.DoltgresType, val1 any, val2 any) (any, error) {
680-
res, err := pgtypes.TimeTZ.Compare(ctx, val1.(time.Time), val2.(time.Time))
682+
res, err := pgtypes.TimeTZ.Compare(ctx, val1.(timetz.TimeTZ), val2.(timetz.TimeTZ))
681683
return res == 0, err
682684
}
683685

0 commit comments

Comments
 (0)