diff --git a/go/mysql/datetime/datetime.go b/go/mysql/datetime/datetime.go index 162ac970e67..cc1fc92e091 100644 --- a/go/mysql/datetime/datetime.go +++ b/go/mysql/datetime/datetime.go @@ -244,12 +244,12 @@ func (d Date) Hash(h *vthash.Hasher) { h.Write8(d.day) } -func (dt Date) Weekday() time.Weekday { - return dt.ToStdTime(time.Local).Weekday() +func (d Date) Weekday() time.Weekday { + return d.ToStdTime(time.Local).Weekday() } -func (dt Date) Yearday() int { - return dt.ToStdTime(time.Local).YearDay() +func (d Date) Yearday() int { + return d.ToStdTime(time.Local).YearDay() } func (d Date) ISOWeek() (int, int) { @@ -406,7 +406,19 @@ func (t Time) ToDuration() time.Duration { } func (t Time) toStdTime(year int, month time.Month, day int, loc *time.Location) (out time.Time) { - return time.Date(year, month, day, 0, 0, 0, 0, loc).Add(t.ToDuration()) + hours := t.Hour() + minutes := t.Minute() + secs := t.Second() + nsecs := t.Nanosecond() + + if t.Neg() { + hours = -hours + minutes = -minutes + secs = -secs + nsecs = -nsecs + } + + return time.Date(year, month, day, hours, minutes, secs, nsecs, loc) } func (t Time) ToStdTime(loc *time.Location) (out time.Time) { diff --git a/go/mysql/datetime/time_zone_test.go b/go/mysql/datetime/time_zone_test.go index 94745d0c71e..4bd1572755f 100644 --- a/go/mysql/datetime/time_zone_test.go +++ b/go/mysql/datetime/time_zone_test.go @@ -18,10 +18,50 @@ package datetime import ( "testing" + "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) +func TestDST(t *testing.T) { + testCases := []struct { + time Time + year int + month time.Month + day int + tz string + expected string + }{ + { + time: Time{hour: 130, minute: 34, second: 58}, + year: 2023, month: 10, day: 24, + tz: "Europe/Madrid", + expected: "2023-10-29T10:34:58+01:00", + }, + { + time: Time{hour: 130, minute: 34, second: 58}, + year: 2023, month: 10, day: 29, + tz: "Europe/Madrid", + expected: "2023-11-03T10:34:58+01:00", + }, + { + time: Time{hour: 130 | negMask, minute: 34, second: 58}, + year: 2023, month: 11, day: 03, + tz: "Europe/Madrid", + expected: "2023-10-28T13:25:02+02:00", + }, + } + + for _, tc := range testCases { + tz, err := ParseTimeZone(tc.tz) + require.NoError(t, err) + + got := tc.time.toStdTime(tc.year, tc.month, tc.day, tz) + assert.Equal(t, tc.expected, got.Format(time.RFC3339)) + } +} + func TestParseTimeZone(t *testing.T) { testCases := []struct { tz string diff --git a/go/vt/vtgate/evalengine/compiler_asm.go b/go/vt/vtgate/evalengine/compiler_asm.go index 317423696db..105ee3f4721 100644 --- a/go/vt/vtgate/evalengine/compiler_asm.go +++ b/go/vt/vtgate/evalengine/compiler_asm.go @@ -2042,6 +2042,7 @@ func (asm *assembler) Fn_FROM_BASE64(t sqltypes.Type) { } str.tt = int16(t) str.bytes = decoded + str.col = collationBinary return 1 }, "FN FROM_BASE64 VARCHAR(SP-1)") } diff --git a/go/vt/vtgate/evalengine/fn_numeric.go b/go/vt/vtgate/evalengine/fn_numeric.go index fe8eeffb2c4..3802fbd5630 100644 --- a/go/vt/vtgate/evalengine/fn_numeric.go +++ b/go/vt/vtgate/evalengine/fn_numeric.go @@ -1549,7 +1549,7 @@ func (expr *builtinConv) compile(c *compiler) (ctype, error) { c.asm.Fn_CONV_bu(3, 2) } - col := defaultCoercionCollation(n.Col.Collation) + col := defaultCoercionCollation(expr.collate) c.asm.Fn_CONV_uc(t, col) c.asm.jumpDestination(skip)