Skip to content

Commit

Permalink
cli: format time zones and floating points to match SQL
Browse files Browse the repository at this point in the history
Release note (cli change): The SQL shell now formats times with time
zones so that the minutes and seconds offsets are only shown if they are
non-zero. Also, infinite floating point values are formatted as
`Infinity` rather than `Inf` now.
  • Loading branch information
rafiss committed May 17, 2021
1 parent 0d1f701 commit c08ee66
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 11 deletions.
17 changes: 11 additions & 6 deletions pkg/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,9 @@ func Example_sql_format() {
c.RunWithArgs([]string{"sql", "-e", "create database t; create table t.times (bare timestamp, withtz timestamptz)"})
c.RunWithArgs([]string{"sql", "-e", "insert into t.times values ('2016-01-25 10:10:10', '2016-01-25 10:10:10-05:00')"})
c.RunWithArgs([]string{"sql", "-e", "select bare from t.times; select withtz from t.times"})
c.RunWithArgs([]string{"sql", "-e", "select '2021-03-20'::date; select '01:01'::time; select '01:01'::timetz"})
c.RunWithArgs([]string{"sql", "-e", "select (1/3.0)::real; select (1/3.0)::double precision"})
c.RunWithArgs([]string{"sql", "-e",
"select '2021-03-20'::date; select '01:01'::time; select '01:01'::timetz; select '01:01+02:02'::timetz"})
c.RunWithArgs([]string{"sql", "-e", "select (1/3.0)::real; select (1/3.0)::double precision; select '-inf'::float8"})

// Output:
// sql -e create database t; create table t.times (bare timestamp, withtz timestamptz)
Expand All @@ -299,19 +300,23 @@ func Example_sql_format() {
// bare
// 2016-01-25 10:10:10
// withtz
// 2016-01-25 15:10:10+00:00:00
// sql -e select '2021-03-20'::date; select '01:01'::time; select '01:01'::timetz
// 2016-01-25 15:10:10+00
// sql -e select '2021-03-20'::date; select '01:01'::time; select '01:01'::timetz; select '01:01+02:02'::timetz
// date
// 2021-03-20
// time
// 01:01:00
// timetz
// 01:01:00+00:00:00
// sql -e select (1/3.0)::real; select (1/3.0)::double precision
// 01:01:00+00
// timetz
// 01:01:00+02:02
// sql -e select (1/3.0)::real; select (1/3.0)::double precision; select '-inf'::float8
// float4
// 0.33333334
// float8
// 0.3333333333333333
// float8
// -Infinity
}

func Example_sql_column_labels() {
Expand Down
15 changes: 14 additions & 1 deletion pkg/cli/sql_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"database/sql/driver"
"fmt"
"io"
"math"
"net/url"
"reflect"
"strconv"
Expand Down Expand Up @@ -1134,6 +1135,11 @@ func formatVal(
if colType == "FLOAT4" {
width = 32
}
if math.IsInf(t, 1) {
return "Infinity"
} else if math.IsInf(t, -1) {
return "-Infinity"
}
return strconv.FormatFloat(t, 'g', -1, width)

case string:
Expand Down Expand Up @@ -1178,6 +1184,13 @@ func formatVal(
// Some unknown/new time-like format.
tfmt = timeutil.FullTimeFormat
}
if tfmt == timeutil.TimestampWithTZFormat || tfmt == timeutil.TimeWithTZFormat {
if _, offsetSeconds := t.Zone(); offsetSeconds%60 != 0 {
tfmt += ":00:00"
} else if offsetSeconds%3600 != 0 {
tfmt += ":00"
}
}
return t.Format(tfmt)
}

Expand All @@ -1186,7 +1199,7 @@ func formatVal(

var timeOutputFormats = map[string]string{
"TIMESTAMP": timeutil.TimestampWithoutTZFormat,
"TIMESTAMPTZ": timeutil.FullTimeFormat,
"TIMESTAMPTZ": timeutil.TimestampWithTZFormat,
"TIME": timeutil.TimeWithoutTZFormat,
"TIMETZ": timeutil.TimeWithTZFormat,
"DATE": timeutil.DateFormat,
Expand Down
14 changes: 10 additions & 4 deletions pkg/util/timeutil/timeutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,23 @@

package timeutil

// FullTimeFormat is the time format used to display any timestamp
// with date, time and time zone data.
// FullTimeFormat is the time format used to display any unknown timestamp
// type, and always shows the full time zone offset.
const FullTimeFormat = "2006-01-02 15:04:05.999999-07:00:00"

// TimestampWithTZFormat is the time format used to display
// timestamps with a time zone offset. The minutes and seconds
// offsets are only added if they are non-zero.
const TimestampWithTZFormat = "2006-01-02 15:04:05.999999-07"

// TimestampWithoutTZFormat is the time format used to display
// timestamps without a time zone offset.
// timestamps without a time zone offset. The minutes and seconds
// offsets are only added if they are non-zero.
const TimestampWithoutTZFormat = "2006-01-02 15:04:05.999999"

// TimeWithTZFormat is the time format used to display a time
// with a time zone offset.
const TimeWithTZFormat = "15:04:05.999999-07:00:00"
const TimeWithTZFormat = "15:04:05.999999-07"

// TimeWithoutTZFormat is the time format used to display a time
// without a time zone offset.
Expand Down

0 comments on commit c08ee66

Please sign in to comment.