{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
module Data.Time.Quote
( utcTime
, day
, timeOfDay
, localTime
, timeZone
, zonedTime
, calendarDiffDays
, calendarDiffTime
) where
import qualified Data.Char as Char
import qualified Data.List as List
import Data.Time
( CalendarDiffDays(..), CalendarDiffTime(..), Day, LocalTime, TimeOfDay
, TimeZone, UTCTime, ZonedTime )
import Data.Time.Format.ISO8601 (ISO8601)
import qualified Data.Time.Format.ISO8601 as Time
import Language.Haskell.TH.Lib
import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Quote (QuasiQuoter(..))
utcTime :: QuasiQuoter
utcTime =
QuasiQuoter
{ quoteExp = \str -> parse @UTCTime str >>= liftData
, quotePat = \_ -> fail "utcTime: cannot quote pattern!"
, quoteType = \_ -> fail "utcTime: cannot quote type!"
, quoteDec = \_ -> fail "utcTime: cannot quote declaration!"
}
day :: QuasiQuoter
day =
QuasiQuoter
{ quoteExp = \str -> parse @Day str >>= liftData
, quotePat = \_ -> fail "day: cannot quote pattern!"
, quoteType = \_ -> fail "day: cannot quote type!"
, quoteDec = \_ -> fail "day: cannot quote declaration!"
}
timeOfDay :: QuasiQuoter
timeOfDay =
QuasiQuoter
{ quoteExp = \str -> parse @TimeOfDay str >>= liftData
, quotePat = \_ -> fail "timeOfDay: cannot quote pattern!"
, quoteType = \_ -> fail "timeOfDay: cannot quote type!"
, quoteDec = \_ -> fail "timeOfDay: cannot quote declaration!"
}
localTime :: QuasiQuoter
localTime =
QuasiQuoter
{ quoteExp = \str -> parse @LocalTime str >>= liftData
, quotePat = \_ -> fail "localTime: cannot quote pattern!"
, quoteType = \_ -> fail "localTime: cannot quote type!"
, quoteDec = \_ -> fail "localTime: cannot quote declaration!"
}
timeZone :: QuasiQuoter
timeZone =
QuasiQuoter
{ quoteExp = \str -> parse @TimeZone str >>= liftData
, quotePat = \_ -> fail "timeZone: cannot quote pattern!"
, quoteType = \_ -> fail "timeZone: cannot quote type!"
, quoteDec = \_ -> fail "timeZone: cannot quote declaration!"
}
zonedTime :: QuasiQuoter
zonedTime =
QuasiQuoter
{ quoteExp = \str -> parse @ZonedTime str >>= liftData
, quotePat = \_ -> fail "zonedTime: cannot quote pattern!"
, quoteType = \_ -> fail "zonedTime: cannot quote type!"
, quoteDec = \_ -> fail "zonedTime: cannot quote declaration!"
}
calendarDiffDays :: QuasiQuoter
calendarDiffDays =
QuasiQuoter
{ quoteExp = \str -> parse @CalendarDiffDays str >>= lift
, quotePat = \_ -> fail "calendarDiffDays: cannot quote pattern!"
, quoteType = \_ -> fail "calendarDiffDays: cannot quote type!"
, quoteDec = \_ -> fail "calendarDiffDays: cannot quote declaration!"
}
where
lift CalendarDiffDays {..} =
[|
CalendarDiffDays
{ cdMonths = $(liftData cdMonths)
, cdDays = $(liftData cdDays)
}
|]
calendarDiffTime :: QuasiQuoter
calendarDiffTime =
QuasiQuoter
{ quoteExp = \str -> parse @CalendarDiffTime str >>= lift
, quotePat = \_ -> fail "calendarDiffTime: cannot quote pattern!"
, quoteType = \_ -> fail "calendarDiffTime: cannot quote type!"
, quoteDec = \_ -> fail "calendarDiffTime: cannot quote declaration!"
}
where
lift CalendarDiffTime {..} =
[|
CalendarDiffTime
{ ctMonths = $(liftData ctMonths)
, ctTime = $(liftData ctTime)
}
|]
parse :: ISO8601 t => String -> Q t
parse = Time.iso8601ParseM . strip
where
strip = List.dropWhileEnd Char.isSpace . List.dropWhile Char.isSpace