-
Notifications
You must be signed in to change notification settings - Fork 7
Description
When you are dealing with binary formats, postgresql timestamp values (with or without time zone) just acts as a store of 8-byte values, independent of timezones:
$ ghci-7.6.3
GHCi, version 7.6.3: http://www.haskell.org/ghc/ :? for help
> import Database.PostgreSQL.LibPQ
> let showResult m = m >>= maybe (return Nothing) (\r -> getvalue r 0 0)
> c <- connectdb ""
> showResult $ exec c "show integer_datetimes"
Just "on"
> exec c "set timezone to 'utc'"
Just (Result 0x00007eff8c0092f0)
> showResult $ execParams c "select $1" [Just (Oid 1184, "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL", Binary)] Binary
Just "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL"
> showResult $ execParams c "select $1" [Just (Oid 1184, "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL", Binary)] Text
Just "2000-01-01 00:00:00+00"
> showResult $ execParams c "select $1" [Just (Oid 1184, "2000-01-01 00:00:00+00", Text)] Binary
Just "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL"
> showResult $ execParams c "select $1" [Just (Oid 1184, "1999-12-31 19:00:00-05", Text)] Binary
Just "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL"
> showResult $ execParams c "select $1 = $2" [Just (Oid 1184, "1999-12-31 19:00:00-05", Text), Just (Oid 1184, "2000-01-01 00:00:00+00", Text)] Text
Just "t"
> exec c "set timezone to 'America/New_York'"
Just (Result 0x00007eff940083b0)
> showResult $ execParams c "select $1" [Just (Oid 1184, "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL", Binary)] Binary
Just "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL"
> showResult $ execParams c "select $1" [Just (Oid 1184, "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL", Binary)] Text
Just "1999-12-31 19:00:00-05"
> showResult $ execParams c "select $1" [Just (Oid 1184, "2000-01-01 00:00:00+00", Text)] Binary
Just "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL"
> showResult $ execParams c "select $1" [Just (Oid 1184, "1999-12-31 19:00:00-05", Text)] Binary
Just "\NUL\NUL\NUL\NUL\NUL\NUL\NUL\NUL"
> showResult $ execParams c "select $1 = $2" [Just (Oid 1184, "1999-12-31 19:00:00-05", Text), Just (Oid 1184, "2000-01-01 00:00:00+00", Text)] Text
Just "t"
However, there's still a semantics to each of the types, and hasql-postgres
has the semantics precisely wrong:
> showResult $ execParams c "select $1" [Just (Oid 1114, "1999-12-31 19:00:00-05", Text)] Text
Just "1999-12-31 19:00:00"
> showResult $ execParams c "select $1" [Just (Oid 1114, "1999-12-31 19:00:00-05", Text)] Binary
Just "\255\255\255\251\207\GS\204\NUL"
> showResult $ execParams c "select $1 = $2" [Just (Oid 1114, "1999-12-31 19:00:00-05", Text), Just (Oid 1114, "2000-01-01 00:00:00+00", Text)] Text
Just "f"
Yeah, that doesn't look like a UTCTime
to me. When a backend is using the integer_datetime
format, a timestamptz
is an 8-byte signed integer of microseconds from 2000-01-01 00:00:00+00
, whereas a timestamp
is an 8-byte signed integer of microseconds from somewhere between 2000-01-01 00:00:00-24
and 2000-01-01 00:00:00+24
, and this ambiguity can only be resolved in some larger context.
In short, UTCTime
really should map to timestamp with time zone
, whereas LocalTime
really should map to timestamp
. And, in the vast majority of circumstances, timestamp with time zone
is the correct choice, and one should always include a offset from UTC when using textual formats, as postgresql-simple's ToField
instances for UTCTime
and ZonedTime
do.