module TimeUtils ( lookupLocalTimeZone , startOfDay , justAfter, justBefore , asLocalTime , localTimeText , originTime ) where import Prelude () import Prelude.MH import qualified Data.Text as T import Data.Time.Clock ( UTCTime(..) ) import Data.Time.Format ( formatTime, defaultTimeLocale ) import Data.Time.LocalTime ( LocalTime(..), TimeOfDay(..) ) import Data.Time.LocalTime.TimeZone.Olson ( getTimeZoneSeriesFromOlsonFile ) import Data.Time.LocalTime.TimeZone.Series ( localTimeToUTC' , utcToLocalTime') import Network.Mattermost.Types ( ServerTime(..) ) -- | Get the timezone series that should be used for converting UTC -- times into local times with appropriate DST adjustments. lookupLocalTimeZone :: IO TimeZoneSeries lookupLocalTimeZone = getTimeZoneSeriesFromOlsonFile "/etc/localtime" -- | Sometimes it is convenient to render a divider between messages; -- the 'justAfter' function can be used to get a time that is after -- the input time but by such a small increment that there is unlikely -- to be anything between (or at) the result. Adding the divider -- using this timestamp value allows the general sorting based on -- timestamps to operate normally (whereas a type-match for a -- non-timestamp-entry in the sort operation would be considerably -- more complex). justAfter :: ServerTime -> ServerTime justAfter = ServerTime . justAfterUTC . withServerTime where justAfterUTC time = let UTCTime d t = time in UTCTime d (succ t) -- | Obtain a time value that is just moments before the input time; -- see the comment for the 'justAfter' function for more details. justBefore :: ServerTime -> ServerTime justBefore = ServerTime . justBeforeUTC . withServerTime where justBeforeUTC time = let UTCTime d t = time in UTCTime d (pred t) -- | The timestamp for the start of the day associated with the input -- timestamp. If timezone information is supplied, then the returned -- value will correspond to when the day started in that timezone; -- otherwise it is the start of the day in a timezone aligned with -- UTC. startOfDay :: Maybe TimeZoneSeries -> UTCTime -> UTCTime startOfDay Nothing time = let UTCTime d _ = time in UTCTime d 0 startOfDay (Just tz) time = let lt = utcToLocalTime' tz time ls = LocalTime (localDay lt) (TimeOfDay 0 0 0) in localTimeToUTC' tz ls -- | Convert a UTC time value to a local time. asLocalTime :: TimeZoneSeries -> UTCTime -> LocalTime asLocalTime = utcToLocalTime' -- | Local time in displayable format localTimeText :: Text -> LocalTime -> Text localTimeText fmt time = T.pack $ formatTime defaultTimeLocale (T.unpack fmt) time -- | Provides a time value that can be used when there are no other times available originTime :: UTCTime originTime = UTCTime (toEnum 0) 0