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

#if MIN_VERSION_base(4,9,0)
import Control.Monad.Fail
import Prelude hiding (fail)
#endif
#if MIN_VERSION_base(4,8,0)
#else
import Data.Monoid
#endif
import Data.Ratio
import Data.Fixed
import Text.ParserCombinators.ReadP
import Data.Format
import Data.Time
import Data.Time.Calendar.OrdinalDate
import Data.Time.Calendar.WeekDate
import Data.Time.Calendar.Private

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 :: (FormatExtension -> Format t) -> ReadP t
formatReadPExtension ff :: FormatExtension -> Format t
ff = Format t -> ReadP t
forall t. Format t -> ReadP t
formatReadP (FormatExtension -> Format t
ff FormatExtension
ExtendedFormat) ReadP t -> ReadP t -> ReadP t
forall a. ReadP a -> ReadP a -> ReadP a
+++ Format t -> ReadP t
forall t. Format t -> ReadP t
formatReadP (FormatExtension -> Format t
ff FormatExtension
BasicFormat)

-- | Parse a value in either extended or basic format
parseFormatExtension :: (
#if MIN_VERSION_base(4,9,0)
    MonadFail m
#else
    Monad m
#endif
    ) => (FormatExtension -> Format t) -> String -> m t
parseFormatExtension :: (FormatExtension -> Format t) -> String -> m t
parseFormatExtension ff :: FormatExtension -> Format t
ff = ReadP t -> String -> m t
forall (m :: * -> *) t. MonadFail m => ReadP t -> String -> m t
parseReader (ReadP t -> String -> m t) -> ReadP t -> String -> m t
forall a b. (a -> b) -> a -> b
$ (FormatExtension -> Format t) -> ReadP t
forall t. (FormatExtension -> Format t) -> ReadP t
formatReadPExtension FormatExtension -> Format t
ff

sepFormat :: String -> Format a -> Format b -> Format (a,b)
sepFormat :: String -> Format a -> Format b -> Format (a, b)
sepFormat sep :: String
sep fa :: Format a
fa fb :: Format b
fb = (Format a
fa Format a -> Format () -> Format a
forall (f :: * -> *) a. Productish f => f a -> f () -> f a
<** String -> Format ()
literalFormat String
sep) Format a -> Format b -> Format (a, b)
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 :: Format a -> Format b -> Format (a, b)
dashFormat = String -> Format a -> Format b -> Format (a, b)
forall a b. String -> Format a -> Format b -> Format (a, b)
sepFormat "-"

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

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

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

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

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

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

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

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

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

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

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

data E14
instance HasResolution E14 where
    resolution :: p E14 -> Integer
resolution _ = 100000000000000
data E16
instance HasResolution E16 where
    resolution :: p E16 -> Integer
resolution _ = 10000000000000000

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

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

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

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

mapGregorian :: Format (Integer,(Int,Int)) -> Format Day
mapGregorian :: Format (Integer, (Int, Int)) -> Format Day
mapGregorian = ((Integer, (Int, Int)) -> Maybe Day)
-> (Day -> Maybe (Integer, (Int, Int)))
-> Format (Integer, (Int, Int))
-> Format Day
forall a b.
(a -> Maybe b) -> (b -> Maybe a) -> Format a -> Format b
mapMFormat (\(y :: Integer
y,(m :: Int
m,d :: Int
d)) -> Integer -> Int -> Int -> Maybe Day
fromGregorianValid Integer
y Int
m Int
d) (\day :: Day
day -> (\(y :: Integer
y,m :: Int
m,d :: Int
d) -> (Integer, (Int, Int)) -> Maybe (Integer, (Int, Int))
forall a. a -> Maybe a
Just (Integer
y,(Int
m,Int
d))) ((Integer, Int, Int) -> Maybe (Integer, (Int, Int)))
-> (Integer, Int, Int) -> Maybe (Integer, (Int, Int))
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 = ((Integer, Int) -> Maybe Day)
-> (Day -> Maybe (Integer, Int))
-> Format (Integer, Int)
-> Format Day
forall a b.
(a -> Maybe b) -> (b -> Maybe a) -> Format a -> Format b
mapMFormat (\(y :: Integer
y,d :: Int
d) -> Integer -> Int -> Maybe Day
fromOrdinalDateValid Integer
y Int
d) ((Integer, Int) -> Maybe (Integer, Int)
forall a. a -> Maybe a
Just ((Integer, Int) -> Maybe (Integer, Int))
-> (Day -> (Integer, Int)) -> Day -> Maybe (Integer, Int)
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 = ((Integer, (Int, Int)) -> Maybe Day)
-> (Day -> Maybe (Integer, (Int, Int)))
-> Format (Integer, (Int, Int))
-> Format Day
forall a b.
(a -> Maybe b) -> (b -> Maybe a) -> Format a -> Format b
mapMFormat (\(y :: Integer
y,(w :: Int
w,d :: Int
d)) -> Integer -> Int -> Int -> Maybe Day
fromWeekDateValid Integer
y Int
w Int
d) (\day :: Day
day -> (\(y :: Integer
y,w :: Int
w,d :: Int
d) -> (Integer, (Int, Int)) -> Maybe (Integer, (Int, Int))
forall a. a -> Maybe a
Just (Integer
y,(Int
w,Int
d))) ((Integer, Int, Int) -> Maybe (Integer, (Int, Int)))
-> (Integer, Int, Int) -> Maybe (Integer, (Int, Int))
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 = ((Int, (Int, Pico)) -> Maybe TimeOfDay)
-> (TimeOfDay -> Maybe (Int, (Int, Pico)))
-> Format (Int, (Int, Pico))
-> Format TimeOfDay
forall a b.
(a -> Maybe b) -> (b -> Maybe a) -> Format a -> Format b
mapMFormat (\(h :: Int
h,(m :: Int
m,s :: Pico
s)) -> Int -> Int -> Pico -> Maybe TimeOfDay
makeTimeOfDayValid Int
h Int
m Pico
s) (\(TimeOfDay h :: Int
h m :: Int
m s :: Pico
s) -> (Int, (Int, Pico)) -> Maybe (Int, (Int, Pico))
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 fe :: FormatExtension
fe = Format (Integer, (Int, Int)) -> Format Day
mapGregorian (Format (Integer, (Int, Int)) -> Format Day)
-> Format (Integer, (Int, Int)) -> Format Day
forall a b. (a -> b) -> a -> b
$ FormatExtension
-> Format Integer
-> Format (Int, Int)
-> Format (Integer, (Int, Int))
forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe Format Integer
yearFormat (Format (Int, Int) -> Format (Integer, (Int, Int)))
-> Format (Int, Int) -> Format (Integer, (Int, Int))
forall a b. (a -> b) -> a -> b
$ FormatExtension -> Format Int -> Format Int -> Format (Int, Int)
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 Format Integer -> Format Int -> Format (Integer, Int)
forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> String -> Format ()
literalFormat "-" Format () -> Format Int -> Format Int
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 = SignOption -> Maybe Int -> Format Integer
forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NegSign (Int -> Maybe Int
forall a. a -> Maybe a
Just 2)

-- | ISO 8601:2004(E) sec. 4.1.2.4(a)
expandedCalendarFormat :: Int -> FormatExtension -> Format Day
expandedCalendarFormat :: Int -> FormatExtension -> Format Day
expandedCalendarFormat n :: Int
n fe :: FormatExtension
fe = Format (Integer, (Int, Int)) -> Format Day
mapGregorian (Format (Integer, (Int, Int)) -> Format Day)
-> Format (Integer, (Int, Int)) -> Format Day
forall a b. (a -> b) -> a -> b
$ FormatExtension
-> Format Integer
-> Format (Int, Int)
-> Format (Integer, (Int, Int))
forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe (Int -> Format Integer
expandedYearFormat Int
n) (Format (Int, Int) -> Format (Integer, (Int, Int)))
-> Format (Int, Int) -> Format (Integer, (Int, Int))
forall a b. (a -> b) -> a -> b
$ FormatExtension -> Format Int -> Format Int -> Format (Int, Int)
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 n :: Int
n = Format Integer -> Format Int -> Format (Integer, Int)
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 n :: Int
n = SignOption -> Maybe Int -> Format Integer
forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
PosNegSign (Int -> Maybe Int
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 fe :: FormatExtension
fe = Format (Integer, Int) -> Format Day
mapOrdinalDate (Format (Integer, Int) -> Format Day)
-> Format (Integer, Int) -> Format Day
forall a b. (a -> b) -> a -> b
$ FormatExtension
-> Format Integer -> Format Int -> Format (Integer, Int)
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 n :: Int
n fe :: FormatExtension
fe = Format (Integer, Int) -> Format Day
mapOrdinalDate (Format (Integer, Int) -> Format Day)
-> Format (Integer, Int) -> Format Day
forall a b. (a -> b) -> a -> b
$ FormatExtension
-> Format Integer -> Format Int -> Format (Integer, Int)
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 fe :: FormatExtension
fe = Format (Integer, (Int, Int)) -> Format Day
mapWeekDate (Format (Integer, (Int, Int)) -> Format Day)
-> Format (Integer, (Int, Int)) -> Format Day
forall a b. (a -> b) -> a -> b
$ FormatExtension
-> Format Integer
-> Format (Int, Int)
-> Format (Integer, (Int, Int))
forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe Format Integer
yearFormat (Format (Int, Int) -> Format (Integer, (Int, Int)))
-> Format (Int, Int) -> Format (Integer, (Int, Int))
forall a b. (a -> b) -> a -> b
$ FormatExtension -> Format Int -> Format Int -> Format (Int, Int)
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 fe :: FormatExtension
fe = FormatExtension
-> Format Integer -> Format Int -> Format (Integer, Int)
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 n :: Int
n fe :: FormatExtension
fe = Format (Integer, (Int, Int)) -> Format Day
mapWeekDate (Format (Integer, (Int, Int)) -> Format Day)
-> Format (Integer, (Int, Int)) -> Format Day
forall a b. (a -> b) -> a -> b
$ FormatExtension
-> Format Integer
-> Format (Int, Int)
-> Format (Integer, (Int, Int))
forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extDashFormat FormatExtension
fe (Int -> Format Integer
expandedYearFormat Int
n) (Format (Int, Int) -> Format (Integer, (Int, Int)))
-> Format (Int, Int) -> Format (Integer, (Int, Int))
forall a b. (a -> b) -> a -> b
$ FormatExtension -> Format Int -> Format Int -> Format (Int, Int)
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 n :: Int
n fe :: FormatExtension
fe = FormatExtension
-> Format Integer -> Format Int -> Format (Integer, Int)
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 fe :: FormatExtension
fe = Format (Int, (Int, Pico)) -> Format TimeOfDay
mapTimeOfDay (Format (Int, (Int, Pico)) -> Format TimeOfDay)
-> Format (Int, (Int, Pico)) -> Format TimeOfDay
forall a b. (a -> b) -> a -> b
$ FormatExtension
-> Format Int -> Format (Int, Pico) -> Format (Int, (Int, Pico))
forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extColonFormat FormatExtension
fe Format Int
hourFormat' (Format (Int, Pico) -> Format (Int, (Int, Pico)))
-> Format (Int, Pico) -> Format (Int, (Int, Pico))
forall a b. (a -> b) -> a -> b
$ FormatExtension -> Format Int -> Format Pico -> Format (Int, Pico)
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 r :: Rational
r = Rational -> NominalDiffTime
forall a. Fractional a => Rational -> a
fromRational (Rational -> NominalDiffTime) -> Rational -> NominalDiffTime
forall a b. (a -> b) -> a -> b
$ Rational -> Integer
forall a b. (RealFrac a, Integral b) => a -> b
round (Rational
r Rational -> Rational -> Rational
forall a. Num a => a -> a -> a
* 1000000000000) Integer -> Integer -> Rational
forall a. Integral a => a -> a -> Ratio a
% 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 fe :: FormatExtension
fe = let
    toTOD :: (a, a) -> Maybe TimeOfDay
toTOD (h :: a
h,m :: a
m) = case NominalDiffTime -> (Integer, TimeOfDay)
timeToDaysAndTimeOfDay (NominalDiffTime -> (Integer, TimeOfDay))
-> NominalDiffTime -> (Integer, TimeOfDay)
forall a b. (a -> b) -> a -> b
$ Rational -> NominalDiffTime
fromRationalRound (Rational -> NominalDiffTime) -> Rational -> NominalDiffTime
forall a b. (a -> b) -> a -> b
$ a -> Rational
forall a. Real a => a -> Rational
toRational (a -> Rational) -> a -> Rational
forall a b. (a -> b) -> a -> b
$ (a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
h) a -> a -> a
forall a. Num a => a -> a -> a
* 3600 a -> a -> a
forall a. Num a => a -> a -> a
+ a
m a -> a -> a
forall a. Num a => a -> a -> a
* 60 of
        (0,tod :: TimeOfDay
tod) -> TimeOfDay -> Maybe TimeOfDay
forall a. a -> Maybe a
Just TimeOfDay
tod
        _ -> Maybe TimeOfDay
forall a. Maybe a
Nothing
    fromTOD :: TimeOfDay -> Maybe (b, a)
fromTOD tod :: TimeOfDay
tod = let
        mm :: a
mm = (NominalDiffTime -> a
forall a b. (Real a, Fractional b) => a -> b
realToFrac (NominalDiffTime -> a) -> NominalDiffTime -> a
forall a b. (a -> b) -> a -> b
$ Integer -> TimeOfDay -> NominalDiffTime
daysAndTimeOfDayToTime 0 TimeOfDay
tod) a -> a -> a
forall a. Fractional a => a -> a -> a
/ 60
        in (b, a) -> Maybe (b, a)
forall a. a -> Maybe a
Just ((b, a) -> Maybe (b, a)) -> (b, a) -> Maybe (b, a)
forall a b. (a -> b) -> a -> b
$ a -> a -> (b, a)
forall a b. (Real a, Integral b) => a -> a -> (b, a)
quotRemBy 60 a
mm
    in ((Int, Fixed E14) -> Maybe TimeOfDay)
-> (TimeOfDay -> Maybe (Int, Fixed E14))
-> Format (Int, Fixed E14)
-> Format TimeOfDay
forall a b.
(a -> Maybe b) -> (b -> Maybe a) -> Format a -> Format b
mapMFormat (Int, Fixed E14) -> Maybe TimeOfDay
forall a a. (Integral a, Real a) => (a, a) -> Maybe TimeOfDay
toTOD TimeOfDay -> Maybe (Int, Fixed E14)
forall b a.
(Integral b, Real a, Fractional a) =>
TimeOfDay -> Maybe (b, a)
fromTOD (Format (Int, Fixed E14) -> Format TimeOfDay)
-> Format (Int, Fixed E14) -> Format TimeOfDay
forall a b. (a -> b) -> a -> b
$ FormatExtension
-> Format Int -> Format (Fixed E14) -> Format (Int, Fixed E14)
forall a b.
FormatExtension -> Format a -> Format b -> Format (a, b)
extColonFormat FormatExtension
fe Format Int
hourFormat' (Format (Fixed E14) -> Format (Int, Fixed E14))
-> Format (Fixed E14) -> Format (Int, Fixed E14)
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 h :: a
h = case NominalDiffTime -> (Integer, TimeOfDay)
timeToDaysAndTimeOfDay (NominalDiffTime -> (Integer, TimeOfDay))
-> NominalDiffTime -> (Integer, TimeOfDay)
forall a b. (a -> b) -> a -> b
$ Rational -> NominalDiffTime
fromRationalRound (Rational -> NominalDiffTime) -> Rational -> NominalDiffTime
forall a b. (a -> b) -> a -> b
$ a -> Rational
forall a. Real a => a -> Rational
toRational (a -> Rational) -> a -> Rational
forall a b. (a -> b) -> a -> b
$ a
h a -> a -> a
forall a. Num a => a -> a -> a
* 3600 of
        (0,tod :: TimeOfDay
tod) -> TimeOfDay -> Maybe TimeOfDay
forall a. a -> Maybe a
Just TimeOfDay
tod
        _ -> Maybe TimeOfDay
forall a. Maybe a
Nothing
    fromTOD :: TimeOfDay -> Maybe a
fromTOD tod :: TimeOfDay
tod = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> a -> Maybe a
forall a b. (a -> b) -> a -> b
$ (NominalDiffTime -> a
forall a b. (Real a, Fractional b) => a -> b
realToFrac (NominalDiffTime -> a) -> NominalDiffTime -> a
forall a b. (a -> b) -> a -> b
$ Integer -> TimeOfDay -> NominalDiffTime
daysAndTimeOfDayToTime 0 TimeOfDay
tod) a -> a -> a
forall a. Fractional a => a -> a -> a
/ 3600
    in (Fixed E16 -> Maybe TimeOfDay)
-> (TimeOfDay -> Maybe (Fixed E16))
-> Format (Fixed E16)
-> Format TimeOfDay
forall a b.
(a -> Maybe b) -> (b -> Maybe a) -> Format a -> Format b
mapMFormat Fixed E16 -> Maybe TimeOfDay
forall a. Real a => a -> Maybe TimeOfDay
toTOD TimeOfDay -> Maybe (Fixed E16)
forall a. Fractional a => TimeOfDay -> Maybe a
fromTOD (Format (Fixed E16) -> Format TimeOfDay)
-> Format (Fixed E16) -> Format TimeOfDay
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 :: Format t -> Format t
withTimeDesignator f :: Format t
f = String -> Format ()
literalFormat "T" Format () -> Format t -> Format 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 :: Format t -> Format t
withUTCDesignator f :: Format t
f = Format t
f Format t -> Format () -> Format t
forall (f :: * -> *) a. Productish f => f a -> f () -> f a
<** String -> Format ()
literalFormat "Z"

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

-- | ISO 8601:2004(E) sec. 4.2.5.2
timeOfDayAndOffsetFormat :: FormatExtension -> Format (TimeOfDay,TimeZone)
timeOfDayAndOffsetFormat :: FormatExtension -> Format (TimeOfDay, TimeZone)
timeOfDayAndOffsetFormat fe :: FormatExtension
fe = FormatExtension -> Format TimeOfDay
timeOfDayFormat FormatExtension
fe Format TimeOfDay -> Format TimeZone -> Format (TimeOfDay, TimeZone)
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 fday :: Format Day
fday ftod :: Format TimeOfDay
ftod = ((Day, TimeOfDay) -> LocalTime)
-> (LocalTime -> (Day, TimeOfDay))
-> Format (Day, TimeOfDay)
-> Format LocalTime
forall (f :: * -> *) a b.
IsoVariant f =>
(a -> b) -> (b -> a) -> f a -> f b
isoMap (\(day :: Day
day,tod :: TimeOfDay
tod) -> Day -> TimeOfDay -> LocalTime
LocalTime Day
day TimeOfDay
tod) (\(LocalTime day :: Day
day tod :: TimeOfDay
tod) -> (Day
day,TimeOfDay
tod)) (Format (Day, TimeOfDay) -> Format LocalTime)
-> Format (Day, TimeOfDay) -> Format LocalTime
forall a b. (a -> b) -> a -> b
$ Format Day
fday Format Day -> Format TimeOfDay -> Format (Day, TimeOfDay)
forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> Format TimeOfDay -> Format TimeOfDay
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 fday :: Format Day
fday ftod :: Format TimeOfDay
ftod fe :: FormatExtension
fe = ((LocalTime, TimeZone) -> ZonedTime)
-> (ZonedTime -> (LocalTime, TimeZone))
-> Format (LocalTime, TimeZone)
-> Format ZonedTime
forall (f :: * -> *) a b.
IsoVariant f =>
(a -> b) -> (b -> a) -> f a -> f b
isoMap (\(lt :: LocalTime
lt,tz :: TimeZone
tz) -> LocalTime -> TimeZone -> ZonedTime
ZonedTime LocalTime
lt TimeZone
tz) (\(ZonedTime lt :: LocalTime
lt tz :: TimeZone
tz) -> (LocalTime
lt,TimeZone
tz)) (Format (LocalTime, TimeZone) -> Format ZonedTime)
-> Format (LocalTime, TimeZone) -> Format ZonedTime
forall a b. (a -> b) -> a -> b
$ Format LocalTime -> FormatExtension -> Format (LocalTime, TimeZone)
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 fday :: Format Day
fday ftod :: Format TimeOfDay
ftod = (LocalTime -> UTCTime)
-> (UTCTime -> LocalTime) -> Format LocalTime -> Format UTCTime
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) (Format LocalTime -> Format UTCTime)
-> Format LocalTime -> Format UTCTime
forall a b. (a -> b) -> a -> b
$ Format LocalTime -> Format LocalTime
forall t. Format t -> Format t
withUTCDesignator (Format LocalTime -> Format LocalTime)
-> Format LocalTime -> Format LocalTime
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 :: Format Day -> Format time -> Format (Day, time)
dayAndTimeFormat fday :: Format Day
fday ft :: Format time
ft = Format Day
fday Format Day -> Format time -> Format (Day, time)
forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> Format time -> Format time
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 :: Format t -> FormatExtension -> Format (t, TimeZone)
timeAndOffsetFormat ft :: Format t
ft fe :: FormatExtension
fe = Format t
ft Format t -> Format TimeZone -> Format (t, TimeZone)
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 :: Char -> Format t
intDesignator c :: Char
c = t -> Format t -> Format t
forall a. Eq a => a -> Format a -> Format a
optionalFormat 0 (Format t -> Format t) -> Format t -> Format t
forall a b. (a -> b) -> a -> b
$ SignOption -> Maybe Int -> Format t
forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
integerFormat SignOption
NoSign Maybe Int
forall a. Maybe a
Nothing Format t -> Format () -> Format t
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 :: Char -> Format t
decDesignator c :: Char
c = t -> Format t -> Format t
forall a. Eq a => a -> Format a -> Format a
optionalFormat 0 (Format t -> Format t) -> Format t -> Format t
forall a b. (a -> b) -> a -> b
$ SignOption -> Maybe Int -> Format t
forall t.
(Show t, Read t, Num t) =>
SignOption -> Maybe Int -> Format t
decimalFormat SignOption
NoSign Maybe Int
forall a. Maybe a
Nothing Format t -> Format () -> Format t
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 (y :: Integer
y,(m :: Integer
m,(w :: Integer
w,d :: Integer
d))) = Integer -> Integer -> CalendarDiffDays
CalendarDiffDays (Integer
y Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* 12 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
m) (Integer
w Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
* 7 Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+ Integer
d)
    fromCD :: CalendarDiffDays -> (Integer, (Integer, (a, Integer)))
fromCD (CalendarDiffDays mm :: Integer
mm d :: Integer
d) = (Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
quot Integer
mm 12,(Integer -> Integer -> Integer
forall a. Integral a => a -> a -> a
rem Integer
mm 12,(0,Integer
d)))
    in ((Integer, (Integer, (Integer, Integer))) -> CalendarDiffDays)
-> (CalendarDiffDays -> (Integer, (Integer, (Integer, Integer))))
-> Format (Integer, (Integer, (Integer, Integer)))
-> Format CalendarDiffDays
forall (f :: * -> *) a b.
IsoVariant f =>
(a -> b) -> (b -> a) -> f a -> f b
isoMap (Integer, (Integer, (Integer, Integer))) -> CalendarDiffDays
toCD CalendarDiffDays -> (Integer, (Integer, (Integer, Integer)))
forall a.
Num a =>
CalendarDiffDays -> (Integer, (Integer, (a, Integer)))
fromCD (Format (Integer, (Integer, (Integer, Integer)))
 -> Format CalendarDiffDays)
-> Format (Integer, (Integer, (Integer, Integer)))
-> Format CalendarDiffDays
forall a b. (a -> b) -> a -> b
$
        Char -> Format Integer
forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
intDesignator 'Y' Format Integer
-> Format (Integer, (Integer, Integer))
-> Format (Integer, (Integer, (Integer, Integer)))
forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> Char -> Format Integer
forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
intDesignator 'M' Format Integer
-> Format (Integer, Integer)
-> Format (Integer, (Integer, Integer))
forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> Char -> Format Integer
forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
intDesignator 'W' Format Integer -> Format Integer -> Format (Integer, Integer)
forall (f :: * -> *) a b. Productish f => f a -> f b -> f (a, b)
<**> Char -> Format Integer
forall t. (Eq t, Show t, Read t, Num t) => Char -> Format t
intDesignator 'D'

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

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

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

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

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

-- | Parse the most commonly used ISO 8601 format.
iso8601ParseM :: (
#if MIN_VERSION_base(4,9,0)
    MonadFail m
#else
    Monad m
#endif
    ,ISO8601 t) => String -> m t
iso8601ParseM :: String -> m t
iso8601ParseM = Format t -> String -> m t
forall (m :: * -> *) t. MonadFail m => Format t -> String -> m t
formatParseM Format t
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 Format Day
forall t. ISO8601 t => Format t
iso8601Format Format TimeOfDay
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 Format Day
forall t. ISO8601 t => Format t
iso8601Format Format TimeOfDay
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 Format Day
forall t. ISO8601 t => Format t
iso8601Format Format TimeOfDay
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