{-# language GeneralizedNewtypeDeriving #-}
{-|
Description : Time differences in milliseconds

Avro defines a specific logical type for time
differences expessed in milliseconds. This module
provides a type which wraps the 'DiffTime' from
the @time@ library (which uses nanoseconds),
offering a millisecond-based interface.
-}
module Data.Time.Millis where

import           Control.DeepSeq             (NFData)
import           Data.Avro.Encoding.FromAvro
import           Data.Avro.Encoding.ToAvro
import           Data.Avro.HasAvroSchema
import qualified Data.Avro.Schema.Schema     as S
import           Data.Int                    (Int32)
import           Data.Tagged
import           Data.Time

-- | Wrapper for time difference expressed in milliseconds
newtype DiffTimeMs = DiffTimeMs { DiffTimeMs -> DiffTime
unDiffTimeMs :: DiffTime }
  deriving (Int -> DiffTimeMs -> ShowS
[DiffTimeMs] -> ShowS
DiffTimeMs -> String
(Int -> DiffTimeMs -> ShowS)
-> (DiffTimeMs -> String)
-> ([DiffTimeMs] -> ShowS)
-> Show DiffTimeMs
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [DiffTimeMs] -> ShowS
$cshowList :: [DiffTimeMs] -> ShowS
show :: DiffTimeMs -> String
$cshow :: DiffTimeMs -> String
showsPrec :: Int -> DiffTimeMs -> ShowS
$cshowsPrec :: Int -> DiffTimeMs -> ShowS
Show, DiffTimeMs -> DiffTimeMs -> Bool
(DiffTimeMs -> DiffTimeMs -> Bool)
-> (DiffTimeMs -> DiffTimeMs -> Bool) -> Eq DiffTimeMs
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: DiffTimeMs -> DiffTimeMs -> Bool
$c/= :: DiffTimeMs -> DiffTimeMs -> Bool
== :: DiffTimeMs -> DiffTimeMs -> Bool
$c== :: DiffTimeMs -> DiffTimeMs -> Bool
Eq, Eq DiffTimeMs
Eq DiffTimeMs
-> (DiffTimeMs -> DiffTimeMs -> Ordering)
-> (DiffTimeMs -> DiffTimeMs -> Bool)
-> (DiffTimeMs -> DiffTimeMs -> Bool)
-> (DiffTimeMs -> DiffTimeMs -> Bool)
-> (DiffTimeMs -> DiffTimeMs -> Bool)
-> (DiffTimeMs -> DiffTimeMs -> DiffTimeMs)
-> (DiffTimeMs -> DiffTimeMs -> DiffTimeMs)
-> Ord DiffTimeMs
DiffTimeMs -> DiffTimeMs -> Bool
DiffTimeMs -> DiffTimeMs -> Ordering
DiffTimeMs -> DiffTimeMs -> DiffTimeMs
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs
$cmin :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs
max :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs
$cmax :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs
>= :: DiffTimeMs -> DiffTimeMs -> Bool
$c>= :: DiffTimeMs -> DiffTimeMs -> Bool
> :: DiffTimeMs -> DiffTimeMs -> Bool
$c> :: DiffTimeMs -> DiffTimeMs -> Bool
<= :: DiffTimeMs -> DiffTimeMs -> Bool
$c<= :: DiffTimeMs -> DiffTimeMs -> Bool
< :: DiffTimeMs -> DiffTimeMs -> Bool
$c< :: DiffTimeMs -> DiffTimeMs -> Bool
compare :: DiffTimeMs -> DiffTimeMs -> Ordering
$ccompare :: DiffTimeMs -> DiffTimeMs -> Ordering
$cp1Ord :: Eq DiffTimeMs
Ord, Int -> DiffTimeMs
DiffTimeMs -> Int
DiffTimeMs -> [DiffTimeMs]
DiffTimeMs -> DiffTimeMs
DiffTimeMs -> DiffTimeMs -> [DiffTimeMs]
DiffTimeMs -> DiffTimeMs -> DiffTimeMs -> [DiffTimeMs]
(DiffTimeMs -> DiffTimeMs)
-> (DiffTimeMs -> DiffTimeMs)
-> (Int -> DiffTimeMs)
-> (DiffTimeMs -> Int)
-> (DiffTimeMs -> [DiffTimeMs])
-> (DiffTimeMs -> DiffTimeMs -> [DiffTimeMs])
-> (DiffTimeMs -> DiffTimeMs -> [DiffTimeMs])
-> (DiffTimeMs -> DiffTimeMs -> DiffTimeMs -> [DiffTimeMs])
-> Enum DiffTimeMs
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs -> [DiffTimeMs]
$cenumFromThenTo :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs -> [DiffTimeMs]
enumFromTo :: DiffTimeMs -> DiffTimeMs -> [DiffTimeMs]
$cenumFromTo :: DiffTimeMs -> DiffTimeMs -> [DiffTimeMs]
enumFromThen :: DiffTimeMs -> DiffTimeMs -> [DiffTimeMs]
$cenumFromThen :: DiffTimeMs -> DiffTimeMs -> [DiffTimeMs]
enumFrom :: DiffTimeMs -> [DiffTimeMs]
$cenumFrom :: DiffTimeMs -> [DiffTimeMs]
fromEnum :: DiffTimeMs -> Int
$cfromEnum :: DiffTimeMs -> Int
toEnum :: Int -> DiffTimeMs
$ctoEnum :: Int -> DiffTimeMs
pred :: DiffTimeMs -> DiffTimeMs
$cpred :: DiffTimeMs -> DiffTimeMs
succ :: DiffTimeMs -> DiffTimeMs
$csucc :: DiffTimeMs -> DiffTimeMs
Enum, Integer -> DiffTimeMs
DiffTimeMs -> DiffTimeMs
DiffTimeMs -> DiffTimeMs -> DiffTimeMs
(DiffTimeMs -> DiffTimeMs -> DiffTimeMs)
-> (DiffTimeMs -> DiffTimeMs -> DiffTimeMs)
-> (DiffTimeMs -> DiffTimeMs -> DiffTimeMs)
-> (DiffTimeMs -> DiffTimeMs)
-> (DiffTimeMs -> DiffTimeMs)
-> (DiffTimeMs -> DiffTimeMs)
-> (Integer -> DiffTimeMs)
-> Num DiffTimeMs
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> DiffTimeMs
$cfromInteger :: Integer -> DiffTimeMs
signum :: DiffTimeMs -> DiffTimeMs
$csignum :: DiffTimeMs -> DiffTimeMs
abs :: DiffTimeMs -> DiffTimeMs
$cabs :: DiffTimeMs -> DiffTimeMs
negate :: DiffTimeMs -> DiffTimeMs
$cnegate :: DiffTimeMs -> DiffTimeMs
* :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs
$c* :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs
- :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs
$c- :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs
+ :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs
$c+ :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs
Num, Num DiffTimeMs
Num DiffTimeMs
-> (DiffTimeMs -> DiffTimeMs -> DiffTimeMs)
-> (DiffTimeMs -> DiffTimeMs)
-> (Rational -> DiffTimeMs)
-> Fractional DiffTimeMs
Rational -> DiffTimeMs
DiffTimeMs -> DiffTimeMs
DiffTimeMs -> DiffTimeMs -> DiffTimeMs
forall a.
Num a
-> (a -> a -> a) -> (a -> a) -> (Rational -> a) -> Fractional a
fromRational :: Rational -> DiffTimeMs
$cfromRational :: Rational -> DiffTimeMs
recip :: DiffTimeMs -> DiffTimeMs
$crecip :: DiffTimeMs -> DiffTimeMs
/ :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs
$c/ :: DiffTimeMs -> DiffTimeMs -> DiffTimeMs
$cp1Fractional :: Num DiffTimeMs
Fractional, Num DiffTimeMs
Ord DiffTimeMs
Num DiffTimeMs
-> Ord DiffTimeMs -> (DiffTimeMs -> Rational) -> Real DiffTimeMs
DiffTimeMs -> Rational
forall a. Num a -> Ord a -> (a -> Rational) -> Real a
toRational :: DiffTimeMs -> Rational
$ctoRational :: DiffTimeMs -> Rational
$cp2Real :: Ord DiffTimeMs
$cp1Real :: Num DiffTimeMs
Real, Fractional DiffTimeMs
Real DiffTimeMs
Real DiffTimeMs
-> Fractional DiffTimeMs
-> (forall b. Integral b => DiffTimeMs -> (b, DiffTimeMs))
-> (forall b. Integral b => DiffTimeMs -> b)
-> (forall b. Integral b => DiffTimeMs -> b)
-> (forall b. Integral b => DiffTimeMs -> b)
-> (forall b. Integral b => DiffTimeMs -> b)
-> RealFrac DiffTimeMs
DiffTimeMs -> b
DiffTimeMs -> b
DiffTimeMs -> b
DiffTimeMs -> b
DiffTimeMs -> (b, DiffTimeMs)
forall b. Integral b => DiffTimeMs -> b
forall b. Integral b => DiffTimeMs -> (b, DiffTimeMs)
forall a.
Real a
-> Fractional a
-> (forall b. Integral b => a -> (b, a))
-> (forall b. Integral b => a -> b)
-> (forall b. Integral b => a -> b)
-> (forall b. Integral b => a -> b)
-> (forall b. Integral b => a -> b)
-> RealFrac a
floor :: DiffTimeMs -> b
$cfloor :: forall b. Integral b => DiffTimeMs -> b
ceiling :: DiffTimeMs -> b
$cceiling :: forall b. Integral b => DiffTimeMs -> b
round :: DiffTimeMs -> b
$cround :: forall b. Integral b => DiffTimeMs -> b
truncate :: DiffTimeMs -> b
$ctruncate :: forall b. Integral b => DiffTimeMs -> b
properFraction :: DiffTimeMs -> (b, DiffTimeMs)
$cproperFraction :: forall b. Integral b => DiffTimeMs -> (b, DiffTimeMs)
$cp2RealFrac :: Fractional DiffTimeMs
$cp1RealFrac :: Real DiffTimeMs
RealFrac, DiffTimeMs -> ()
(DiffTimeMs -> ()) -> NFData DiffTimeMs
forall a. (a -> ()) -> NFData a
rnf :: DiffTimeMs -> ()
$crnf :: DiffTimeMs -> ()
NFData)

instance HasAvroSchema DiffTimeMs where
  schema :: Tagged DiffTimeMs Schema
schema = Schema -> Tagged DiffTimeMs Schema
forall k (s :: k) b. b -> Tagged s b
Tagged (Schema -> Tagged DiffTimeMs Schema)
-> Schema -> Tagged DiffTimeMs Schema
forall a b. (a -> b) -> a -> b
$ Maybe LogicalTypeInt -> Schema
S.Int (LogicalTypeInt -> Maybe LogicalTypeInt
forall a. a -> Maybe a
Just LogicalTypeInt
S.TimeMillis)

instance ToAvro DiffTimeMs where
  toAvro :: Schema -> DiffTimeMs -> Builder
toAvro Schema
s = Schema -> Int32 -> Builder
forall a. ToAvro a => Schema -> a -> Builder
toAvro Schema
s (Int32 -> Builder)
-> (DiffTimeMs -> Int32) -> DiffTimeMs -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral :: Integer -> Int32) (Integer -> Int32)
-> (DiffTimeMs -> Integer) -> DiffTimeMs -> Int32
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DiffTimeMs -> Integer
diffTimeToMillis

instance FromAvro DiffTimeMs where
  fromAvro :: Value -> Either String DiffTimeMs
fromAvro (Int ReadSchema
_ Int32
v) = DiffTimeMs -> Either String DiffTimeMs
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DiffTimeMs -> Either String DiffTimeMs)
-> DiffTimeMs -> Either String DiffTimeMs
forall a b. (a -> b) -> a -> b
$ Integer -> DiffTimeMs
millisToDiffTime (Int32 -> Integer
forall a. Integral a => a -> Integer
toInteger Int32
v)
  fromAvro Value
_         = String -> Either String DiffTimeMs
forall a b. a -> Either a b
Left String
"expecting time_ms"

-- | Obtain the underlying time in milliseconds from a 'DiffTimeMs'.
diffTimeToMillis :: DiffTimeMs -> Integer
diffTimeToMillis :: DiffTimeMs -> Integer
diffTimeToMillis = (Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
`div` Integer
1000000000) (Integer -> Integer)
-> (DiffTimeMs -> Integer) -> DiffTimeMs -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DiffTime -> Integer
diffTimeToPicoseconds (DiffTime -> Integer)
-> (DiffTimeMs -> DiffTime) -> DiffTimeMs -> Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DiffTimeMs -> DiffTime
unDiffTimeMs

-- | Build a 'DiffTimeMs' from an amount expressed in milliseconds.
millisToDiffTime :: Integer -> DiffTimeMs
millisToDiffTime :: Integer -> DiffTimeMs
millisToDiffTime = DiffTime -> DiffTimeMs
DiffTimeMs (DiffTime -> DiffTimeMs)
-> (Integer -> DiffTime) -> Integer -> DiffTimeMs
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> DiffTime
picosecondsToDiffTime (Integer -> DiffTime)
-> (Integer -> Integer) -> Integer -> DiffTime
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* Integer
1000000000)