-- | 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
$cshowsPrec :: Int -> UnixTimestamp -> ShowS
showsPrec :: Int -> UnixTimestamp -> ShowS
$cshow :: UnixTimestamp -> String
show :: UnixTimestamp -> String
$cshowList :: [UnixTimestamp] -> ShowS
showList :: [UnixTimestamp] -> ShowS
Show) via UTCTime
  deriving (Int -> UnixTimestamp -> Text
Int -> UnixTimestamp -> Builder
Int -> UnixTimestamp -> Text
[UnixTimestamp] -> Text
[UnixTimestamp] -> Builder
[UnixTimestamp] -> Text
UnixTimestamp -> Text
UnixTimestamp -> Builder
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
$cshowbPrec :: Int -> UnixTimestamp -> Builder
showbPrec :: Int -> UnixTimestamp -> Builder
$cshowb :: UnixTimestamp -> Builder
showb :: UnixTimestamp -> Builder
$cshowbList :: [UnixTimestamp] -> Builder
showbList :: [UnixTimestamp] -> Builder
$cshowtPrec :: Int -> UnixTimestamp -> Text
showtPrec :: Int -> UnixTimestamp -> Text
$cshowt :: UnixTimestamp -> Text
showt :: UnixTimestamp -> Text
$cshowtList :: [UnixTimestamp] -> Text
showtList :: [UnixTimestamp] -> Text
$cshowtlPrec :: Int -> UnixTimestamp -> Text
showtlPrec :: Int -> UnixTimestamp -> Text
$cshowtl :: UnixTimestamp -> Text
showtl :: UnixTimestamp -> Text
$cshowtlList :: [UnixTimestamp] -> Text
showtlList :: [UnixTimestamp] -> Text
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 b. Integral b => Rational -> b
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 b. Integral b => Rational -> b
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 b. Integral b => Rational -> b
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 a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure