{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
module Achille.Timestamped
( Timestamped(..)
, IsTimestamped
, timestamp
, timestamped
, timestampedWith
, compareTimestamped
, recentFirst
, oldFirst
) where
import Data.Ord (Ord, compare, Ordering)
import System.FilePath (FilePath)
import Data.List (sortBy, sort)
import Data.Typeable (Typeable)
import Data.Binary (Binary, put, get)
import Data.Time.Calendar (fromGregorian)
import Data.Time (UTCTime(..), secondsToDiffTime)
import Data.Time.Format (readSTime, defaultTimeLocale)
import System.FilePath (takeFileName)
import Data.Binary.Instances.Time ()
data Timestamped a = Timestamped UTCTime a
deriving (Int -> Timestamped a -> ShowS
[Timestamped a] -> ShowS
Timestamped a -> String
(Int -> Timestamped a -> ShowS)
-> (Timestamped a -> String)
-> ([Timestamped a] -> ShowS)
-> Show (Timestamped a)
forall a. Show a => Int -> Timestamped a -> ShowS
forall a. Show a => [Timestamped a] -> ShowS
forall a. Show a => Timestamped a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Timestamped a] -> ShowS
$cshowList :: forall a. Show a => [Timestamped a] -> ShowS
show :: Timestamped a -> String
$cshow :: forall a. Show a => Timestamped a -> String
showsPrec :: Int -> Timestamped a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Timestamped a -> ShowS
Show, Timestamped a -> Timestamped a -> Bool
(Timestamped a -> Timestamped a -> Bool)
-> (Timestamped a -> Timestamped a -> Bool) -> Eq (Timestamped a)
forall a. Eq a => Timestamped a -> Timestamped a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Timestamped a -> Timestamped a -> Bool
$c/= :: forall a. Eq a => Timestamped a -> Timestamped a -> Bool
== :: Timestamped a -> Timestamped a -> Bool
$c== :: forall a. Eq a => Timestamped a -> Timestamped a -> Bool
Eq, Eq (Timestamped a)
Eq (Timestamped a) =>
(Timestamped a -> Timestamped a -> Ordering)
-> (Timestamped a -> Timestamped a -> Bool)
-> (Timestamped a -> Timestamped a -> Bool)
-> (Timestamped a -> Timestamped a -> Bool)
-> (Timestamped a -> Timestamped a -> Bool)
-> (Timestamped a -> Timestamped a -> Timestamped a)
-> (Timestamped a -> Timestamped a -> Timestamped a)
-> Ord (Timestamped a)
Timestamped a -> Timestamped a -> Bool
Timestamped a -> Timestamped a -> Ordering
Timestamped a -> Timestamped a -> Timestamped a
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
forall a. Ord a => Eq (Timestamped a)
forall a. Ord a => Timestamped a -> Timestamped a -> Bool
forall a. Ord a => Timestamped a -> Timestamped a -> Ordering
forall a. Ord a => Timestamped a -> Timestamped a -> Timestamped a
min :: Timestamped a -> Timestamped a -> Timestamped a
$cmin :: forall a. Ord a => Timestamped a -> Timestamped a -> Timestamped a
max :: Timestamped a -> Timestamped a -> Timestamped a
$cmax :: forall a. Ord a => Timestamped a -> Timestamped a -> Timestamped a
>= :: Timestamped a -> Timestamped a -> Bool
$c>= :: forall a. Ord a => Timestamped a -> Timestamped a -> Bool
> :: Timestamped a -> Timestamped a -> Bool
$c> :: forall a. Ord a => Timestamped a -> Timestamped a -> Bool
<= :: Timestamped a -> Timestamped a -> Bool
$c<= :: forall a. Ord a => Timestamped a -> Timestamped a -> Bool
< :: Timestamped a -> Timestamped a -> Bool
$c< :: forall a. Ord a => Timestamped a -> Timestamped a -> Bool
compare :: Timestamped a -> Timestamped a -> Ordering
$ccompare :: forall a. Ord a => Timestamped a -> Timestamped a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Timestamped a)
Ord, Typeable, a -> Timestamped b -> Timestamped a
(a -> b) -> Timestamped a -> Timestamped b
(forall a b. (a -> b) -> Timestamped a -> Timestamped b)
-> (forall a b. a -> Timestamped b -> Timestamped a)
-> Functor Timestamped
forall a b. a -> Timestamped b -> Timestamped a
forall a b. (a -> b) -> Timestamped a -> Timestamped b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Timestamped b -> Timestamped a
$c<$ :: forall a b. a -> Timestamped b -> Timestamped a
fmap :: (a -> b) -> Timestamped a -> Timestamped b
$cfmap :: forall a b. (a -> b) -> Timestamped a -> Timestamped b
Functor)
instance Binary a => Binary (Timestamped a) where
put :: Timestamped a -> Put
put (Timestamped d :: UTCTime
d x :: a
x) = UTCTime -> Put
forall t. Binary t => t -> Put
put UTCTime
d Put -> Put -> Put
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> a -> Put
forall t. Binary t => t -> Put
put a
x
get :: Get (Timestamped a)
get = UTCTime -> a -> Timestamped a
forall a. UTCTime -> a -> Timestamped a
Timestamped (UTCTime -> a -> Timestamped a)
-> Get UTCTime -> Get (a -> Timestamped a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Get UTCTime
forall t. Binary t => Get t
get Get (a -> Timestamped a) -> Get a -> Get (Timestamped a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Get a
forall t. Binary t => Get t
get
class IsTimestamped a where
timestamp :: a -> UTCTime
instance IsTimestamped (Timestamped a) where
timestamp :: Timestamped a -> UTCTime
timestamp (Timestamped d :: UTCTime
d _) = UTCTime
d
instance IsTimestamped FilePath where
timestamp :: String -> UTCTime
timestamp p :: String
p =
case Bool -> TimeLocale -> String -> ReadS UTCTime
forall t. ParseTime t => Bool -> TimeLocale -> String -> ReadS t
readSTime Bool
False TimeLocale
defaultTimeLocale "%Y-%m-%d" (ShowS
takeFileName String
p) of
[(t :: UTCTime
t, _)] -> UTCTime
t
_ -> Day -> DiffTime -> UTCTime
UTCTime (Integer -> Int -> Int -> Day
fromGregorian 1970 01 01) (Integer -> DiffTime
secondsToDiffTime 0)
timestamped :: IsTimestamped a => a -> Timestamped a
timestamped :: a -> Timestamped a
timestamped x :: a
x = UTCTime -> a -> Timestamped a
forall a. UTCTime -> a -> Timestamped a
Timestamped (a -> UTCTime
forall a. IsTimestamped a => a -> UTCTime
timestamp a
x) a
x
timestampedWith :: (a -> UTCTime) -> a -> Timestamped a
timestampedWith :: (a -> UTCTime) -> a -> Timestamped a
timestampedWith f :: a -> UTCTime
f x :: a
x = UTCTime -> a -> Timestamped a
forall a. UTCTime -> a -> Timestamped a
Timestamped (a -> UTCTime
f a
x) a
x
compareTimestamped :: IsTimestamped a => a -> a -> Ordering
compareTimestamped :: a -> a -> Ordering
compareTimestamped x :: a
x y :: a
y = UTCTime -> UTCTime -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (a -> UTCTime
forall a. IsTimestamped a => a -> UTCTime
timestamp a
x) (a -> UTCTime
forall a. IsTimestamped a => a -> UTCTime
timestamp a
y)
recentFirst :: IsTimestamped a => [a] -> [a]
recentFirst :: [a] -> [a]
recentFirst = (a -> a -> Ordering) -> [a] -> [a]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy ((a -> a -> Ordering) -> a -> a -> Ordering
forall a b c. (a -> b -> c) -> b -> a -> c
flip a -> a -> Ordering
forall a. IsTimestamped a => a -> a -> Ordering
compareTimestamped)
oldFirst :: IsTimestamped a => [a] -> [a]
oldFirst :: [a] -> [a]
oldFirst = (a -> a -> Ordering) -> [a] -> [a]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy a -> a -> Ordering
forall a. IsTimestamped a => a -> a -> Ordering
compareTimestamped