{-# LANGUAGE Safe #-}

module Data.Time.Format.ISO8601
    (
        -- * Format
      Format
    , formatShowM
    , formatShow
    , formatReadP
    , formatParseM
        -- * Common formats
    , ISO8601(..)
    , iso8601Show
    , iso8601ParseM
        -- * All formats
    , FormatExtension(..)
    , formatReadPExtension
    , parseFormatExtension
    , calendarFormat
    , yearMonthFormat
    , yearFormat
    , centuryFormat
    , expandedCalendarFormat
    , expandedYearMonthFormat
    , expandedYearFormat
    , expandedCenturyFormat
    , ordinalDateFormat
    , expandedOrdinalDateFormat
    , weekDateFormat
    , yearWeekFormat
    , expandedWeekDateFormat
    , expandedYearWeekFormat
    , timeOfDayFormat
    , hourMinuteFormat
    , hourFormat
    , withTimeDesignator
    , withUTCDesignator
    , timeOffsetFormat
    , timeOfDayAndOffsetFormat
    , localTimeFormat
    , zonedTimeFormat
    , utcTimeFormat
    , dayAndTimeFormat
    , timeAndOffsetFormat
    , durationDaysFormat
    , durationTimeFormat
    , alternativeDurationDaysFormat
    , alternativeDurationTimeFormat
    , intervalFormat
    , recurringIntervalFormat
    ) where

import Control.Monad.Fail
import Data.Fixed
import Data.Format
import Data.Ratio
import Data.Time
import Data.Time.Calendar.OrdinalDate
import Data.Time.Calendar.Private
import Data.Time.Calendar.WeekDate
import Prelude hiding (fail)
import Text.ParserCombinators.ReadP

data FormatExtension
    = 
    -- | ISO 8601:2004(E) sec. 2.3.4. Use hyphens and colons.
      ExtendedFormat
    -- | ISO 8601:2004(E) sec. 2.3.3. Omit hyphens and colons. "The basic format should be avoided in plain text."
    | BasicFormat

-- | Read a value in either extended or basic format
formatReadPExtension :: (FormatExtension -> Format t) -> ReadP t
formatReadPExtension :: forall t. (FormatExtension -> Format t) -> ReadP t
formatReadPExtension FormatExtension -> Format t
ff = forall t. Format t -> ReadP t
formatReadP (FormatExtension -> Format t
ff FormatExtension
ExtendedFormat) forall a. ReadP a -> ReadP a -> ReadP a
+++ forall t. Format t -> ReadP t
formatReadP (FormatExtension -> Format t
ff FormatExtension
BasicFormat)

-- | Parse a value in either extended or basic format
parseFormatExtension :: (MonadFail m) => (FormatExtension -> Format t) -> String -> m t
parseFormatExtension :: forall (m :: * -> *) t.
MonadFail m =>
(FormatExtension -> Format t) -> String -> m t
parseFormatExtension FormatExtension -> Format t
ff = forall (m :: * -> *) t. MonadFail m => ReadP t -> String -> m t
parseReader forall a b. (a -> b) -> a -> b
$ forall t. (FormatExtension -> Format t) -> ReadP t
formatReadPExtension FormatExtension -> Format t
ff

sepFormat :: String -> Format a -> Format b -> Format (a, b)
sepFormat :: forall a b. String -> Format a -> Format b -> Format (a, b)
sepFormat String
sep Format a
fa Format b
fb = (Format a
fa forall (f :: * -> *) a. Productish f => f a -> f () -> f a
<** String -> Format ()
literalFormat String
sep) forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> Format b
fb

dashFormat :: Format a -> Format b -> Format (a, b)
dashFormat :: forall a b. Format a -> Format b -> Format (a, b)
dashFormat = forall a b. String -> Format a -> Format b -> Format (a, b)
sepFormat String
"-"

colnFormat :: Format a -> Format b -> Format (a, b)
colnFormat :: forall a b. Format a -> Format b -> Format (a, b)
colnFormat = forall a b. String -> Format a -> Format b -> Format (a, b)
sepFormat String
":"

extDashFormat :: FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat :: forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
ExtendedFormat = forall a b. Format a -> Format b -> Format (a, b)
dashFormat
extDashFormat FormatExtension
BasicFormat = forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
(<**>)

extColonFormat :: FormatExtension -> Format a -> Format b -> Format (a, b)
extColonFormat :: forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extColonFormat FormatExtension
ExtendedFormat = forall a b. Format a -> Format b -> Format (a, b)
colnFormat
extColonFormat FormatExtension
BasicFormat = forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
(<**>)

expandedYearFormat' :: Int -> Format Integer
expandedYearFormat' :: Int -> Format Integer
expandedYearFormat' Int
n = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
PosNegSign (forall a. a -> Maybe a
Just Int
n)

yearFormat' :: Format Integer
yearFormat' :: Format Integer
yearFormat' = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NegSign (forall a. a -> Maybe a
Just Int
4)

monthFormat :: Format Int
monthFormat :: Format Int
monthFormat = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NoSign (forall a. a -> Maybe a
Just Int
2)

dayOfMonthFormat :: Format Int
dayOfMonthFormat :: Format Int
dayOfMonthFormat = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NoSign (forall a. a -> Maybe a
Just Int
2)

dayOfYearFormat :: Format Int
dayOfYearFormat :: Format Int
dayOfYearFormat = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NoSign (forall a. a -> Maybe a
Just Int
3)

weekOfYearFormat :: Format Int
weekOfYearFormat :: Format Int
weekOfYearFormat = String -> Format ()
literalFormat String
"W" forall (f :: * -> *) a. Productish f => f () -> f a -> f a
**> forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NoSign (forall a. a -> Maybe a
Just Int
2)

dayOfWeekFormat :: Format Int
dayOfWeekFormat :: Format Int
dayOfWeekFormat = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NoSign (forall a. a -> Maybe a
Just Int
1)

hourFormat' :: Format Int
hourFormat' :: Format Int
hourFormat' = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NoSign (forall a. a -> Maybe a
Just Int
2)

data E14

instance HasResolution E14 where
    resolution :: forall (p :: * -> *). p E14 -> Integer
resolution p E14
_ = Integer
100000000000000

data E16

instance HasResolution E16 where
    resolution :: forall (p :: * -> *). p E16 -> Integer
resolution p E16
_ = Integer
10000000000000000

hourDecimalFormat :: Format (Fixed E16) -- need four extra decimal places for hours
hourDecimalFormat :: Format (Fixed E16)
hourDecimalFormat = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
decimalFormat SignOption
NoSign (forall a. a -> Maybe a
Just Int
2)

minuteFormat :: Format Int
minuteFormat :: Format Int
minuteFormat = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NoSign (forall a. a -> Maybe a
Just Int
2)

minuteDecimalFormat :: Format (Fixed E14) -- need two extra decimal places for minutes
minuteDecimalFormat :: Format (Fixed E14)
minuteDecimalFormat = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
decimalFormat SignOption
NoSign (forall a. a -> Maybe a
Just Int
2)

secondFormat :: Format Pico
secondFormat :: Format Pico
secondFormat = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
decimalFormat SignOption
NoSign (forall a. a -> Maybe a
Just Int
2)

mapGregorian :: Format (Integer, (Int, Int)) -> Format Day
mapGregorian :: Format (Integer, (Int, Int)) -> Format Day
mapGregorian =
    forall a b.
(a -> Maybe b) -> (b -> Maybe a) -> Format a -> Format b
mapMFormat (\(Integer
y, (Int
m, Int
d)) -> Integer -> Int -> Int -> Maybe Day
fromGregorianValid Integer
y Int
m Int
d) (\Day
day -> (\(Integer
y, Int
m, Int
d) -> forall a. a -> Maybe a
Just (Integer
y, (Int
m, Int
d))) forall a b. (a -> b) -> a -> b
$ Day -> (Integer, Int, Int)
toGregorian Day
day)

mapOrdinalDate :: Format (Integer, Int) -> Format Day
mapOrdinalDate :: Format (Integer, Int) -> Format Day
mapOrdinalDate = forall a b.
(a -> Maybe b) -> (b -> Maybe a) -> Format a -> Format b
mapMFormat (\(Integer
y, Int
d) -> Integer -> Int -> Maybe Day
fromOrdinalDateValid Integer
y Int
d) (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. Day -> (Integer, Int)
toOrdinalDate)

mapWeekDate :: Format (Integer, (Int, Int)) -> Format Day
mapWeekDate :: Format (Integer, (Int, Int)) -> Format Day
mapWeekDate =
    forall a b.
(a -> Maybe b) -> (b -> Maybe a) -> Format a -> Format b
mapMFormat (\(Integer
y, (Int
w, Int
d)) -> Integer -> Int -> Int -> Maybe Day
fromWeekDateValid Integer
y Int
w Int
d) (\Day
day -> (\(Integer
y, Int
w, Int
d) -> forall a. a -> Maybe a
Just (Integer
y, (Int
w, Int
d))) forall a b. (a -> b) -> a -> b
$ Day -> (Integer, Int, Int)
toWeekDate Day
day)

mapTimeOfDay :: Format (Int, (Int, Pico)) -> Format TimeOfDay
mapTimeOfDay :: Format (Int, (Int, Pico)) -> Format TimeOfDay
mapTimeOfDay = forall a b.
(a -> Maybe b) -> (b -> Maybe a) -> Format a -> Format b
mapMFormat (\(Int
h, (Int
m, Pico
s)) -> Int -> Int -> Pico -> Maybe TimeOfDay
makeTimeOfDayValid Int
h Int
m Pico
s) (\(TimeOfDay Int
h Int
m Pico
s) -> forall a. a -> Maybe a
Just (Int
h, (Int
m, Pico
s)))

-- | ISO 8601:2004(E) sec. 4.1.2.2
calendarFormat :: FormatExtension -> Format Day
calendarFormat :: FormatExtension -> Format Day
calendarFormat FormatExtension
fe = Format (Integer, (Int, Int)) -> Format Day
mapGregorian forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe Format Integer
yearFormat forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe Format Int
monthFormat Format Int
dayOfMonthFormat

-- | ISO 8601:2004(E) sec. 4.1.2.3(a)
yearMonthFormat :: Format (Integer, Int)
yearMonthFormat :: Format (Integer, Int)
yearMonthFormat = Format Integer
yearFormat forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> String -> Format ()
literalFormat String
"-" forall (f :: * -> *) a. Productish f => f () -> f a -> f a
**> Format Int
monthFormat

-- | ISO 8601:2004(E) sec. 4.1.2.3(b)
yearFormat :: Format Integer
yearFormat :: Format Integer
yearFormat = Format Integer
yearFormat'

-- | ISO 8601:2004(E) sec. 4.1.2.3(c)
centuryFormat :: Format Integer
centuryFormat :: Format Integer
centuryFormat = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NegSign (forall a. a -> Maybe a
Just Int
2)

-- | ISO 8601:2004(E) sec. 4.1.2.4(a)
expandedCalendarFormat :: Int -> FormatExtension -> Format Day
expandedCalendarFormat :: Int -> FormatExtension -> Format Day
expandedCalendarFormat Int
n FormatExtension
fe =
    Format (Integer, (Int, Int)) -> Format Day
mapGregorian forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe (Int -> Format Integer
expandedYearFormat Int
n) forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe Format Int
monthFormat Format Int
dayOfMonthFormat

-- | ISO 8601:2004(E) sec. 4.1.2.4(b)
expandedYearMonthFormat :: Int -> Format (Integer, Int)
expandedYearMonthFormat :: Int -> Format (Integer, Int)
expandedYearMonthFormat Int
n = forall a b. Format a -> Format b -> Format (a, b)
dashFormat (Int -> Format Integer
expandedYearFormat Int
n) Format Int
monthFormat

-- | ISO 8601:2004(E) sec. 4.1.2.4(c)
expandedYearFormat :: Int -> Format Integer
expandedYearFormat :: Int -> Format Integer
expandedYearFormat = Int -> Format Integer
expandedYearFormat'

-- | ISO 8601:2004(E) sec. 4.1.2.4(d)
expandedCenturyFormat :: Int -> Format Integer
expandedCenturyFormat :: Int -> Format Integer
expandedCenturyFormat Int
n = forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
PosNegSign (forall a. a -> Maybe a
Just Int
n)

-- | ISO 8601:2004(E) sec. 4.1.3.2
ordinalDateFormat :: FormatExtension -> Format Day
ordinalDateFormat :: FormatExtension -> Format Day
ordinalDateFormat FormatExtension
fe = Format (Integer, Int) -> Format Day
mapOrdinalDate forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe Format Integer
yearFormat Format Int
dayOfYearFormat

-- | ISO 8601:2004(E) sec. 4.1.3.3
expandedOrdinalDateFormat :: Int -> FormatExtension -> Format Day
expandedOrdinalDateFormat :: Int -> FormatExtension -> Format Day
expandedOrdinalDateFormat Int
n FormatExtension
fe = Format (Integer, Int) -> Format Day
mapOrdinalDate forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe (Int -> Format Integer
expandedYearFormat Int
n) Format Int
dayOfYearFormat

-- | ISO 8601:2004(E) sec. 4.1.4.2
weekDateFormat :: FormatExtension -> Format Day
weekDateFormat :: FormatExtension -> Format Day
weekDateFormat FormatExtension
fe = Format (Integer, (Int, Int)) -> Format Day
mapWeekDate forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe Format Integer
yearFormat forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe Format Int
weekOfYearFormat Format Int
dayOfWeekFormat

-- | ISO 8601:2004(E) sec. 4.1.4.3
yearWeekFormat :: FormatExtension -> Format (Integer, Int)
yearWeekFormat :: FormatExtension -> Format (Integer, Int)
yearWeekFormat FormatExtension
fe = forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe Format Integer
yearFormat Format Int
weekOfYearFormat

-- | ISO 8601:2004(E) sec. 4.1.4.2
expandedWeekDateFormat :: Int -> FormatExtension -> Format Day
expandedWeekDateFormat :: Int -> FormatExtension -> Format Day
expandedWeekDateFormat Int
n FormatExtension
fe =
    Format (Integer, (Int, Int)) -> Format Day
mapWeekDate forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe (Int -> Format Integer
expandedYearFormat Int
n) forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe Format Int
weekOfYearFormat Format Int
dayOfWeekFormat

-- | ISO 8601:2004(E) sec. 4.1.4.3
expandedYearWeekFormat :: Int -> FormatExtension -> Format (Integer, Int)
expandedYearWeekFormat :: Int -> FormatExtension -> Format (Integer, Int)
expandedYearWeekFormat Int
n FormatExtension
fe = forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe (Int -> Format Integer
expandedYearFormat Int
n) Format Int
weekOfYearFormat

-- | ISO 8601:2004(E) sec. 4.2.2.2, 4.2.2.4(a)
timeOfDayFormat :: FormatExtension -> Format TimeOfDay
timeOfDayFormat :: FormatExtension -> Format TimeOfDay
timeOfDayFormat FormatExtension
fe = Format (Int, (Int, Pico)) -> Format TimeOfDay
mapTimeOfDay forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extColonFormat FormatExtension
fe Format Int
hourFormat' forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extColonFormat FormatExtension
fe Format Int
minuteFormat Format Pico
secondFormat

-- workaround for the 'fromRational' in 'Fixed', which uses 'floor' instead of 'round'
fromRationalRound :: Rational -> NominalDiffTime
fromRationalRound :: Rational -> NominalDiffTime
fromRationalRound Rational
r = forall a. Fractional a => Rational -> a
fromRational forall a b. (a -> b) -> a -> b
$ forall a b. (RealFrac a, Integral b) => a -> b
round (Rational
r forall a. Num a => a -> a -> a
* Rational
1000000000000) forall a. Integral a => a -> a -> Ratio a
% Integer
1000000000000

-- | ISO 8601:2004(E) sec. 4.2.2.3(a), 4.2.2.4(b)
hourMinuteFormat :: FormatExtension -> Format TimeOfDay
hourMinuteFormat :: FormatExtension -> Format TimeOfDay
hourMinuteFormat FormatExtension
fe = let
    toTOD :: (a, a) -> Maybe TimeOfDay
toTOD (a
h, a
m) =
        case NominalDiffTime -> (Integer, TimeOfDay)
timeToDaysAndTimeOfDay forall a b. (a -> b) -> a -> b
$ Rational -> NominalDiffTime
fromRationalRound forall a b. (a -> b) -> a -> b
$ forall a. Real a => a -> Rational
toRational forall a b. (a -> b) -> a -> b
$ (forall a b. (Integral a, Num b) => a -> b
fromIntegral a
h) forall a. Num a => a -> a -> a
* a
3600 forall a. Num a => a -> a -> a
+ a
m forall a. Num a => a -> a -> a
* a
60 of
            (Integer
0, TimeOfDay
tod) -> forall a. a -> Maybe a
Just TimeOfDay
tod
            (Integer, TimeOfDay)
_ -> forall a. Maybe a
Nothing
    fromTOD :: TimeOfDay -> Maybe (b, a)
fromTOD TimeOfDay
tod = let
        mm :: a
mm = (forall a b. (Real a, Fractional b) => a -> b
realToFrac forall a b. (a -> b) -> a -> b
$ Integer -> TimeOfDay -> NominalDiffTime
daysAndTimeOfDayToTime Integer
0 TimeOfDay
tod) forall a. Fractional a => a -> a -> a
/ a
60
        in forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ forall a b. (Real a, Integral b) => a -> a -> (b, a)
quotRemBy a
60 a
mm
    in forall a b.
(a -> Maybe b) -> (b -> Maybe a) -> Format a -> Format b
mapMFormat forall {a} {a}. (Integral a, Real a) => (a, a) -> Maybe TimeOfDay
toTOD forall {b} {a}.
(Integral b, Real a, Fractional a) =>
TimeOfDay -> Maybe (b, a)
fromTOD forall a b. (a -> b) -> a -> b
$ forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extColonFormat FormatExtension
fe Format Int
hourFormat' forall a b. (a -> b) -> a -> b
$ Format (Fixed E14)
minuteDecimalFormat

-- | ISO 8601:2004(E) sec. 4.2.2.3(b), 4.2.2.4(c)
hourFormat :: Format TimeOfDay
hourFormat :: Format TimeOfDay
hourFormat = let
    toTOD :: a -> Maybe TimeOfDay
toTOD a
h =
        case NominalDiffTime -> (Integer, TimeOfDay)
timeToDaysAndTimeOfDay forall a b. (a -> b) -> a -> b
$ Rational -> NominalDiffTime
fromRationalRound forall a b. (a -> b) -> a -> b
$ forall a. Real a => a -> Rational
toRational forall a b. (a -> b) -> a -> b
$ a
h forall a. Num a => a -> a -> a
* a
3600 of
            (Integer
0, TimeOfDay
tod) -> forall a. a -> Maybe a
Just TimeOfDay
tod
            (Integer, TimeOfDay)
_ -> forall a. Maybe a
Nothing
    fromTOD :: TimeOfDay -> Maybe a
fromTOD TimeOfDay
tod = forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ (forall a b. (Real a, Fractional b) => a -> b
realToFrac forall a b. (a -> b) -> a -> b
$ Integer -> TimeOfDay -> NominalDiffTime
daysAndTimeOfDayToTime Integer
0 TimeOfDay
tod) forall a. Fractional a => a -> a -> a
/ a
3600
    in forall a b.
(a -> Maybe b) -> (b -> Maybe a) -> Format a -> Format b
mapMFormat forall {a}. Real a => a -> Maybe TimeOfDay
toTOD forall {a}. Fractional a => TimeOfDay -> Maybe a
fromTOD forall a b. (a -> b) -> a -> b
$ Format (Fixed E16)
hourDecimalFormat

-- | ISO 8601:2004(E) sec. 4.2.2.5
withTimeDesignator :: Format t -> Format t
withTimeDesignator :: forall t. Format t -> Format t
withTimeDesignator Format t
f = String -> Format ()
literalFormat String
"T" forall (f :: * -> *) a. Productish f => f () -> f a -> f a
**> Format t
f

-- | ISO 8601:2004(E) sec. 4.2.4
withUTCDesignator :: Format t -> Format t
withUTCDesignator :: forall t. Format t -> Format t
withUTCDesignator Format t
f = Format t
f forall (f :: * -> *) a. Productish f => f a -> f () -> f a
<** String -> Format ()
literalFormat String
"Z"

-- | ISO 8601:2004(E) sec. 4.2.5.1
timeOffsetFormat :: FormatExtension -> Format TimeZone
timeOffsetFormat :: FormatExtension -> Format TimeZone
timeOffsetFormat FormatExtension
fe = let
    toTimeZone :: (Int, (Int, Int)) -> TimeZone
toTimeZone (Int
sign, (Int
h, Int
m)) = Int -> TimeZone
minutesToTimeZone forall a b. (a -> b) -> a -> b
$ Int
sign forall a. Num a => a -> a -> a
* (Int
h forall a. Num a => a -> a -> a
* Int
60 forall a. Num a => a -> a -> a
+ Int
m)
    fromTimeZone :: TimeZone -> (Int, (Int, Int))
fromTimeZone TimeZone
tz = let
        mm :: Int
mm = TimeZone -> Int
timeZoneMinutes TimeZone
tz
        hm :: (Int, Int)
hm = forall a. Integral a => a -> a -> (a, a)
quotRem (forall a. Num a => a -> a
abs Int
mm) Int
60
        in (forall a. Num a => a -> a
signum Int
mm, (Int, Int)
hm)
    in forall (f :: * -> *) a b.
IsoVariant f =>
(a -> b) -> (b -> a) -> f a -> f b
isoMap (Int, (Int, Int)) -> TimeZone
toTimeZone TimeZone -> (Int, (Int, Int))
fromTimeZone forall a b. (a -> b) -> a -> b
$
       forall t. (Eq t, Num t) => Format t
mandatorySignFormat forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extColonFormat FormatExtension
fe (forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NoSign (forall a. a -> Maybe a
Just Int
2)) (forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NoSign (forall a. a -> Maybe a
Just Int
2))

-- | ISO 8601:2004(E) sec. 4.2.5.2
timeOfDayAndOffsetFormat :: FormatExtension -> Format (TimeOfDay, TimeZone)
timeOfDayAndOffsetFormat :: FormatExtension -> Format (TimeOfDay, TimeZone)
timeOfDayAndOffsetFormat FormatExtension
fe = FormatExtension -> Format TimeOfDay
timeOfDayFormat FormatExtension
fe forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> FormatExtension -> Format TimeZone
timeOffsetFormat FormatExtension
fe

-- | ISO 8601:2004(E) sec. 4.3.2
localTimeFormat :: Format Day -> Format TimeOfDay -> Format LocalTime
localTimeFormat :: Format Day -> Format TimeOfDay -> Format LocalTime
localTimeFormat Format Day
fday Format TimeOfDay
ftod =
    forall (f :: * -> *) a b.
IsoVariant f =>
(a -> b) -> (b -> a) -> f a -> f b
isoMap (\(Day
day, TimeOfDay
tod) -> Day -> TimeOfDay -> LocalTime
LocalTime Day
day TimeOfDay
tod) (\(LocalTime Day
day TimeOfDay
tod) -> (Day
day, TimeOfDay
tod)) forall a b. (a -> b) -> a -> b
$ Format Day
fday forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> forall t. Format t -> Format t
withTimeDesignator Format TimeOfDay
ftod

-- | ISO 8601:2004(E) sec. 4.3.2
zonedTimeFormat :: Format Day -> Format TimeOfDay -> FormatExtension -> Format ZonedTime
zonedTimeFormat :: Format Day
-> Format TimeOfDay -> FormatExtension -> Format ZonedTime
zonedTimeFormat Format Day
fday Format TimeOfDay
ftod FormatExtension
fe =
    forall (f :: * -> *) a b.
IsoVariant f =>
(a -> b) -> (b -> a) -> f a -> f b
isoMap (\(LocalTime
lt, TimeZone
tz) -> LocalTime -> TimeZone -> ZonedTime
ZonedTime LocalTime
lt TimeZone
tz) (\(ZonedTime LocalTime
lt TimeZone
tz) -> (LocalTime
lt, TimeZone
tz)) forall a b. (a -> b) -> a -> b
$
    forall t. Format t -> FormatExtension -> Format (t, TimeZone)
timeAndOffsetFormat (Format Day -> Format TimeOfDay -> Format LocalTime
localTimeFormat Format Day
fday Format TimeOfDay
ftod) FormatExtension
fe

-- | ISO 8601:2004(E) sec. 4.3.2
utcTimeFormat :: Format Day -> Format TimeOfDay -> Format UTCTime
utcTimeFormat :: Format Day -> Format TimeOfDay -> Format UTCTime
utcTimeFormat Format Day
fday Format TimeOfDay
ftod =
    forall (f :: * -> *) a b.
IsoVariant f =>
(a -> b) -> (b -> a) -> f a -> f b
isoMap (TimeZone -> LocalTime -> UTCTime
localTimeToUTC TimeZone
utc) (TimeZone -> UTCTime -> LocalTime
utcToLocalTime TimeZone
utc) forall a b. (a -> b) -> a -> b
$ forall t. Format t -> Format t
withUTCDesignator forall a b. (a -> b) -> a -> b
$ Format Day -> Format TimeOfDay -> Format LocalTime
localTimeFormat Format Day
fday Format TimeOfDay
ftod

-- | ISO 8601:2004(E) sec. 4.3.3
dayAndTimeFormat :: Format Day -> Format time -> Format (Day, time)
dayAndTimeFormat :: forall time. Format Day -> Format time -> Format (Day, time)
dayAndTimeFormat Format Day
fday Format time
ft = Format Day
fday forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> forall t. Format t -> Format t
withTimeDesignator Format time
ft

-- | ISO 8601:2004(E) sec. 4.3.3
timeAndOffsetFormat :: Format t -> FormatExtension -> Format (t, TimeZone)
timeAndOffsetFormat :: forall t. Format t -> FormatExtension -> Format (t, TimeZone)
timeAndOffsetFormat Format t
ft FormatExtension
fe = Format t
ft forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> FormatExtension -> Format TimeZone
timeOffsetFormat FormatExtension
fe

intDesignator :: (Eq t, Show t, Read t, Num t) => Char -> Format t
intDesignator :: forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
intDesignator Char
c = forall a. Eq a => a -> Format a -> Format a
optionalFormat t
0 forall a b. (a -> b) -> a -> b
$ forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NoSign forall a. Maybe a
Nothing forall (f :: * -> *) a. Productish f => f a -> f () -> f a
<** String -> Format ()
literalFormat [Char
c]

decDesignator :: (Eq t, Show t, Read t, Num t) => Char -> Format t
decDesignator :: forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
decDesignator Char
c = forall a. Eq a => a -> Format a -> Format a
optionalFormat t
0 forall a b. (a -> b) -> a -> b
$ forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
decimalFormat SignOption
NoSign forall a. Maybe a
Nothing forall (f :: * -> *) a. Productish f => f a -> f () -> f a
<** String -> Format ()
literalFormat [Char
c]

daysDesigs :: Format CalendarDiffDays
daysDesigs :: Format CalendarDiffDays
daysDesigs = let
    toCD :: (Integer, (Integer, (Integer, Integer))) -> CalendarDiffDays
toCD (Integer
y, (Integer
m, (Integer
w, Integer
d))) = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays (Integer
y forall a. Num a => a -> a -> a
* Integer
12 forall a. Num a => a -> a -> a
+ Integer
m) (Integer
w forall a. Num a => a -> a -> a
* Integer
7 forall a. Num a => a -> a -> a
+ Integer
d)
    fromCD :: CalendarDiffDays -> (Integer, (Integer, (a, Integer)))
fromCD (CalendarDiffDays Integer
mm Integer
d) = (forall a. Integral a => a -> a -> a
quot Integer
mm Integer
12, (forall a. Integral a => a -> a -> a
rem Integer
mm Integer
12, (a
0, Integer
d)))
    in forall (f :: * -> *) a b.
IsoVariant f =>
(a -> b) -> (b -> a) -> f a -> f b
isoMap (Integer, (Integer, (Integer, Integer))) -> CalendarDiffDays
toCD forall {a}.
Num a =>
CalendarDiffDays -> (Integer, (Integer, (a, Integer)))
fromCD forall a b. (a -> b) -> a -> b
$ forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
intDesignator Char
'Y' forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
intDesignator Char
'M' forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
intDesignator Char
'W' forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
intDesignator Char
'D'

-- | ISO 8601:2004(E) sec. 4.4.3.2
durationDaysFormat :: Format CalendarDiffDays
durationDaysFormat :: Format CalendarDiffDays
durationDaysFormat = forall (f :: * -> *) a. Productish f => f () -> f a -> f a
(**>) (String -> Format ()
literalFormat String
"P") forall a b. (a -> b) -> a -> b
$ forall a. Eq a => (a, String) -> Format a -> Format a
specialCaseShowFormat (forall a. Monoid a => a
mempty, String
"0D") forall a b. (a -> b) -> a -> b
$ Format CalendarDiffDays
daysDesigs

-- | ISO 8601:2004(E) sec. 4.4.3.2
durationTimeFormat :: Format CalendarDiffTime
durationTimeFormat :: Format CalendarDiffTime
durationTimeFormat = let
    toCT :: (CalendarDiffDays, (Int, (Int, Pico))) -> CalendarDiffTime
toCT (CalendarDiffDays
cd, (Int
h, (Int
m, Pico
s))) =
        forall a. Monoid a => a -> a -> a
mappend (CalendarDiffDays -> CalendarDiffTime
calendarTimeDays CalendarDiffDays
cd) (NominalDiffTime -> CalendarDiffTime
calendarTimeTime forall a b. (a -> b) -> a -> b
$ Integer -> TimeOfDay -> NominalDiffTime
daysAndTimeOfDayToTime Integer
0 forall a b. (a -> b) -> a -> b
$ Int -> Int -> Pico -> TimeOfDay
TimeOfDay Int
h Int
m Pico
s)
    fromCT :: CalendarDiffTime -> (CalendarDiffDays, (Int, (Int, Pico)))
fromCT (CalendarDiffTime Integer
mm NominalDiffTime
t) = let
        (Integer
d, TimeOfDay Int
h Int
m Pico
s) = NominalDiffTime -> (Integer, TimeOfDay)
timeToDaysAndTimeOfDay NominalDiffTime
t
        in (Integer -> Integer -> CalendarDiffDays
CalendarDiffDays Integer
mm Integer
d, (Int
h, (Int
m, Pico
s)))
    in forall (f :: * -> *) a. Productish f => f () -> f a -> f a
(**>) (String -> Format ()
literalFormat String
"P") forall a b. (a -> b) -> a -> b
$
       forall a. Eq a => (a, String) -> Format a -> Format a
specialCaseShowFormat (forall a. Monoid a => a
mempty, String
"0D") forall a b. (a -> b) -> a -> b
$
       forall (f :: * -> *) a b.
IsoVariant f =>
(a -> b) -> (b -> a) -> f a -> f b
isoMap (CalendarDiffDays, (Int, (Int, Pico))) -> CalendarDiffTime
toCT CalendarDiffTime -> (CalendarDiffDays, (Int, (Int, Pico)))
fromCT forall a b. (a -> b) -> a -> b
$
       forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
(<**>) Format CalendarDiffDays
daysDesigs forall a b. (a -> b) -> a -> b
$
       forall a. Eq a => a -> Format a -> Format a
optionalFormat (Int
0, (Int
0, Pico
0)) forall a b. (a -> b) -> a -> b
$
       String -> Format ()
literalFormat String
"T" forall (f :: * -> *) a. Productish f => f () -> f a -> f a
**> forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
intDesignator Char
'H' forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
intDesignator Char
'M' forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
decDesignator Char
'S'

-- | ISO 8601:2004(E) sec. 4.4.3.3
alternativeDurationDaysFormat :: FormatExtension -> Format CalendarDiffDays
alternativeDurationDaysFormat :: FormatExtension -> Format CalendarDiffDays
alternativeDurationDaysFormat FormatExtension
fe = let
    toCD :: (Integer, (Integer, Integer)) -> CalendarDiffDays
toCD (Integer
y, (Integer
m, Integer
d)) = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays (Integer
y forall a. Num a => a -> a -> a
* Integer
12 forall a. Num a => a -> a -> a
+ Integer
m) Integer
d
    fromCD :: CalendarDiffDays -> (Integer, (Integer, Integer))
fromCD (CalendarDiffDays Integer
mm Integer
d) = (forall a. Integral a => a -> a -> a
quot Integer
mm Integer
12, (forall a. Integral a => a -> a -> a
rem Integer
mm Integer
12, Integer
d))
    in forall (f :: * -> *) a b.
IsoVariant f =>
(a -> b) -> (b -> a) -> f a -> f b
isoMap (Integer, (Integer, Integer)) -> CalendarDiffDays
toCD CalendarDiffDays -> (Integer, (Integer, Integer))
fromCD forall a b. (a -> b) -> a -> b
$
       forall (f :: * -> *) a. Productish f => f () -> f a -> f a
(**>) (String -> Format ()
literalFormat String
"P") forall a b. (a -> b) -> a -> b
$
       forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe (forall a. Ord a => (a, a) -> Format a -> Format a
clipFormat (Integer
0, Integer
9999) forall a b. (a -> b) -> a -> b
$ forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NegSign forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just Int
4) forall a b. (a -> b) -> a -> b
$
       forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe (forall a. Ord a => (a, a) -> Format a -> Format a
clipFormat (Integer
0, Integer
12) forall a b. (a -> b) -> a -> b
$ forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NegSign forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just Int
2) forall a b. (a -> b) -> a -> b
$
       (forall a. Ord a => (a, a) -> Format a -> Format a
clipFormat (Integer
0, Integer
30) forall a b. (a -> b) -> a -> b
$ forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NegSign forall a b. (a -> b) -> a -> b
$ forall a. a -> Maybe a
Just Int
2)

-- | ISO 8601:2004(E) sec. 4.4.3.3
alternativeDurationTimeFormat :: FormatExtension -> Format CalendarDiffTime
alternativeDurationTimeFormat :: FormatExtension -> Format CalendarDiffTime
alternativeDurationTimeFormat FormatExtension
fe = let
    toCT :: (CalendarDiffDays, (Int, (Int, Pico))) -> CalendarDiffTime
toCT (CalendarDiffDays
cd, (Int
h, (Int
m, Pico
s))) =
        forall a. Monoid a => a -> a -> a
mappend (CalendarDiffDays -> CalendarDiffTime
calendarTimeDays CalendarDiffDays
cd) (NominalDiffTime -> CalendarDiffTime
calendarTimeTime forall a b. (a -> b) -> a -> b
$ Integer -> TimeOfDay -> NominalDiffTime
daysAndTimeOfDayToTime Integer
0 forall a b. (a -> b) -> a -> b
$ Int -> Int -> Pico -> TimeOfDay
TimeOfDay Int
h Int
m Pico
s)
    fromCT :: CalendarDiffTime -> (CalendarDiffDays, (Int, (Int, Pico)))
fromCT (CalendarDiffTime Integer
mm NominalDiffTime
t) = let
        (Integer
d, TimeOfDay Int
h Int
m Pico
s) = NominalDiffTime -> (Integer, TimeOfDay)
timeToDaysAndTimeOfDay NominalDiffTime
t
        in (Integer -> Integer -> CalendarDiffDays
CalendarDiffDays Integer
mm Integer
d, (Int
h, (Int
m, Pico
s)))
    in forall (f :: * -> *) a b.
IsoVariant f =>
(a -> b) -> (b -> a) -> f a -> f b
isoMap (CalendarDiffDays, (Int, (Int, Pico))) -> CalendarDiffTime
toCT CalendarDiffTime -> (CalendarDiffDays, (Int, (Int, Pico)))
fromCT forall a b. (a -> b) -> a -> b
$
       forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
(<**>) (FormatExtension -> Format CalendarDiffDays
alternativeDurationDaysFormat FormatExtension
fe) forall a b. (a -> b) -> a -> b
$
       forall t. Format t -> Format t
withTimeDesignator forall a b. (a -> b) -> a -> b
$
       forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extColonFormat FormatExtension
fe (forall a. Ord a => (a, a) -> Format a -> Format a
clipFormat (Int
0, Int
24) forall a b. (a -> b) -> a -> b
$ forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NegSign (forall a. a -> Maybe a
Just Int
2)) forall a b. (a -> b) -> a -> b
$
       forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extColonFormat FormatExtension
fe (forall a. Ord a => (a, a) -> Format a -> Format a
clipFormat (Int
0, Int
60) forall a b. (a -> b) -> a -> b
$ forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NegSign (forall a. a -> Maybe a
Just Int
2)) forall a b. (a -> b) -> a -> b
$
       (forall a. Ord a => (a, a) -> Format a -> Format a
clipFormat (Pico
0, Pico
60) forall a b. (a -> b) -> a -> b
$ forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
decimalFormat SignOption
NegSign (forall a. a -> Maybe a
Just Int
2))

-- | ISO 8601:2004(E) sec. 4.4.4.1
intervalFormat :: Format a -> Format b -> Format (a, b)
intervalFormat :: forall a b. Format a -> Format b -> Format (a, b)
intervalFormat = forall a b. String -> Format a -> Format b -> Format (a, b)
sepFormat String
"/"

-- | ISO 8601:2004(E) sec. 4.5
recurringIntervalFormat :: Format a -> Format b -> Format (Int, a, b)
recurringIntervalFormat :: forall a b. Format a -> Format b -> Format (Int, a, b)
recurringIntervalFormat Format a
fa Format b
fb =
    forall (f :: * -> *) a b.
IsoVariant f =>
(a -> b) -> (b -> a) -> f a -> f b
isoMap (\(Int
r, (a
a, b
b)) -> (Int
r, a
a, b
b)) (\(Int
r, a
a, b
b) -> (Int
r, (a
a, b
b))) forall a b. (a -> b) -> a -> b
$
    forall a b. String -> Format a -> Format b -> Format (a, b)
sepFormat String
"/" (String -> Format ()
literalFormat String
"R" forall (f :: * -> *) a. Productish f => f () -> f a -> f a
**> forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NoSign forall a. Maybe a
Nothing) forall a b. (a -> b) -> a -> b
$ forall a b. Format a -> Format b -> Format (a, b)
intervalFormat Format a
fa Format b
fb

class ISO8601 t where
    -- | The most commonly used ISO 8601 format for this type.
    iso8601Format :: Format t

-- | Show in the most commonly used ISO 8601 format.
iso8601Show :: ISO8601 t => t -> String
iso8601Show :: forall t. ISO8601 t => t -> String
iso8601Show = forall t. Format t -> t -> String
formatShow forall t. ISO8601 t => Format t
iso8601Format

-- | Parse the most commonly used ISO 8601 format.
iso8601ParseM :: (MonadFail m, ISO8601 t) => String -> m t
iso8601ParseM :: forall (m :: * -> *) t. (MonadFail m, ISO8601 t) => String -> m t
iso8601ParseM = forall (m :: * -> *) t. MonadFail m => Format t -> String -> m t
formatParseM forall t. ISO8601 t => Format t
iso8601Format

-- | @yyyy-mm-dd@ (ISO 8601:2004(E) sec. 4.1.2.2 extended format)
instance ISO8601 Day where
    iso8601Format :: Format Day
iso8601Format = FormatExtension -> Format Day
calendarFormat FormatExtension
ExtendedFormat

-- | @hh:mm:ss[.sss]@ (ISO 8601:2004(E) sec. 4.2.2.2, 4.2.2.4(a) extended format)
instance ISO8601 TimeOfDay where
    iso8601Format :: Format TimeOfDay
iso8601Format = FormatExtension -> Format TimeOfDay
timeOfDayFormat FormatExtension
ExtendedFormat

-- | @±hh:mm@ (ISO 8601:2004(E) sec. 4.2.5.1 extended format)
instance ISO8601 TimeZone where
    iso8601Format :: Format TimeZone
iso8601Format = FormatExtension -> Format TimeZone
timeOffsetFormat FormatExtension
ExtendedFormat

-- | @yyyy-mm-ddThh:mm:ss[.sss]@ (ISO 8601:2004(E) sec. 4.3.2 extended format)
instance ISO8601 LocalTime where
    iso8601Format :: Format LocalTime
iso8601Format = Format Day -> Format TimeOfDay -> Format LocalTime
localTimeFormat forall t. ISO8601 t => Format t
iso8601Format forall t. ISO8601 t => Format t
iso8601Format

-- | @yyyy-mm-ddThh:mm:ss[.sss]±hh:mm@ (ISO 8601:2004(E) sec. 4.3.2 extended format)
instance ISO8601 ZonedTime where
    iso8601Format :: Format ZonedTime
iso8601Format = Format Day
-> Format TimeOfDay -> FormatExtension -> Format ZonedTime
zonedTimeFormat forall t. ISO8601 t => Format t
iso8601Format forall t. ISO8601 t => Format t
iso8601Format FormatExtension
ExtendedFormat

-- | @yyyy-mm-ddThh:mm:ss[.sss]Z@ (ISO 8601:2004(E) sec. 4.3.2 extended format)
instance ISO8601 UTCTime where
    iso8601Format :: Format UTCTime
iso8601Format = Format Day -> Format TimeOfDay -> Format UTCTime
utcTimeFormat forall t. ISO8601 t => Format t
iso8601Format forall t. ISO8601 t => Format t
iso8601Format

-- | @PyYmMdD@ (ISO 8601:2004(E) sec. 4.4.3.2)
instance ISO8601 CalendarDiffDays where
    iso8601Format :: Format CalendarDiffDays
iso8601Format = Format CalendarDiffDays
durationDaysFormat

-- | @PyYmMdDThHmMs[.sss]S@ (ISO 8601:2004(E) sec. 4.4.3.2)
instance ISO8601 CalendarDiffTime where
    iso8601Format :: Format CalendarDiffTime
iso8601Format = Format CalendarDiffTime
durationTimeFormat