{-# OPTIONS_GHC -fno-warn-orphans #-}
module Data.Binary.Instances.Time where

import Control.Monad       (liftM2, liftM3)
import Data.Binary         (Binary, Get, Put, get, put)
import Data.Binary.Orphans ()
import Data.Word           (Word8)

import qualified Data.Fixed                        as Fixed
import qualified Data.Time.Calendar.Compat         as Time
import qualified Data.Time.Calendar.Month.Compat   as Time
import qualified Data.Time.Calendar.Quarter.Compat as Time
import qualified Data.Time.Clock.Compat            as Time
import qualified Data.Time.Clock.System.Compat     as Time
import qualified Data.Time.Clock.TAI.Compat        as Time
import qualified Data.Time.LocalTime.Compat        as Time

instance Binary Time.Day where
  get :: Get Day
get = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Integer -> Day
Time.ModifiedJulianDay forall t. Binary t => Get t
get
  put :: Day -> Put
put = forall t. Binary t => t -> Put
put forall b c a. (b -> c) -> (a -> b) -> a -> c
. Day -> Integer
Time.toModifiedJulianDay

instance Binary Time.UniversalTime where
  get :: Get UniversalTime
get = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Rational -> UniversalTime
Time.ModJulianDate forall t. Binary t => Get t
get
  put :: UniversalTime -> Put
put = forall t. Binary t => t -> Put
put forall b c a. (b -> c) -> (a -> b) -> a -> c
. UniversalTime -> Rational
Time.getModJulianDate

instance Binary Time.DiffTime where
  get :: Get DiffTime
get = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Integer -> DiffTime
Time.picosecondsToDiffTime forall t. Binary t => Get t
get
  put :: DiffTime -> Put
put = (forall t. Binary t => t -> Put
put :: Fixed.Pico -> Put)  forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Real a, Fractional b) => a -> b
realToFrac

instance Binary Time.UTCTime where
  get :: Get UTCTime
get = forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 Day -> DiffTime -> UTCTime
Time.UTCTime forall t. Binary t => Get t
get forall t. Binary t => Get t
get
  put :: UTCTime -> Put
put (Time.UTCTime Day
d DiffTime
dt) = forall t. Binary t => t -> Put
put Day
d forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put DiffTime
dt

instance Binary Time.NominalDiffTime where
  get :: Get NominalDiffTime
get = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a b. (Real a, Fractional b) => a -> b
realToFrac (forall t. Binary t => Get t
get :: Get Fixed.Pico)
  put :: NominalDiffTime -> Put
put = (forall t. Binary t => t -> Put
put :: Fixed.Pico -> Put)  forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (Real a, Fractional b) => a -> b
realToFrac

instance Binary Time.TimeZone where
  get :: Get TimeZone
get = forall (m :: * -> *) a1 a2 a3 r.
Monad m =>
(a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
liftM3 Int -> Bool -> String -> TimeZone
Time.TimeZone forall t. Binary t => Get t
get forall t. Binary t => Get t
get forall t. Binary t => Get t
get
  put :: TimeZone -> Put
put (Time.TimeZone Int
m Bool
s String
n) = forall t. Binary t => t -> Put
put Int
m forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put Bool
s forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put String
n

instance Binary Time.TimeOfDay where
  get :: Get TimeOfDay
get = forall (m :: * -> *) a1 a2 a3 r.
Monad m =>
(a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
liftM3 Int -> Int -> Pico -> TimeOfDay
Time.TimeOfDay forall t. Binary t => Get t
get forall t. Binary t => Get t
get forall t. Binary t => Get t
get
  put :: TimeOfDay -> Put
put (Time.TimeOfDay Int
h Int
m Pico
s) = forall t. Binary t => t -> Put
put Int
h forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put Int
m forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put Pico
s

instance Binary Time.LocalTime where
  get :: Get LocalTime
get = forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 Day -> TimeOfDay -> LocalTime
Time.LocalTime forall t. Binary t => Get t
get forall t. Binary t => Get t
get
  put :: LocalTime -> Put
put (Time.LocalTime Day
d TimeOfDay
tod) = forall t. Binary t => t -> Put
put Day
d forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put TimeOfDay
tod

instance Binary Time.ZonedTime where
  get :: Get ZonedTime
get = forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 LocalTime -> TimeZone -> ZonedTime
Time.ZonedTime forall t. Binary t => Get t
get forall t. Binary t => Get t
get
  put :: ZonedTime -> Put
put (Time.ZonedTime LocalTime
t TimeZone
z) = forall t. Binary t => t -> Put
put LocalTime
t forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put TimeZone
z

instance Binary Time.AbsoluteTime where
  get :: Get AbsoluteTime
get = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a b c. (a -> b -> c) -> b -> a -> c
flip DiffTime -> AbsoluteTime -> AbsoluteTime
Time.addAbsoluteTime AbsoluteTime
Time.taiEpoch) forall t. Binary t => Get t
get
  put :: AbsoluteTime -> Put
put = forall t. Binary t => t -> Put
put forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> b -> a -> c
flip AbsoluteTime -> AbsoluteTime -> DiffTime
Time.diffAbsoluteTime AbsoluteTime
Time.taiEpoch

instance Binary Time.SystemTime where
    get :: Get SystemTime
get = forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 Int64 -> Word32 -> SystemTime
Time.MkSystemTime forall t. Binary t => Get t
get forall t. Binary t => Get t
get
    put :: SystemTime -> Put
put (Time.MkSystemTime Int64
s Word32
ns) = forall t. Binary t => t -> Put
put Int64
s forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put Word32
ns

instance Binary Time.CalendarDiffDays where
    get :: Get CalendarDiffDays
get = forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 Integer -> Integer -> CalendarDiffDays
Time.CalendarDiffDays forall t. Binary t => Get t
get forall t. Binary t => Get t
get
    put :: CalendarDiffDays -> Put
put (Time.CalendarDiffDays Integer
m Integer
d) = forall t. Binary t => t -> Put
put Integer
m forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put Integer
d

instance Binary Time.CalendarDiffTime where
    get :: Get CalendarDiffTime
get = forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 Integer -> NominalDiffTime -> CalendarDiffTime
Time.CalendarDiffTime forall t. Binary t => Get t
get forall t. Binary t => Get t
get
    put :: CalendarDiffTime -> Put
put (Time.CalendarDiffTime Integer
m NominalDiffTime
nt) = forall t. Binary t => t -> Put
put Integer
m forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall t. Binary t => t -> Put
put NominalDiffTime
nt

instance Binary Time.DayOfWeek where
    put :: DayOfWeek -> Put
put DayOfWeek
Time.Sunday    = forall t. Binary t => t -> Put
put (Word8
0 :: Word8)
    put DayOfWeek
Time.Monday    = forall t. Binary t => t -> Put
put (Word8
1 :: Word8)
    put DayOfWeek
Time.Tuesday   = forall t. Binary t => t -> Put
put (Word8
2 :: Word8)
    put DayOfWeek
Time.Wednesday = forall t. Binary t => t -> Put
put (Word8
3 :: Word8)
    put DayOfWeek
Time.Thursday  = forall t. Binary t => t -> Put
put (Word8
4 :: Word8)
    put DayOfWeek
Time.Friday    = forall t. Binary t => t -> Put
put (Word8
5 :: Word8)
    put DayOfWeek
Time.Saturday  = forall t. Binary t => t -> Put
put (Word8
6 :: Word8)

    get :: Get DayOfWeek
get = do
        Word8
i <- forall t. Binary t => Get t
get
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ case forall a. Integral a => a -> a -> a
mod (Word8
i :: Word8) Word8
7 of
            Word8
0 -> DayOfWeek
Time.Sunday
            Word8
1 -> DayOfWeek
Time.Monday
            Word8
2 -> DayOfWeek
Time.Tuesday
            Word8
3 -> DayOfWeek
Time.Wednesday
            Word8
4 -> DayOfWeek
Time.Thursday
            Word8
5 -> DayOfWeek
Time.Friday
            Word8
6 -> DayOfWeek
Time.Saturday
            Word8
_ -> forall a. HasCallStack => String -> a
error String
"panic: get @DayOfWeek"

instance Binary Time.Month where
    put :: Month -> Put
put (Time.MkMonth Integer
m) = forall t. Binary t => t -> Put
put Integer
m
    get :: Get Month
get = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Integer -> Month
Time.MkMonth forall t. Binary t => Get t
get

instance Binary Time.Quarter where
    put :: Quarter -> Put
put (Time.MkQuarter Integer
m) = forall t. Binary t => t -> Put
put Integer
m
    get :: Get Quarter
get = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Integer -> Quarter
Time.MkQuarter forall t. Binary t => Get t
get

instance Binary Time.QuarterOfYear where
    put :: QuarterOfYear -> Put
put QuarterOfYear
Time.Q1 = forall t. Binary t => t -> Put
put (Word8
1 :: Word8)
    put QuarterOfYear
Time.Q2 = forall t. Binary t => t -> Put
put (Word8
2 :: Word8)
    put QuarterOfYear
Time.Q3 = forall t. Binary t => t -> Put
put (Word8
3 :: Word8)
    put QuarterOfYear
Time.Q4 = forall t. Binary t => t -> Put
put (Word8
4 :: Word8)

    get :: Get QuarterOfYear
get = do
        Word8
i <- forall t. Binary t => Get t
get
        forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ case forall a. Integral a => a -> a -> a
mod (Word8
i :: Word8) Word8
7 of
            Word8
1 -> QuarterOfYear
Time.Q1
            Word8
2 -> QuarterOfYear
Time.Q2
            Word8
3 -> QuarterOfYear
Time.Q3
            Word8
4 -> QuarterOfYear
Time.Q4
            Word8
_ -> forall a. HasCallStack => String -> a
error String
"panic: get @DayOfWeek"