fix(oracle): preserve timezone-less datetime values

This commit is contained in:
t8y2 2026-07-23 19:03:50 +08:00
parent c6135d6bb2
commit 08e907c3db
2 changed files with 42 additions and 0 deletions

View File

@ -3628,6 +3628,10 @@ func normalizeValue(value any, columnTypeName string) any {
}
return string(v)
case time.Time:
// Oracle DATE and plain TIMESTAMP are wall-clock values; adding an offset makes clients shift them.
if isOracleTimezoneLessDateTime(columnTypeName) {
return v.Format("2006-01-02T15:04:05.999999999")
}
return v.Format(time.RFC3339Nano)
case int64, float64, bool, string:
return v
@ -3638,6 +3642,14 @@ func normalizeValue(value any, columnTypeName string) any {
}
}
func isOracleTimezoneLessDateTime(columnTypeName string) bool {
normalized := strings.ToUpper(strings.ReplaceAll(strings.TrimSpace(columnTypeName), " ", ""))
if normalized == "DATE" || normalized == "TIMESTAMPDTY" || normalized == "TIMESTAMP" {
return true
}
return strings.HasPrefix(normalized, "TIMESTAMP(") && strings.HasSuffix(normalized, ")")
}
func isOracleBinaryColumnType(columnTypeName string) bool {
normalized := strings.ToUpper(strings.ReplaceAll(strings.TrimSpace(columnTypeName), " ", ""))
switch normalized {

View File

@ -242,6 +242,36 @@ func TestNormalizeValueKeepsNonBinaryBytesAsText(t *testing.T) {
}
}
func TestNormalizeValueFormatsOracleTimezoneLessDateTimesAsWallClock(t *testing.T) {
value := time.Date(2026, time.July, 23, 13, 42, 13, 123456000, time.FixedZone("CST", 8*60*60))
tests := []string{
"DATE",
"TIMESTAMP",
"TIMESTAMP(6)",
"TimeStampDTY",
}
for _, columnType := range tests {
if got := normalizeValue(value, columnType); got != "2026-07-23T13:42:13.123456" {
t.Fatalf("normalizeValue time for %q = %#v, want wall-clock value", columnType, got)
}
}
}
func TestNormalizeValueKeepsOracleZonedDateTimeOffsets(t *testing.T) {
value := time.Date(2026, time.July, 23, 13, 42, 13, 123456000, time.FixedZone("CST", 8*60*60))
tests := []string{
"TimeStampTZ_DTY",
"TIMESTAMP WITH TIME ZONE",
}
for _, columnType := range tests {
if got := normalizeValue(value, columnType); got != "2026-07-23T13:42:13.123456+08:00" {
t.Fatalf("normalizeValue time for %q = %#v, want RFC3339 offset", columnType, got)
}
}
}
func TestNormalizeDDLObjectType(t *testing.T) {
tests := map[string]string{
"": "",