---------------------------------------------------------------------- -- -- Module : Uniform.Time -- ---------------------------------------------------------------------- {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} -- | a minimal set of time operations -- at the moment only a wrapper to time -- examples in TestingTime.hs module Uniform.Time ( module Uniform.Time, -- module Uniform.Strings, EpochTime, UTCTime (..), ErrIO ) where import Data.Convertible (convert) import Data.Time as T ( NominalDiffTime, UTCTime (..), addUTCTime, defaultTimeLocale, diffDays, diffUTCTime, formatTime, getCurrentTime, parseTimeM, parseTimeOrError, toGregorian, ) import Data.Time.Clock.POSIX ( getCurrentTime, posixSecondsToUTCTime ) import System.Posix.Types (EpochTime) import Uniform.Error --(ErrIO, errorT) import Uniform.Strings -- Text, CharChains2, show', IsString(..), t2s, s2) import Uniform.Zero year2000 :: UTCTime year2000 = readDate3 "2000-01-01" -- ^ may serve as zero in some applications instance CharChains2 UTCTime Text where -- orphan instance show' = s2t . show instance CharChains2 T.NominalDiffTime Text where show' = s2t . show instance CharChains2 (Integer, Int, Int) Text where show' = s2t . show instance IsString UTCTime where fromString = readNote "IsString UTCTime" getCurrentTimeUTC :: ErrIO UTCTime addSeconds :: Double -> UTCTime -> UTCTime diffSeconds :: UTCTime -> UTCTime -> T.NominalDiffTime getCurrentTimeUTC = liftIO T.getCurrentTime addSeconds s t = T.addUTCTime (realToFrac s) t diffSeconds = T.diffUTCTime toYMD :: UTCTime -> (Integer, Int, Int) toYMD = T.toGregorian . T.utctDay diffDays :: UTCTime -> UTCTime -> Integer diffDays a b = T.diffDays (T.utctDay a) (T.utctDay b) epochTime2UTCTime :: EpochTime -> UTCTime epochTime2UTCTime = convert getDateAsText :: ErrIO Text getDateAsText = callIO $ do now <- getCurrentTime let res = formatTime defaultTimeLocale "%b %-d, %Y" now return . s2t $ res readDate2 :: Text -> UTCTime -- ^ read data in the Jan 7, 2019 format (no . after month) readDate2 datestring = parseTimeOrError True defaultTimeLocale "%b %-d, %Y" (t2s datestring) :: UTCTime readDate3 :: Text -> UTCTime readDate3 dateText = case (readDateMaybe dateText) of Nothing -> errorT ["readDate3", dateText, "cannot be parsed"] Just t -> t readDateMaybe :: Text -> Maybe UTCTime -- ^ read data in various formats (but not 9.10.20 !) readDateMaybe dateText = listToMaybe . catMaybes $ [ shortMonth, longMonth, monthPoint, germanNumeralShort, germanNumeral, isoformat ] where shortMonth :: Maybe UTCTime shortMonth = parseTimeM True defaultTimeLocale "%b %-d, %Y" dateString :: Maybe UTCTime longMonth = parseTimeM True defaultTimeLocale "%B %-d, %Y" dateString :: Maybe UTCTime monthPoint = parseTimeM True defaultTimeLocale "%b. %-d, %Y" dateString :: Maybe UTCTime germanNumeral = parseTimeM True defaultTimeLocale "%-d.%-m.%Y" dateString :: Maybe UTCTime germanNumeralShort = parseTimeM True defaultTimeLocale "%-d.%-m.%y" dateString :: Maybe UTCTime isoformat = parseTimeM True defaultTimeLocale "%Y-%m-%d" dateString :: Maybe UTCTime dateString = t2s dateText fromEpochTime' :: EpochTime -> UTCTime fromEpochTime' et = posixSecondsToUTCTime (realToFrac et)