Skip to content

Instantly share code, notes, and snippets.

@friedbrice
Last active April 4, 2024 16:09
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save friedbrice/f9566173436e1697eba4912047a369cd to your computer and use it in GitHub Desktop.
Save friedbrice/f9566173436e1697eba4912047a369cd to your computer and use it in GitHub Desktop.
Haskell Time Crib Sheet
-- ghcid -c'stack repl --resolver nightly --package time' haskell-time.hs --allow-eval
----
-- # Haskell Time Crib Sheet
----
-- Excellent sources for this small guide include:
--
-- * https://two-wrongs.com/haskell-time-library-tutorial.html
-- * https://williamyaoh.com/posts/2019-09-16-time-cheatsheet.html
-- * https://wiki.haskell.org/Time
-- * https://hackage.haskell.org/package/time-1.10/docs/Data-Time.html
{-# LANGUAGE DisambiguateRecordFields, NamedFieldPuns #-}
import Control.Applicative ((<|>))
import Data.Fixed (Pico)
import qualified Data.Time as T
import qualified Data.Time.Format.ISO8601 as T
(formatShow, iso8601Format, formatParseM)
----
-- ## Basics
-- ### Get the current UTC time
getCurrentTime :: IO T.UTCTime
getCurrentTime = T.getCurrentTime
-- $> getCurrentTime
-- ### Print UTC time as ISO-8601
printIso8601 :: T.UTCTime -> String
printIso8601 utct = T.formatShow T.iso8601Format utct
-- $> printIso8601 <$> getCurrentTime
-- ### Parse UTC time from ISO-8601
parseUtcIso8601 :: String -> Maybe T.UTCTime
parseUtcIso8601 raw =
parseNoOffset raw <|> parseWithOffset raw
where
parseNoOffset =
T.formatParseM T.iso8601Format
parseWithOffset =
fmap T.zonedTimeToUTC . T.formatParseM T.iso8601Format
-- $> parseUtcIso8601 "2012-01-23T00:00:00Z"
-- $> parseUtcIso8601 "2012-01-23T00:00:00+00:00"
-- $> parseUtcIso8601 "2012-01-23T00:00:00-07:00"
----
-- ## Manipulation
-- ### Add (or subtract) seconds (or minutes or hours) to UTC time
addSeconds :: Integer -> T.UTCTime -> T.UTCTime
addSeconds n utct = T.addUTCTime (fromInteger n) utct
-- $> addSeconds (60 * 60 * 2) <$> getCurrentTime
-- ### Add (or subtract) days (or weeks) to UTC time
addDays :: Integer -> T.UTCTime -> T.UTCTime
addDays n utct = T.addUTCTime (fromInteger n * T.nominalDay) utct
-- $> addDays (-1 * 7 * 2) <$> getCurrentTime
-- ### Add (or subtract) months (or years) to UTC time
addMonths :: Integer -> T.UTCTime -> T.UTCTime
addMonths n utct =
let
lt@T.LocalTime{ localDay } = T.utcToLocalTime T.utc utct
localDay' = T.addGregorianMonthsClip n localDay
in
T.localTimeToUTC T.utc lt{ T.localDay = localDay' }
-- $> addMonths (-2) <$> getCurrentTime
----
-- ## Local Time
-- ### Get local date
getLocalDate :: T.TimeZone -> T.UTCTime -> (Integer, Int, Int)
getLocalDate tz utct =
let
T.LocalTime{ localDay } = T.utcToLocalTime tz utct
in
T.toGregorian localDay
-- $> getLocalDate (read "PDT") <$> getCurrentTime
-- ### Get local time
getLocalTime :: T.TimeZone -> T.UTCTime -> (Int, Int, Pico)
getLocalTime tz utct =
let
T.LocalTime{ localTimeOfDay } = T.utcToLocalTime tz utct
T.TimeOfDay{ todHour, todMin, todSec } = localTimeOfDay
in
(todHour, todMin, todSec)
-- $> getLocalTime (read "PDT") <$> getCurrentTime
-- ### Get local day of week
getLocalDayOfWeek :: T.TimeZone -> T.UTCTime -> T.DayOfWeek
getLocalDayOfWeek tz utct =
let
T.LocalTime{ localDay } = T.utcToLocalTime tz utct
in
T.dayOfWeek localDay
-- $> getLocalDayOfWeek (read "PDT") <$> getCurrentTime
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment