-- | 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           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 ( 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
* 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
/ 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 "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