-- | Parsing of unix timestamps
module Calamity.Types.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 GHC.Generics

import Control.DeepSeq (NFData)
import TextShow
import qualified TextShow.Generic as TSG

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, UnixTimestamp -> UnixTimestamp -> Bool
(UnixTimestamp -> UnixTimestamp -> Bool)
-> (UnixTimestamp -> UnixTimestamp -> Bool) -> Eq UnixTimestamp
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: UnixTimestamp -> UnixTimestamp -> Bool
$c/= :: UnixTimestamp -> UnixTimestamp -> Bool
== :: UnixTimestamp -> UnixTimestamp -> Bool
$c== :: UnixTimestamp -> UnixTimestamp -> Bool
Eq, (forall x. UnixTimestamp -> Rep UnixTimestamp x)
-> (forall x. Rep UnixTimestamp x -> UnixTimestamp)
-> Generic UnixTimestamp
forall x. Rep UnixTimestamp x -> UnixTimestamp
forall x. UnixTimestamp -> Rep UnixTimestamp x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep UnixTimestamp x -> UnixTimestamp
$cfrom :: forall x. UnixTimestamp -> Rep UnixTimestamp x
Generic)
    deriving newtype (UnixTimestamp -> ()
(UnixTimestamp -> ()) -> NFData UnixTimestamp
forall a. (a -> ()) -> NFData a
rnf :: UnixTimestamp -> ()
$crnf :: UnixTimestamp -> ()
NFData)
    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 TSG.FromGeneric UnixTimestamp

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
>>> ToJSON Word64 => Word64 -> Value
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