caliper-0.1.0.0: src/Caliper/Syntax/Transform.hs
module Caliper.Syntax.Transform where
import Data.Function
import Data.List.NonEmpty qualified as NE
import Data.Map qualified as M
import Data.Maybe
import Data.Text qualified as T
import Data.Time.Clock
import Data.Time.LocalTime
import Caliper.Syntax.Ast
data TagPredicate
= HasKeyValue T.Text T.Text
| Negate TagPredicate
applyTagPredicate :: TagPredicate -> M.Map T.Text (NE.NonEmpty T.Text) -> Bool
applyTagPredicate (HasKeyValue k v) = maybe False (v `elem`) . M.lookup k
applyTagPredicate (Negate f) = not . applyTagPredicate f
sumDuration :: (Foldable f, Functor f) => f ResolvedEntry -> NominalDiffTime
sumDuration = sum . fmap entrySpan
filterByTags :: [TagPredicate] -> [ResolvedEntry] -> [ResolvedEntry]
filterByTags = foldr ((.) . filterByTag) id
filterByTag :: TagPredicate -> [ResolvedEntry] -> [ResolvedEntry]
filterByTag p = filter (applyTagPredicate p . entryMetadata)
{- | Precondition: input entries must be sorted in ascending order in absolute time
We group by perceived day, that is, the local day experienced in a given timezone
-}
groupEntriesByDay :: [ResolvedEntry] -> [NE.NonEmpty ResolvedEntry]
groupEntriesByDay = NE.groupBy ((==) `on` localDay . zonedTimeToLocalTime . entryStart)
entriesAfter :: LocalTime -> [ResolvedEntry] -> [ResolvedEntry]
entriesAfter thres = mapMaybe $ \e ->
let ZonedTime l tz = entryStart e
e' = e {entryStart = ZonedTime (max l thres) tz}
in if entrySpan e' > 0 then Just e' else Nothing
entriesBefore :: LocalTime -> [ResolvedEntry] -> [ResolvedEntry]
entriesBefore thres = mapMaybe $ \e ->
let ZonedTime l tz = entryEnd e
e' = e {entryEnd = ZonedTime (min l thres) tz}
in if entrySpan e' > 0 then Just e' else Nothing