module PostgreSQLBinary.Time where import PostgreSQLBinary.Prelude import Data.Time.Calendar.Julian type YMD = (Integer, Int, Int) {-# INLINE dayToJulianYMD #-} dayToJulianYMD :: Day -> YMD dayToJulianYMD = toJulian {-# INLINE dayToGregorianYMD #-} dayToGregorianYMD :: Day -> YMD dayToGregorianYMD = toGregorian {-# INLINABLE ymdToInt #-} ymdToInt :: YMD -> Int ymdToInt (y, m, d) = let (m', y') = if m > 2 then (m + 1, fromIntegral $ y + 4800) else (m + 13, fromIntegral $ y + 4799) century = y' `div` 100 in y' * 365 - 32167 + y' `div` 4 - century + century `div` 4 + 7834 * m' `div` 256 + d {-# INLINABLE dayToPostgresJulian #-} dayToPostgresJulian :: Day -> Integer dayToPostgresJulian = (+ (2400001 - 2451545)) . toModifiedJulianDay {-# INLINABLE postgresJulianToDay #-} postgresJulianToDay :: Int -> Day postgresJulianToDay = ModifiedJulianDay . fromIntegral . subtract (2400001 - 2451545) {-# INLINABLE microsToTimeOfDay #-} microsToTimeOfDay :: Int -> TimeOfDay microsToTimeOfDay = evalState $ do h <- state $ flip divMod (10 ^ 6 * 60 * 60) m <- state $ flip divMod (10 ^ 6 * 60) u <- get let p = fromIntegral u * 10 ^ 6 :: Integer return $ TimeOfDay h m (unsafeCoerce p) {-# INLINABLE secondsToTimeOfDay #-} secondsToTimeOfDay :: Double -> TimeOfDay secondsToTimeOfDay = evalState $ do h <- state $ flip divMod' (60 * 60) m <- state $ flip divMod' (60) s <- get let p = truncate $ toRational s * 10 ^ 12 :: Integer return $ TimeOfDay h m (unsafeCoerce p)