{-# LANGUAGE NumericUnderscores #-}
module DataFrame.IO.Parquet.Time where
import Data.Time
import Data.Word
import DataFrame.IO.Parquet.Binary
int96ToUTCTime :: [Word8] -> UTCTime
int96ToUTCTime :: [Word8] -> UTCTime
int96ToUTCTime [Word8]
bytes
| [Word8] -> DayOfMonth
forall a. [a] -> DayOfMonth
forall (t :: * -> *) a. Foldable t => t a -> DayOfMonth
length [Word8]
bytes DayOfMonth -> DayOfMonth -> Bool
forall a. Eq a => a -> a -> Bool
/= DayOfMonth
12 = [Char] -> UTCTime
forall a. HasCallStack => [Char] -> a
error [Char]
"INT96 must be exactly 12 bytes"
| Bool
otherwise =
let ([Word8]
nanosBytes, [Word8]
julianBytes) = DayOfMonth -> [Word8] -> ([Word8], [Word8])
forall a. DayOfMonth -> [a] -> ([a], [a])
splitAt DayOfMonth
8 [Word8]
bytes
nanosSinceMidnight :: Word64
nanosSinceMidnight = [Word8] -> Word64
littleEndianWord64 [Word8]
nanosBytes
julianDay :: Word32
julianDay = [Word8] -> Word32
littleEndianWord32 [Word8]
julianBytes
in Integer -> Word64 -> UTCTime
julianDayAndNanosToUTCTime (Word32 -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word32
julianDay) Word64
nanosSinceMidnight
julianDayAndNanosToUTCTime :: Integer -> Word64 -> UTCTime
julianDayAndNanosToUTCTime :: Integer -> Word64 -> UTCTime
julianDayAndNanosToUTCTime Integer
julianDay Word64
nanosSinceMidnight =
let day :: Day
day = Integer -> Day
julianDayToDay Integer
julianDay
secondsSinceMidnight :: Double
secondsSinceMidnight = Word64 -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
nanosSinceMidnight Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
1_000_000_000
diffTime :: DiffTime
diffTime = Integer -> DiffTime
secondsToDiffTime (Double -> Integer
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor Double
secondsSinceMidnight)
in Day -> DiffTime -> UTCTime
UTCTime Day
day DiffTime
diffTime
julianDayToDay :: Integer -> Day
julianDayToDay :: Integer -> Day
julianDayToDay Integer
julianDay =
let a :: Integer
a = Integer
julianDay Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
32_044
b :: Integer
b = (Integer
4 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
3) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
146_097
c :: Integer
c = Integer
a Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- (Integer
146_097 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
b) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
4
d :: Integer
d = (Integer
4 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
c Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
3) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
1461
e :: Integer
e = Integer
c Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- (Integer
1461 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
d) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
4
m :: Integer
m = (Integer
5 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
e Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
2) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
153
day :: Integer
day = Integer
e Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- (Integer
153 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
m Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
2) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
5 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
1
month :: Integer
month = Integer
m Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
3 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
12 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* (Integer
m Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
10)
year :: Integer
year = Integer
100 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
b Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
d Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
4800 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
m Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
10
in Integer -> DayOfMonth -> DayOfMonth -> Day
fromGregorian Integer
year (Integer -> DayOfMonth
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
month) (Integer -> DayOfMonth
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
day)
utcTimeToInt96 :: UTCTime -> [Word8]
utcTimeToInt96 :: UTCTime -> [Word8]
utcTimeToInt96 (UTCTime Day
day DiffTime
diffTime) =
let julianDay :: Integer
julianDay = Day -> Integer
dayToJulianDay Day
day
nanosSinceMidnight :: Word64
nanosSinceMidnight = Double -> Word64
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
floor (DiffTime -> Double
forall a b. (Real a, Fractional b) => a -> b
realToFrac DiffTime
diffTime Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
1_000_000_000)
nanosBytes :: [Word8]
nanosBytes = Word64 -> [Word8]
word64ToLittleEndian Word64
nanosSinceMidnight
julianBytes :: [Word8]
julianBytes = Word32 -> [Word8]
word32ToLittleEndian (Integer -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
julianDay)
in [Word8]
nanosBytes [Word8] -> [Word8] -> [Word8]
forall a. [a] -> [a] -> [a]
++ [Word8]
julianBytes
dayToJulianDay :: Day -> Integer
dayToJulianDay :: Day -> Integer
dayToJulianDay Day
day =
let (Integer
year, DayOfMonth
month, DayOfMonth
dayOfMonth) = Day -> (Integer, DayOfMonth, DayOfMonth)
toGregorian Day
day
a :: Integer
a = Integer -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Integer) -> Integer -> Integer
forall a b. (a -> b) -> a -> b
$ (Integer
14 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- DayOfMonth -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral DayOfMonth
month) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
12
y :: Integer
y = Integer -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Integer -> Integer) -> Integer -> Integer
forall a b. (a -> b) -> a -> b
$ Integer
year Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
4800 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
a
m :: Integer
m = DayOfMonth -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral (DayOfMonth -> Integer) -> DayOfMonth -> Integer
forall a b. (a -> b) -> a -> b
$ DayOfMonth
month DayOfMonth -> DayOfMonth -> DayOfMonth
forall a. Num a => a -> a -> a
+ DayOfMonth
12 DayOfMonth -> DayOfMonth -> DayOfMonth
forall a. Num a => a -> a -> a
* Integer -> DayOfMonth
forall a b. (Integral a, Num b) => a -> b
fromIntegral Integer
a DayOfMonth -> DayOfMonth -> DayOfMonth
forall a. Num a => a -> a -> a
- DayOfMonth
3
in DayOfMonth -> Integer
forall a b. (Integral a, Num b) => a -> b
fromIntegral DayOfMonth
dayOfMonth
Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ (Integer
153 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
m Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
2) Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
5
Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
365 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
y
Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
y Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
4
Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
y Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
100
Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
y Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
400
Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
32_045