{-# LANGUAGE FlexibleContexts, ScopedTypeVariables, ViewPatterns, ConstraintKinds, TupleSections, RecordWildCards, TypeFamilies #-} module Postdelay.TimeSpec ( pTimeSpec , pTimeZone , spaceConsumer, lexeme ) where import Postdelay.TimeSpec.Utils import Postdelay.TimeSpec.Units import Text.Megaparsec import Control.Monad.IO.Class import Control.Applicative import Control.Lens hiding ((#)) import Data.Bool import Data.Semigroup hiding (option) import Data.Monoid (Endo(..)) import Data.Foldable import Data.VectorSpace import Data.Time import Data.Time.Lens import Data.Time.Zones seconds' :: Timeable t => Lens' t Time seconds' = seconds . iso (% Second) (# Second) pTimeSpec :: StringParser s m => m (Endo LocalTime) pTimeSpec = label "Relative time specification" $ choice [ pOffsets False ] pOffsets :: forall s m. StringParser s m => Bool -- ^ Require sign on first offset? -> m (Endo LocalTime) pOffsets (bool optSigned signed -> reqSgn) = fmap fold $ (:) <$> offset reqSgn <*> many (offset optSigned) where asOffset :: Time -> Endo LocalTime asOffset by = Endo $ flexDT.seconds' %~ (^+^ by) offset :: (m Time -> m Time) -> m (Endo LocalTime) offset sgn = asOffset <$> lexeme (sgn timeLength) "Time offset" pTimeZone :: (StringParser s m, MonadIO m) => m (Either TimeZone TZ) pTimeZone = label "Timezone" $ empty