Skip to content

Commit

Permalink
Update format when casting datetimes to strings
Browse files Browse the repository at this point in the history
  • Loading branch information
colincadams authored and ohaibbq committed Jan 23, 2024
1 parent 7d3a82f commit 4c3b3f5
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 4 deletions.
28 changes: 27 additions & 1 deletion internal/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,25 @@ func CastValue(t types.Type, v Value) (Value, error) {
return nil, err
}
return FloatValue(f64), nil
case types.STRING, types.ENUM:
case types.STRING:
switch v.(type) {
// If this is coming from a date/time, the format is slightly different
// than when just writing the value out as a string.
case DateValue:
return convertTimeValueToStringWithFormat(v, "2006-01-02")
case DatetimeValue:
return convertTimeValueToStringWithFormat(v, "2006-01-02 15:04:05.999999")
case TimeValue:
return convertTimeValueToStringWithFormat(v, "15:04:05.999999")
case TimestampValue:
return convertTimeValueToStringWithFormat(v, "2006-01-02 15:04:05.999999-07")
}
s, err := v.ToString()
if err != nil {
return nil, err
}
return StringValue(s), nil
case types.ENUM:
s, err := v.ToString()
if err != nil {
return nil, err
Expand Down Expand Up @@ -507,6 +525,14 @@ func CastValue(t types.Type, v Value) (Value, error) {
return nil, fmt.Errorf("unsupported cast %s value", t.Kind())
}

func convertTimeValueToStringWithFormat(v Value, format string) (Value, error) {
valueTime, err := v.ToTime()
if err != nil {
return nil, err
}
return StringValue(valueTime.UTC().Format(format)), nil
}

func ValueFromGoValue(v interface{}) (Value, error) {
if isNullValue(v) {
return nil, nil
Expand Down
2 changes: 1 addition & 1 deletion internal/function_datetime.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func DATETIME(args ...Value) (Value, error) {
}
return DatetimeValue(t.In(loc)), nil
}
return DatetimeValue(t), nil
return DatetimeValue(t.UTC()), nil
}
return nil, fmt.Errorf("DATETIME: first argument must be DATE or TIMESTAMP type")
}
Expand Down
4 changes: 2 additions & 2 deletions internal/function_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@ func TIME(args ...Value) (Value, error) {
}
return TimeValue(t.In(loc)), nil
}
return TimeValue(t), nil
return TimeValue(t.UTC()), nil
case DatetimeValue:
t, err := args[0].ToTime()
if err != nil {
return nil, err
}
return TimeValue(t), nil
return TimeValue(t.UTC()), nil
}
return nil, fmt.Errorf("TIME: invalid first argument type %T", args[0])
}
Expand Down
36 changes: 36 additions & 0 deletions query_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3706,6 +3706,12 @@ SELECT date, EXTRACT(ISOYEAR FROM date), EXTRACT(YEAR FROM date), EXTRACT(MONTH
expectedRows: [][]interface{}{{"2008"}},
},

{
name: "cast date as string",
query: `SELECT CAST(DATE("2022-08-01 06:47:51.123456-07:00") AS STRING)`,
expectedRows: [][]interface{}{{"2022-08-01"}},
},

{
name: "last_day",
query: `SELECT LAST_DAY(DATE '2008-11-25') AS last_day`,
Expand Down Expand Up @@ -3876,6 +3882,16 @@ SELECT date, EXTRACT(ISOYEAR FROM date), EXTRACT(YEAR FROM date), EXTRACT(MONTH
query: `SELECT FORMAT_DATETIME("%E4Y", DATETIME "2008-12-25 15:30:12.345678")`,
expectedRows: [][]interface{}{{"2008"}},
},
{
name: "cast datetime as string",
query: `SELECT CAST(DATETIME(TIMESTAMP("2022-08-01 06:47:51.123456-07:00")) AS STRING)`,
expectedRows: [][]interface{}{{"2022-08-01 13:47:51.123456"}},
},
{
name: "cast date as datetime",
query: `SELECT CAST(DATE("1987-01-25") AS DATETIME)`,
expectedRows: [][]interface{}{{"1987-01-25T00:00:00"}},
},
{
name: "parse datetime",
query: `SELECT PARSE_DATETIME("%a %b %e %I:%M:%S %Y", "Thu Dec 25 07:30:00 2008")`,
Expand Down Expand Up @@ -3952,6 +3968,21 @@ SELECT date, EXTRACT(ISOYEAR FROM date), EXTRACT(YEAR FROM date), EXTRACT(MONTH
query: `SELECT FORMAT_TIME("%E*S", TIME "15:30:12.345678")`,
expectedRows: [][]interface{}{{"12.345678"}},
},
{
name: "cast time as string",
query: `SELECT CAST(TIME("2022-08-01 06:47:51.123456-04:00") AS STRING)`,
expectedRows: [][]interface{}{{"10:47:51.123456"}},
},
{
name: "cast time with timezone as string",
query: `SELECT CAST(TIME("2022-08-01 06:47:51.123456-04:00", "America/Los_Angeles") AS STRING)`,
expectedRows: [][]interface{}{{"03:47:51.123456"}},
},
{
name: "cast time from datetime as string",
query: `SELECT CAST(TIME(DATETIME(TIMESTAMP("2022-08-01 06:47:51.123456-04:00"))) AS STRING)`,
expectedRows: [][]interface{}{{"10:47:51.123456"}},
},
{
name: "parse time with %I:%M:%S",
query: `SELECT PARSE_TIME("%I:%M:%S", "07:30:00")`,
Expand Down Expand Up @@ -4094,6 +4125,11 @@ SELECT date, EXTRACT(ISOYEAR FROM date), EXTRACT(YEAR FROM date), EXTRACT(MONTH
query: `SELECT FORMAT_TIMESTAMP("%Ez", TIMESTAMP "2008-12-25 15:30:12.345678+00")`,
expectedRows: [][]interface{}{{"+00:00"}},
},
{
name: "cast timestamp as string",
query: `SELECT CAST(TIMESTAMP("2022-08-01 06:47:51.123456-07:00") AS STRING);`,
expectedRows: [][]interface{}{{"2022-08-01 13:47:51.123456+00"}},
},
{
name: "parse timestamp with %a %b %e %I:%M:%S %Y",
query: `SELECT PARSE_TIMESTAMP("%a %b %e %I:%M:%S %Y", "Thu Dec 25 07:30:00 2008")`,
Expand Down

0 comments on commit 4c3b3f5

Please sign in to comment.