-- | Internal newtype for deserializing timestamps
module Calamity.Internal.UnixTimestamp (
    UnixTimestamp (..),
    unixToMilliseconds,
    millisecondsToUnix,
) where

import Calamity.Internal.Utils ()
import Control.Arrow
import Data.Aeson
import Data.Aeson.Encoding (word64)
import Data.Time
import Data.Time.Clock.POSIX
import Data.Word
import TextShow

newtype UnixTimestamp = UnixTimestamp
    { UnixTimestamp -> UTCTime
unUnixTimestamp :: UTCTime
    }
    deriving (Int -> UnixTimestamp -> ShowS
[UnixTimestamp] -> ShowS
UnixTimestamp -> String
(Int -> UnixTimestamp -> ShowS)
-> (UnixTimestamp -> String)
-> ([UnixTimestamp] -> ShowS)
-> Show UnixTimestamp
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UnixTimestamp] -> ShowS
$cshowList :: [UnixTimestamp] -> ShowS
show :: UnixTimestamp -> String
$cshow :: UnixTimestamp -> String
showsPrec :: Int -> UnixTimestamp -> ShowS
$cshowsPrec :: Int -> UnixTimestamp -> ShowS
Show) via UTCTime
    deriving (Int -> UnixTimestamp -> Builder
Int -> UnixTimestamp -> Text
Int -> UnixTimestamp -> Text
[UnixTimestamp] -> Builder
[UnixTimestamp] -> Text
[UnixTimestamp] -> Text
UnixTimestamp -> Builder
UnixTimestamp -> Text
UnixTimestamp -> Text
(Int -> UnixTimestamp -> Builder)
-> (UnixTimestamp -> Builder)
-> ([UnixTimestamp] -> Builder)
-> (Int -> UnixTimestamp -> Text)
-> (UnixTimestamp -> Text)
-> ([UnixTimestamp] -> Text)
-> (Int -> UnixTimestamp -> Text)
-> (UnixTimestamp -> Text)
-> ([UnixTimestamp] -> Text)
-> TextShow UnixTimestamp
forall a.
(Int -> a -> Builder)
-> (a -> Builder)
-> ([a] -> Builder)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> (Int -> a -> Text)
-> (a -> Text)
-> ([a] -> Text)
-> TextShow a
showtlList :: [UnixTimestamp] -> Text
$cshowtlList :: [UnixTimestamp] -> Text
showtl :: UnixTimestamp -> Text
$cshowtl :: UnixTimestamp -> Text
showtlPrec :: Int -> UnixTimestamp -> Text
$cshowtlPrec :: Int -> UnixTimestamp -> Text
showtList :: [UnixTimestamp] -> Text
$cshowtList :: [UnixTimestamp] -> Text
showt :: UnixTimestamp -> Text
$cshowt :: UnixTimestamp -> Text
showtPrec :: Int -> UnixTimestamp -> Text
$cshowtPrec :: Int -> UnixTimestamp -> Text
showbList :: [UnixTimestamp] -> Builder
$cshowbList :: [UnixTimestamp] -> Builder
showb :: UnixTimestamp -> Builder
$cshowb :: UnixTimestamp -> Builder
showbPrec :: Int -> UnixTimestamp -> Builder
$cshowbPrec :: Int -> UnixTimestamp -> Builder
TextShow) via FromStringShow UTCTime

unixToMilliseconds :: UnixTimestamp -> Word64
unixToMilliseconds :: UnixTimestamp -> Word64
unixToMilliseconds =
    UnixTimestamp -> UTCTime
unUnixTimestamp
        (UnixTimestamp -> UTCTime)
-> (UTCTime -> Word64) -> UnixTimestamp -> Word64
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> UTCTime -> POSIXTime
utcTimeToPOSIXSeconds
        (UTCTime -> POSIXTime)
-> (POSIXTime -> Word64) -> UTCTime -> Word64
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> POSIXTime -> Rational
forall a. Real a => a -> Rational
toRational
        (POSIXTime -> Rational)
-> (Rational -> Word64) -> POSIXTime -> Word64
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> (Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* Rational
1000)
        (Rational -> Rational)
-> (Rational -> Word64) -> Rational -> Word64
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> Rational -> Word64
forall a b. (RealFrac a, Integral b) => a -> b
round

millisecondsToUnix :: Word64 -> UnixTimestamp
millisecondsToUnix :: Word64 -> UnixTimestamp
millisecondsToUnix =
    Word64 -> Rational
forall a. Real a => a -> Rational
toRational
        (Word64 -> Rational)
-> (Rational -> UnixTimestamp) -> Word64 -> UnixTimestamp
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> Rational -> POSIXTime
forall a. Fractional a => Rational -> a
fromRational
        (Rational -> POSIXTime)
-> (POSIXTime -> UnixTimestamp) -> Rational -> UnixTimestamp
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> (POSIXTime -> POSIXTime -> POSIXTime
forall a. Fractional a => a -> a -> a
/ POSIXTime
1000)
        (POSIXTime -> POSIXTime)
-> (POSIXTime -> UnixTimestamp) -> POSIXTime -> UnixTimestamp
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> POSIXTime -> UTCTime
posixSecondsToUTCTime
        (POSIXTime -> UTCTime)
-> (UTCTime -> UnixTimestamp) -> POSIXTime -> UnixTimestamp
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> UTCTime -> UnixTimestamp
UnixTimestamp

instance ToJSON UnixTimestamp where
    toJSON :: UnixTimestamp -> Value
toJSON =
        UnixTimestamp -> UTCTime
unUnixTimestamp
            (UnixTimestamp -> UTCTime)
-> (UTCTime -> Value) -> UnixTimestamp -> Value
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> UTCTime -> POSIXTime
utcTimeToPOSIXSeconds
            (UTCTime -> POSIXTime) -> (POSIXTime -> Value) -> UTCTime -> Value
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> POSIXTime -> Rational
forall a. Real a => a -> Rational
toRational
            (POSIXTime -> Rational)
-> (Rational -> Value) -> POSIXTime -> Value
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> Rational -> Word64
forall a b. (RealFrac a, Integral b) => a -> b
round
            (Rational -> Word64) -> (Word64 -> Value) -> Rational -> Value
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> forall a. ToJSON a => a -> Value
toJSON @Word64
    toEncoding :: UnixTimestamp -> Encoding
toEncoding =
        UnixTimestamp -> UTCTime
unUnixTimestamp
            (UnixTimestamp -> UTCTime)
-> (UTCTime -> Encoding) -> UnixTimestamp -> Encoding
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> UTCTime -> POSIXTime
utcTimeToPOSIXSeconds
            (UTCTime -> POSIXTime)
-> (POSIXTime -> Encoding) -> UTCTime -> Encoding
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> POSIXTime -> Rational
forall a. Real a => a -> Rational
toRational
            (POSIXTime -> Rational)
-> (Rational -> Encoding) -> POSIXTime -> Encoding
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> Rational -> Word64
forall a b. (RealFrac a, Integral b) => a -> b
round
            (Rational -> Word64)
-> (Word64 -> Encoding) -> Rational -> Encoding
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> Word64 -> Encoding
word64

instance FromJSON UnixTimestamp where
    parseJSON :: Value -> Parser UnixTimestamp
parseJSON =
        String
-> (Scientific -> Parser UnixTimestamp)
-> Value
-> Parser UnixTimestamp
forall a. String -> (Scientific -> Parser a) -> Value -> Parser a
withScientific String
"UnixTimestamp" ((Scientific -> Parser UnixTimestamp)
 -> Value -> Parser UnixTimestamp)
-> (Scientific -> Parser UnixTimestamp)
-> Value
-> Parser UnixTimestamp
forall a b. (a -> b) -> a -> b
$
            Scientific -> Rational
forall a. Real a => a -> Rational
toRational
                (Scientific -> Rational)
-> (Rational -> Parser UnixTimestamp)
-> Scientific
-> Parser UnixTimestamp
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> Rational -> POSIXTime
forall a. Fractional a => Rational -> a
fromRational
                (Rational -> POSIXTime)
-> (POSIXTime -> Parser UnixTimestamp)
-> Rational
-> Parser UnixTimestamp
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> POSIXTime -> UTCTime
posixSecondsToUTCTime
                (POSIXTime -> UTCTime)
-> (UTCTime -> Parser UnixTimestamp)
-> POSIXTime
-> Parser UnixTimestamp
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> UTCTime -> UnixTimestamp
UnixTimestamp
                (UTCTime -> UnixTimestamp)
-> (UnixTimestamp -> Parser UnixTimestamp)
-> UTCTime
-> Parser UnixTimestamp
forall {k} (cat :: k -> k -> *) (a :: k) (b :: k) (c :: k).
Category cat =>
cat a b -> cat b c -> cat a c
>>> UnixTimestamp -> Parser UnixTimestamp
forall (f :: * -> *) a. Applicative f => a -> f a
pure