    {-# LANGUAGE Safe #-}

    module Data.Time.Format.Format.Class (
        -- * Formatting
        formatTime,
        FormatNumericPadding,
        FormatOptions (..),
        FormatTime (..),
        ShowPadded,
        PadOption,
        formatGeneral,
        formatString,
        formatNumber,
        formatNumberStd,
        showPaddedFixed,
        showPaddedFixedFraction,
        quotBy,
        remBy,
    ) where

    import Data.Char
    import Data.Fixed
    import Data.Maybe
    import Data.Time.Calendar.Private
    import Data.Time.Format.Locale

    type FormatNumericPadding = Maybe Char

    data FormatOptions = MkFormatOptions
        { FormatOptions -> TimeLocale
    foLocale :: TimeLocale
        , FormatOptions -> Maybe FormatNumericPadding
    foPadding :: Maybe FormatNumericPadding
        , FormatOptions -> Maybe Int
    foWidth :: Maybe Int
        }

    -- <http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html>
    class FormatTime t where
        -- | @since 1.9.1
        formatCharacter :: Bool -> Char -> Maybe (FormatOptions -> t -> String)

    -- the weird UNIX logic is here
    getPadOption :: Bool -> Bool -> Int -> Char -> Maybe FormatNumericPadding -> Maybe Int -> PadOption
    getPadOption :: Bool
    -> Bool
    -> Int
    -> Char
    -> Maybe FormatNumericPadding
    -> Maybe Int
    -> PadOption
    getPadOption Bool
    trunc Bool
    fdef Int
    idef Char
    cdef Maybe FormatNumericPadding
    mnpad Maybe Int
    mi =
        let c :: Char
    c =
                case Maybe FormatNumericPadding
    mnpad of
                    Just (Just Char
    c') -> Char
    c'
                    Just FormatNumericPadding
    Nothing -> Char
    ' '
                    Maybe FormatNumericPadding
    _ -> Char
    cdef
            i :: Int
    i =
                case Maybe Int
    mi of
                    Just Int
    i' ->
                        case Maybe FormatNumericPadding
    mnpad of
                            Just FormatNumericPadding
    Nothing -> Int
    i'
                            Maybe FormatNumericPadding
    _ ->
                                if Bool
    trunc
                                    then Int
    i'
                                    else Int -> Int -> Int
    forall a. Ord a => a -> a -> a
    max Int
    i' Int
    idef
                    Maybe Int
    Nothing -> Int
    idef
            f :: Bool
    f =
                case Maybe Int
    mi of
                    Just Int
    _ -> Bool
    True
                    Maybe Int
    Nothing ->
                        case Maybe FormatNumericPadding
    mnpad of
                            Maybe FormatNumericPadding
    Nothing -> Bool
    fdef
                            Just FormatNumericPadding
    Nothing -> Bool
    False
                            Just (Just Char
    _) -> Bool
    True
         in if Bool
    f
                then Int -> Char -> PadOption
    Pad Int
    i Char
    c
                else PadOption
    NoPad

    formatGeneral ::
        Bool -> Bool -> Int -> Char -> (TimeLocale -> PadOption -> t -> String) -> (FormatOptions -> t -> String)
    formatGeneral :: forall t.
    Bool
    -> Bool
    -> Int
    -> Char
    -> (TimeLocale -> PadOption -> t -> String)
    -> FormatOptions
    -> t
    -> String
    formatGeneral Bool
    trunc Bool
    fdef Int
    idef Char
    cdef TimeLocale -> PadOption -> t -> String
    ff FormatOptions
    fo =
        TimeLocale -> PadOption -> t -> String
    ff (FormatOptions -> TimeLocale
    foLocale FormatOptions
    fo) (PadOption -> t -> String) -> PadOption -> t -> String
    forall a b. (a -> b) -> a -> b
    $ Bool
    -> Bool
    -> Int
    -> Char
    -> Maybe FormatNumericPadding
    -> Maybe Int
    -> PadOption
    getPadOption Bool
    trunc Bool
    fdef Int
    idef Char
    cdef (FormatOptions -> Maybe FormatNumericPadding
    foPadding FormatOptions
    fo) (FormatOptions -> Maybe Int
    foWidth FormatOptions
    fo)

    formatString :: (TimeLocale -> t -> String) -> (FormatOptions -> t -> String)
    formatString :: forall t.
    (TimeLocale -> t -> String) -> FormatOptions -> t -> String
    formatString TimeLocale -> t -> String
    ff = Bool
    -> Bool
    -> Int
    -> Char
    -> (TimeLocale -> PadOption -> t -> String)
    -> FormatOptions
    -> t
    -> String
    forall t.
    Bool
    -> Bool
    -> Int
    -> Char
    -> (TimeLocale -> PadOption -> t -> String)
    -> FormatOptions
    -> t
    -> String
    formatGeneral Bool
    False Bool
    False Int
    1 Char
    ' ' ((TimeLocale -> PadOption -> t -> String)
     -> FormatOptions -> t -> String)
    -> (TimeLocale -> PadOption -> t -> String)
    -> FormatOptions
    -> t
    -> String
    forall a b. (a -> b) -> a -> b
    $ \TimeLocale
    locale PadOption
    pado -> PadOption -> String -> String
    showPadded PadOption
    pado (String -> String) -> (t -> String) -> t -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . TimeLocale -> t -> String
    ff TimeLocale
    locale

    formatNumber :: (ShowPadded i) => Bool -> Int -> Char -> (t -> i) -> (FormatOptions -> t -> String)
    formatNumber :: forall i t.
    ShowPadded i =>
    Bool -> Int -> Char -> (t -> i) -> FormatOptions -> t -> String
    formatNumber Bool
    fdef Int
    idef Char
    cdef t -> i
    ff = Bool
    -> Bool
    -> Int
    -> Char
    -> (TimeLocale -> PadOption -> t -> String)
    -> FormatOptions
    -> t
    -> String
    forall t.
    Bool
    -> Bool
    -> Int
    -> Char
    -> (TimeLocale -> PadOption -> t -> String)
    -> FormatOptions
    -> t
    -> String
    formatGeneral Bool
    False Bool
    fdef Int
    idef Char
    cdef ((TimeLocale -> PadOption -> t -> String)
     -> FormatOptions -> t -> String)
    -> (TimeLocale -> PadOption -> t -> String)
    -> FormatOptions
    -> t
    -> String
    forall a b. (a -> b) -> a -> b
    $ \TimeLocale
    _ PadOption
    pado -> PadOption -> i -> String
    forall t. ShowPadded t => PadOption -> t -> String
    showPaddedNum PadOption
    pado (i -> String) -> (t -> i) -> t -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . t -> i
    ff

    formatNumberStd :: Int -> (t -> Integer) -> (FormatOptions -> t -> String)
    formatNumberStd :: forall t. Int -> (t -> Integer) -> FormatOptions -> t -> String
    formatNumberStd Int
    n = Bool
    -> Int -> Char -> (t -> Integer) -> FormatOptions -> t -> String
    forall i t.
    ShowPadded i =>
    Bool -> Int -> Char -> (t -> i) -> FormatOptions -> t -> String
    formatNumber Bool
    False Int
    n Char
    '0'

    showPaddedFixed :: HasResolution a => PadOption -> PadOption -> Fixed a -> String
    showPaddedFixed :: forall a.
    HasResolution a =>
    PadOption -> PadOption -> Fixed a -> String
    showPaddedFixed PadOption
    padn PadOption
    padf Fixed a
    x
        | Fixed a
    x Fixed a -> Fixed a -> Bool
    forall a. Ord a => a -> a -> Bool
    < Fixed a
    0 = Char
    '-' Char -> String -> String
    forall a. a -> [a] -> [a]
    : PadOption -> PadOption -> Fixed a -> String
    forall a.
    HasResolution a =>
    PadOption -> PadOption -> Fixed a -> String
    showPaddedFixed PadOption
    padn PadOption
    padf (Fixed a -> Fixed a
    forall a. Num a => a -> a
    negate Fixed a
    x)
    showPaddedFixed PadOption
    padn PadOption
    padf Fixed a
    x =
        let ns :: String
    ns = PadOption -> Integer -> String
    forall t. ShowPadded t => PadOption -> t -> String
    showPaddedNum PadOption
    padn (Integer -> String) -> Integer -> String
    forall a b. (a -> b) -> a -> b
    $ (Fixed a -> Integer
    forall b. Integral b => Fixed a -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    floor Fixed a
    x :: Integer)
            fs :: String
    fs = PadOption -> Fixed a -> String
    forall a. HasResolution a => PadOption -> Fixed a -> String
    showPaddedFixedFraction PadOption
    padf Fixed a
    x
            ds :: String
    ds =
                if String -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null String
    fs
                    then String
    ""
                    else String
    "."
         in String
    ns String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    ds String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    fs

    showPaddedFixedFraction :: HasResolution a => PadOption -> Fixed a -> String
    showPaddedFixedFraction :: forall a. HasResolution a => PadOption -> Fixed a -> String
    showPaddedFixedFraction PadOption
    pado Fixed a
    x =
        let digits :: String
    digits = (Char -> Bool) -> String -> String
    forall a. (a -> Bool) -> [a] -> [a]
    dropWhile (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    == Char
    '.') (String -> String) -> String -> String
    forall a b. (a -> b) -> a -> b
    $ (Char -> Bool) -> String -> String
    forall a. (a -> Bool) -> [a] -> [a]
    dropWhile (Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Char
    '.') (String -> String) -> String -> String
    forall a b. (a -> b) -> a -> b
    $ Bool -> Fixed a -> String
    forall {k} (a :: k). HasResolution a => Bool -> Fixed a -> String
    showFixed Bool
    True Fixed a
    x
            n :: Int
    n = String -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length String
    digits
         in case PadOption
    pado of
                PadOption
    NoPad -> String
    digits
                Pad Int
    i Char
    c ->
                    if Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    < Int
    n
                        then Int -> String -> String
    forall a. Int -> [a] -> [a]
    take Int
    i String
    digits
                        else String
    digits String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ Int -> Char -> String
    forall a. Int -> a -> [a]
    replicate (Int
    i Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - Int
    n) Char
    c

    -- | Substitute various time-related information for each %-code in the string, as per 'formatCharacter'.
    --
    -- The general form is @%\<modifier\>\<width\>\<alternate\>\<specifier\>@, where @\<modifier\>@, @\<width\>@, and @\<alternate\>@ are optional.
    --
    -- == @\<modifier\>@
    -- glibc-style modifiers can be used before the specifier (here marked as @z@):
    --
    -- [@%-z@] no padding
    --
    -- [@%_z@] pad with spaces
    --
    -- [@%0z@] pad with zeros
    --
    -- [@%^z@] convert to upper case
    --
    -- [@%#z@] convert to lower case (consistently, unlike glibc)
    --
    -- == @\<width\>@
    -- Width digits can also be used after any modifiers and before the specifier (here marked as @z@), for example:
    --
    -- [@%4z@] pad to 4 characters (with default padding character)
    --
    -- [@%_12z@] pad with spaces to 12 characters
    --
    -- == @\<alternate\>@
    -- An optional @E@ character indicates an alternate formatting. Currently this only affects @%Z@ and @%z@.
    --
    -- [@%Ez@] alternate formatting
    --
    -- == @\<specifier\>@
    --
    -- For all types (note these three are done by 'formatTime', not by 'formatCharacter'):
    --
    -- [@%%@] @%@
    --
    -- [@%t@] tab
    --
    -- [@%n@] newline
    --
    -- === 'TimeZone'
    -- For 'TimeZone' (and 'ZonedTime' and 'UTCTime'):
    --
    -- [@%z@] timezone offset in the format @±HHMM@
    --
    -- [@%Ez@] timezone offset in the format @±HH:MM@
    --
    -- [@%Z@] timezone name (or else offset in the format @±HHMM@)
    --
    -- [@%EZ@] timezone name (or else offset in the format @±HH:MM@)
    --
    -- === 'LocalTime'
    -- For 'LocalTime' (and 'ZonedTime' and 'UTCTime' and 'UniversalTime'):
    --
    -- [@%c@] as 'dateTimeFmt' @locale@ (e.g. @%a %b %e %H:%M:%S %Z %Y@)
    --
    -- === 'TimeOfDay'
    -- For 'TimeOfDay' (and 'LocalTime' and 'ZonedTime' and 'UTCTime' and 'UniversalTime'):
    --
    -- [@%R@] same as @%H:%M@
    --
    -- [@%T@] same as @%H:%M:%S@
    --
    -- [@%X@] as 'timeFmt' @locale@ (e.g. @%H:%M:%S@)
    --
    -- [@%r@] as 'time12Fmt' @locale@ (e.g. @%I:%M:%S %p@)
    --
    -- [@%P@] day-half of day from ('amPm' @locale@), converted to lowercase, @am@, @pm@
    --
    -- [@%p@] day-half of day from ('amPm' @locale@), @AM@, @PM@
    --
    -- [@%H@] hour of day (24-hour), 0-padded to two chars, @00@ - @23@
    --
    -- [@%k@] hour of day (24-hour), space-padded to two chars, @ 0@ - @23@
    --
    -- [@%I@] hour of day-half (12-hour), 0-padded to two chars, @01@ - @12@
    --
    -- [@%l@] hour of day-half (12-hour), space-padded to two chars, @ 1@ - @12@
    --
    -- [@%M@] minute of hour, 0-padded to two chars, @00@ - @59@
    --
    -- [@%S@] second of minute (without decimal part), 0-padded to two chars, @00@ - @60@
    --
    -- [@%q@] picosecond of second, 0-padded to twelve chars, @000000000000@ - @999999999999@.
    --
    -- [@%Q@] decimal point and fraction of second, up to 12 second decimals, without trailing zeros.
    -- For a whole number of seconds, @%Q@ omits the decimal point unless padding is specified.
    --
    -- === 'UTCTime' and 'ZonedTime'
    -- For 'UTCTime' and 'ZonedTime':
    --
    -- [@%s@] number of whole seconds since the Unix epoch. For times before
    -- the Unix epoch, this is a negative number. Note that in @%s.%q@ and @%s%Q@
    -- the decimals are positive, not negative. For example, 0.9 seconds
    -- before the Unix epoch is formatted as @-1.1@ with @%s%Q@.
    --
    -- === 'DayOfWeek'
    -- For 'DayOfWeek' (and 'Day' and 'LocalTime' and 'ZonedTime' and 'UTCTime' and 'UniversalTime'):
    --
    -- [@%u@] day of week number for Week Date format, @1@ (= Monday) - @7@ (= Sunday)
    --
    -- [@%w@] day of week number, @0@ (= Sunday) - @6@ (= Saturday)
    --
    -- [@%a@] day of week, short form ('snd' from 'wDays' @locale@), @Sun@ - @Sat@
    --
    -- [@%A@] day of week, long form ('fst' from 'wDays' @locale@), @Sunday@ - @Saturday@
    --
    -- === 'Month'
    -- For 'Month' (and 'Day' and 'LocalTime' and 'ZonedTime' and 'UTCTime' and 'UniversalTime'):
    --
    -- [@%Y@] year, no padding. Note @%0Y@ and @%_Y@ pad to four chars
    --
    -- [@%y@] year of century, 0-padded to two chars, @00@ - @99@
    --
    -- [@%C@] century, no padding. Note @%0C@ and @%_C@ pad to two chars
    --
    -- [@%B@] month name, long form ('fst' from 'months' @locale@), @January@ - @December@
    --
    -- [@%b@, @%h@] month name, short form ('snd' from 'months' @locale@), @Jan@ - @Dec@
    --
    -- [@%m@] month of year, 0-padded to two chars, @01@ - @12@
    --
    -- === 'Day'
    -- For 'Day' (and 'LocalTime' and 'ZonedTime' and 'UTCTime' and 'UniversalTime'):
    --
    -- [@%D@] same as @%m\/%d\/%y@
    --
    -- [@%F@] same as @%Y-%m-%d@
    --
    -- [@%x@] as 'dateFmt' @locale@ (e.g. @%m\/%d\/%y@)
    --
    -- [@%d@] day of month, 0-padded to two chars, @01@ - @31@
    --
    -- [@%e@] day of month, space-padded to two chars,  @ 1@ - @31@
    --
    -- [@%j@] day of year, 0-padded to three chars, @001@ - @366@
    --
    -- [@%f@] century for Week Date format, no padding. Note @%0f@ and @%_f@ pad to two chars
    --
    -- [@%V@] week of year for Week Date format, 0-padded to two chars, @01@ - @53@
    --
    -- [@%U@] week of year where weeks start on Sunday (as 'sundayStartWeek'), 0-padded to two chars, @00@ - @53@
    --
    -- [@%W@] week of year where weeks start on Monday (as 'mondayStartWeek'), 0-padded to two chars, @00@ - @53@
    --
    -- == Duration types
    -- The specifiers for 'DiffTime', 'NominalDiffTime', 'CalendarDiffDays', and 'CalendarDiffTime' are semantically
    -- separate from the other types.
    -- Specifiers on negative time differences will generally be negative (think 'rem' rather than 'mod').
    --
    -- === 'NominalDiffTime' and 'DiffTime'
    -- Note that a "minute" of 'DiffTime' is simply 60 SI seconds, rather than a minute of civil time.
    -- Use 'NominalDiffTime' to work with civil time, ignoring any leap seconds.
    --
    -- For 'NominalDiffTime' and 'DiffTime':
    --
    -- [@%w@] total whole weeks
    --
    -- [@%d@] total whole days
    --
    -- [@%D@] whole days of week
    --
    -- [@%h@] total whole hours
    --
    -- [@%H@] whole hours of day
    --
    -- [@%m@] total whole minutes
    --
    -- [@%M@] whole minutes of hour
    --
    -- [@%s@] total whole seconds
    --
    -- [@%Es@] total seconds, with decimal point and up to \<width\> (default 12) decimal places, without trailing zeros.
    -- For a whole number of seconds, @%Es@ omits the decimal point unless padding is specified.
    --
    -- [@%0Es@] total seconds, with decimal point and \<width\> (default 12) decimal places.
    --
    -- [@%S@] whole seconds of minute
    --
    -- [@%ES@] seconds of minute, with decimal point and up to \<width\> (default 12) decimal places, without trailing zeros.
    -- For a whole number of seconds, @%ES@ omits the decimal point unless padding is specified.
    --
    -- [@%0ES@] seconds of minute as two digits, with decimal point and \<width\> (default 12) decimal places.
    --
    -- === 'CalendarDiffDays'
    -- For 'CalendarDiffDays' (and 'CalendarDiffTime'):
    --
    -- [@%y@] total years
    --
    -- [@%b@] total months
    --
    -- [@%B@] months of year
    --
    -- [@%w@] total weeks, not including months
    --
    -- [@%d@] total days, not including months
    --
    -- [@%D@] days of week
    --
    -- === 'CalendarDiffTime'
    -- For 'CalendarDiffTime':
    --
    -- [@%h@] total hours, not including months
    --
    -- [@%H@] hours of day
    --
    -- [@%m@] total minutes, not including months
    --
    -- [@%M@] minutes of hour
    --
    -- [@%s@] total whole seconds, not including months
    --
    -- [@%Es@] total seconds, not including months, with decimal point and up to \<width\> (default 12) decimal places, without trailing zeros.
    -- For a whole number of seconds, @%Es@ omits the decimal point unless padding is specified.
    --
    -- [@%0Es@] total seconds, not including months, with decimal point and \<width\> (default 12) decimal places.
    --
    -- [@%S@] whole seconds of minute
    --
    -- [@%ES@] seconds of minute, with decimal point and up to \<width\> (default 12) decimal places, without trailing zeros.
    -- For a whole number of seconds, @%ES@ omits the decimal point unless padding is specified.
    --
    -- [@%0ES@] seconds of minute as two digits, with decimal point and \<width\> (default 12) decimal places.
    formatTime :: (FormatTime t) => TimeLocale -> String -> t -> String
    formatTime :: forall t. FormatTime t => TimeLocale -> String -> t -> String
    formatTime TimeLocale
    _ [] t
    _ = String
    ""
    formatTime TimeLocale
    locale (Char
    '%' : String
    cs) t
    t =
        case TimeLocale -> String -> t -> Maybe String
    forall t. FormatTime t => TimeLocale -> String -> t -> Maybe String
    formatTime1 TimeLocale
    locale String
    cs t
    t of
            Just String
    result -> String
    result
            Maybe String
    Nothing -> Char
    '%' Char -> String -> String
    forall a. a -> [a] -> [a]
    : (TimeLocale -> String -> t -> String
    forall t. FormatTime t => TimeLocale -> String -> t -> String
    formatTime TimeLocale
    locale String
    cs t
    t)
    formatTime TimeLocale
    locale (Char
    c : String
    cs) t
    t = Char
    c Char -> String -> String
    forall a. a -> [a] -> [a]
    : (TimeLocale -> String -> t -> String
    forall t. FormatTime t => TimeLocale -> String -> t -> String
    formatTime TimeLocale
    locale String
    cs t
    t)

    formatTime1 :: (FormatTime t) => TimeLocale -> String -> t -> Maybe String
    formatTime1 :: forall t. FormatTime t => TimeLocale -> String -> t -> Maybe String
    formatTime1 TimeLocale
    locale (Char
    '_' : String
    cs) t
    t = TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    forall t.
    FormatTime t =>
    TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    formatTime2 TimeLocale
    locale String -> String
    forall a. a -> a
    id (FormatNumericPadding -> Maybe FormatNumericPadding
    forall a. a -> Maybe a
    Just (Char -> FormatNumericPadding
    forall a. a -> Maybe a
    Just Char
    ' ')) String
    cs t
    t
    formatTime1 TimeLocale
    locale (Char
    '-' : String
    cs) t
    t = TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    forall t.
    FormatTime t =>
    TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    formatTime2 TimeLocale
    locale String -> String
    forall a. a -> a
    id (FormatNumericPadding -> Maybe FormatNumericPadding
    forall a. a -> Maybe a
    Just FormatNumericPadding
    forall a. Maybe a
    Nothing) String
    cs t
    t
    formatTime1 TimeLocale
    locale (Char
    '0' : String
    cs) t
    t = TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    forall t.
    FormatTime t =>
    TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    formatTime2 TimeLocale
    locale String -> String
    forall a. a -> a
    id (FormatNumericPadding -> Maybe FormatNumericPadding
    forall a. a -> Maybe a
    Just (Char -> FormatNumericPadding
    forall a. a -> Maybe a
    Just Char
    '0')) String
    cs t
    t
    formatTime1 TimeLocale
    locale (Char
    '^' : String
    cs) t
    t = TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    forall t.
    FormatTime t =>
    TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    formatTime2 TimeLocale
    locale ((Char -> Char) -> String -> String
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Char -> Char
    toUpper) Maybe FormatNumericPadding
    forall a. Maybe a
    Nothing String
    cs t
    t
    formatTime1 TimeLocale
    locale (Char
    '#' : String
    cs) t
    t = TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    forall t.
    FormatTime t =>
    TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    formatTime2 TimeLocale
    locale ((Char -> Char) -> String -> String
    forall a b. (a -> b) -> [a] -> [b]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Char -> Char
    toLower) Maybe FormatNumericPadding
    forall a. Maybe a
    Nothing String
    cs t
    t
    formatTime1 TimeLocale
    locale String
    cs t
    t = TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    forall t.
    FormatTime t =>
    TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    formatTime2 TimeLocale
    locale String -> String
    forall a. a -> a
    id Maybe FormatNumericPadding
    forall a. Maybe a
    Nothing String
    cs t
    t

    getDigit :: Char -> Maybe Int
    getDigit :: Char -> Maybe Int
    getDigit Char
    c
        | Char
    c Char -> Char -> Bool
    forall a. Ord a => a -> a -> Bool
    < Char
    '0' = Maybe Int
    forall a. Maybe a
    Nothing
    getDigit Char
    c
        | Char
    c Char -> Char -> Bool
    forall a. Ord a => a -> a -> Bool
    > Char
    '9' = Maybe Int
    forall a. Maybe a
    Nothing
    getDigit Char
    c = Int -> Maybe Int
    forall a. a -> Maybe a
    Just (Int -> Maybe Int) -> Int -> Maybe Int
    forall a b. (a -> b) -> a -> b
    $ (Char -> Int
    ord Char
    c) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    - (Char -> Int
    ord Char
    '0')

    pullNumber :: Maybe Int -> String -> (Maybe Int, String)
    pullNumber :: Maybe Int -> String -> (Maybe Int, String)
    pullNumber Maybe Int
    mx [] = (Maybe Int
    mx, [])
    pullNumber Maybe Int
    mx s :: String
    s@(Char
    c : String
    cs) =
        case Char -> Maybe Int
    getDigit Char
    c of
            Just Int
    i -> Maybe Int -> String -> (Maybe Int, String)
    pullNumber (Int -> Maybe Int
    forall a. a -> Maybe a
    Just (Int -> Maybe Int) -> Int -> Maybe Int
    forall a b. (a -> b) -> a -> b
    $ (Int -> Maybe Int -> Int
    forall a. a -> Maybe a -> a
    fromMaybe Int
    0 Maybe Int
    mx) Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    10 Int -> Int -> Int
    forall a. Num a => a -> a -> a
    + Int
    i) String
    cs
            Maybe Int
    Nothing -> (Maybe Int
    mx, String
    s)

    formatTime2 ::
        (FormatTime t) => TimeLocale -> (String -> String) -> Maybe FormatNumericPadding -> String -> t -> Maybe String
    formatTime2 :: forall t.
    FormatTime t =>
    TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> String
    -> t
    -> Maybe String
    formatTime2 TimeLocale
    locale String -> String
    recase Maybe FormatNumericPadding
    mpad String
    cs t
    t =
        let (Maybe Int
    mwidth, String
    rest) = Maybe Int -> String -> (Maybe Int, String)
    pullNumber Maybe Int
    forall a. Maybe a
    Nothing String
    cs
         in TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> Maybe Int
    -> String
    -> t
    -> Maybe String
    forall t.
    FormatTime t =>
    TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> Maybe Int
    -> String
    -> t
    -> Maybe String
    formatTime3 TimeLocale
    locale String -> String
    recase Maybe FormatNumericPadding
    mpad Maybe Int
    mwidth String
    rest t
    t

    formatTime3 ::
        (FormatTime t) =>
        TimeLocale ->
        (String -> String) ->
        Maybe FormatNumericPadding ->
        Maybe Int ->
        String ->
        t ->
        Maybe String
    formatTime3 :: forall t.
    FormatTime t =>
    TimeLocale
    -> (String -> String)
    -> Maybe FormatNumericPadding
    -> Maybe Int
    -> String
    -> t
    -> Maybe String
    formatTime3 TimeLocale
    locale String -> String
    recase Maybe FormatNumericPadding
    mpad Maybe Int
    mwidth (Char
    'E' : String
    cs) = Bool
    -> (String -> String)
    -> FormatOptions
    -> String
    -> t
    -> Maybe String
    forall t.
    FormatTime t =>
    Bool
    -> (String -> String)
    -> FormatOptions
    -> String
    -> t
    -> Maybe String
    formatTime4 Bool
    True String -> String
    recase (TimeLocale
    -> Maybe FormatNumericPadding -> Maybe Int -> FormatOptions
    MkFormatOptions TimeLocale
    locale Maybe FormatNumericPadding
    mpad Maybe Int
    mwidth) String
    cs
    formatTime3 TimeLocale
    locale String -> String
    recase Maybe FormatNumericPadding
    mpad Maybe Int
    mwidth String
    cs = Bool
    -> (String -> String)
    -> FormatOptions
    -> String
    -> t
    -> Maybe String
    forall t.
    FormatTime t =>
    Bool
    -> (String -> String)
    -> FormatOptions
    -> String
    -> t
    -> Maybe String
    formatTime4 Bool
    False String -> String
    recase (TimeLocale
    -> Maybe FormatNumericPadding -> Maybe Int -> FormatOptions
    MkFormatOptions TimeLocale
    locale Maybe FormatNumericPadding
    mpad Maybe Int
    mwidth) String
    cs

    formatTime4 :: (FormatTime t) => Bool -> (String -> String) -> FormatOptions -> String -> t -> Maybe String
    formatTime4 :: forall t.
    FormatTime t =>
    Bool
    -> (String -> String)
    -> FormatOptions
    -> String
    -> t
    -> Maybe String
    formatTime4 Bool
    alt String -> String
    recase FormatOptions
    fo (Char
    c : String
    cs) t
    t = String -> Maybe String
    forall a. a -> Maybe a
    Just (String -> Maybe String) -> String -> Maybe String
    forall a b. (a -> b) -> a -> b
    $ (String -> String
    recase (Bool -> Char -> FormatOptions -> t -> String
    forall t.
    FormatTime t =>
    Bool -> Char -> FormatOptions -> t -> String
    formatChar Bool
    alt Char
    c FormatOptions
    fo t
    t)) String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ (TimeLocale -> String -> t -> String
    forall t. FormatTime t => TimeLocale -> String -> t -> String
    formatTime (FormatOptions -> TimeLocale
    foLocale FormatOptions
    fo) String
    cs t
    t)
    formatTime4 Bool
    _alt String -> String
    _recase FormatOptions
    _fo [] t
    _t = Maybe String
    forall a. Maybe a
    Nothing

    formatChar :: (FormatTime t) => Bool -> Char -> FormatOptions -> t -> String
    formatChar :: forall t.
    FormatTime t =>
    Bool -> Char -> FormatOptions -> t -> String
    formatChar Bool
    _ Char
    '%' = (TimeLocale -> t -> String) -> FormatOptions -> t -> String
    forall t.
    (TimeLocale -> t -> String) -> FormatOptions -> t -> String
    formatString ((TimeLocale -> t -> String) -> FormatOptions -> t -> String)
    -> (TimeLocale -> t -> String) -> FormatOptions -> t -> String
    forall a b. (a -> b) -> a -> b
    $ \TimeLocale
    _ t
    _ -> String
    "%"
    formatChar Bool
    _ Char
    't' = (TimeLocale -> t -> String) -> FormatOptions -> t -> String
    forall t.
    (TimeLocale -> t -> String) -> FormatOptions -> t -> String
    formatString ((TimeLocale -> t -> String) -> FormatOptions -> t -> String)
    -> (TimeLocale -> t -> String) -> FormatOptions -> t -> String
    forall a b. (a -> b) -> a -> b
    $ \TimeLocale
    _ t
    _ -> String
    "\t"
    formatChar Bool
    _ Char
    'n' = (TimeLocale -> t -> String) -> FormatOptions -> t -> String
    forall t.
    (TimeLocale -> t -> String) -> FormatOptions -> t -> String
    formatString ((TimeLocale -> t -> String) -> FormatOptions -> t -> String)
    -> (TimeLocale -> t -> String) -> FormatOptions -> t -> String
    forall a b. (a -> b) -> a -> b
    $ \TimeLocale
    _ t
    _ -> String
    "\n"
    formatChar Bool
    alt Char
    c =
        case Bool -> Char -> Maybe (FormatOptions -> t -> String)
    forall t.
    FormatTime t =>
    Bool -> Char -> Maybe (FormatOptions -> t -> String)
    formatCharacter Bool
    alt Char
    c of
            Just FormatOptions -> t -> String
    f -> FormatOptions -> t -> String
    f
            Maybe (FormatOptions -> t -> String)
    _ -> \FormatOptions
    _ t
    _ -> String
    ""