Implement UTCTime decoding
Remove LocalTime decoding because it requires IO to convert from Postgres time.
This commit is contained in:
@@ -19,8 +19,8 @@ import Data.Proxy (Proxy (..))
|
||||
import Data.Time
|
||||
( Day (..)
|
||||
, DiffTime
|
||||
, LocalTime (..)
|
||||
, TimeOfDay
|
||||
, UTCTime (..)
|
||||
, addDays
|
||||
, fromGregorian
|
||||
, picosecondsToDiffTime
|
||||
@@ -171,23 +171,20 @@ instance FromField TimeOfDay where
|
||||
validOid Proxy = Oid.time
|
||||
parseField = timeToTimeOfDay <$> parseField @DiffTime
|
||||
|
||||
fromPostgresTimestamp :: Int -> (Day, DiffTime)
|
||||
fromPostgresTimestamp ts = (day, time)
|
||||
where
|
||||
(days, microseconds) = ts `divMod` (86400 * 1000000)
|
||||
day = fromPostgresJulian $ fromIntegral days
|
||||
time = picosecondsToDiffTime $ fromIntegral microseconds * 1000000
|
||||
|
||||
-- | See https://www.postgresql.org/docs/current/datatype-datetime.html.
|
||||
-- | Accepts @timestamp@.
|
||||
-- Note that Postgres uses the proleptic Gregorian calendar, whereas @Show Day@ and @fromGregorian@ use an astronomical calendar.
|
||||
-- In short, Postgres treats 1 BC as a leap year and doesn't have a year zero.
|
||||
-- This means that working with negative dates will be different in Postgres and your application code.
|
||||
instance FromField LocalTime where
|
||||
validOid Proxy = Oid.timestamp
|
||||
parseField = fromPostgresTimestamp <$> readBigEndian @Int <$> AP.takeByteString
|
||||
-- Accepts @timestamp with timezone@.
|
||||
instance FromField UTCTime where
|
||||
validOid Proxy = Oid.timestampWithTimezone
|
||||
parseField = toUTCTime . fromPostgresTimestamp <$> readBigEndian @Int <$> AP.takeByteString
|
||||
where
|
||||
fromPostgresTimestamp :: Int -> LocalTime
|
||||
fromPostgresTimestamp ts =
|
||||
let
|
||||
(days, microseconds) = ts `divMod` (86400 * 1000000)
|
||||
day = fromPostgresJulian $ fromIntegral days
|
||||
time = picosecondsToDiffTime $ fromIntegral microseconds * 1000000
|
||||
in
|
||||
LocalTime day (timeToTimeOfDay time)
|
||||
toUTCTime (day, time) = UTCTime day time
|
||||
|
||||
newtype RawField a = RawField a
|
||||
deriving (Eq, Show)
|
||||
|
||||
@@ -60,3 +60,7 @@ time = eq $ Oid 1083
|
||||
-- | A point in time.
|
||||
timestamp :: Oid -> Bool
|
||||
timestamp = eq $ Oid 1114
|
||||
|
||||
-- | A point in time.
|
||||
timestampWithTimezone :: Oid -> Bool
|
||||
timestampWithTimezone = eq $ Oid 1184
|
||||
|
||||
Reference in New Issue
Block a user