-----------------------------------------------------------------------------
-- |
-- Module      :  Data.HodaTime.Pattern.LocalTime
-- Copyright   :  (C) 2017 Jason Johnson
-- License     :  BSD-style (see the file LICENSE)
-- Maintainer  :  Jason Johnson <jason.johnson.081@gmail.com>
-- Stability   :  experimental
-- Portability :  POSIX, Windows
--
-- Patterns for a 'Data.HodaTime.LocalTime.LocalTime': the standard time layouts (@pt@, @pT@, @pr@) together with the
-- individual field patterns (@pHH@, @phh@, @pmm@, @pss@, @pfrac@, @ppp@ and friends) from which custom time patterns are
-- built.  The primed variant @ppp'@ takes a 'Data.HodaTime.Locale.Locale' for its AM\/PM designators.
----------------------------------------------------------------------------
module Data.HodaTime.Pattern.LocalTime
(
  -- * Standard Patterns
   pt
  ,pT
  ,pr
  -- * Custom Patterns
  --
  -- | Used to create specialized patterns
  ,phour
  ,pHH
  ,phh
  ,phhSpace
  ,pminute
  ,pmm
  ,psecond
  ,pss
  ,pfrac
  ,pp
  ,ppp
  ,ppp'
  ,pPeriod
  ,hour'
  ,minute'
  ,second'
)
where

import Data.HodaTime.Pattern.Internal
import Data.HodaTime.Pattern.ParseTypes (TimeInfo)
import qualified Data.HodaTime.Pattern.ParseTypes as PT(hour, minute, second)
import Data.HodaTime.LocalTime.Internal (HasLocalTime)
import qualified Data.HodaTime.LocalTime.Internal as LT(hour, setHour, minute, setMinute, second, setSecond, nanosecond, setNanosecond)
import Control.Applicative ((<|>))
import Formatting (Format, later, left, (%.))
import qualified Data.Text as T
import qualified Data.Text.Lazy.Builder as TLB
import Text.Parsec (oneOf, digit, count, try, (<?>))
import qualified Text.Parsec as P (char)
import Data.HodaTime.Locale.Internal (Locale(..))

-- x = maybe (error "duh") id $ localTime 1 2 3 0
-- parse pT "01:01:01" :: IO LocalTime
-- format pT x
-- format pt x

-- | The double digit hour of day in the 12-hour clock; a value 01-12.  When formatting, the underlying 24-hour
--   value is folded into the 1-12 range (e.g. both 00:00 and 12:00 render as @12@).  When parsing, the value is
--   combined with an AM\/PM designator ('pp' \/ 'ppp') if one is present in the pattern; if no designator is
--   present the value is interpreted as the morning (so @12@ parses to midnight).
--
--   'phh' and the AM\/PM designators are /order independent/: each only rewrites its own portion of the hour, so
--   @'phh' '<%' 'char' \' \' '<>' 'ppp'@ and @'ppp' '<%' 'char' \' \' '<>' 'phh'@ both round-trip correctly.
phh :: HasLocalTime lt => Pattern (lt -> lt) (lt -> String) String
phh :: forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
phh = Parser Int String
-> ((lt -> Int) -> Format String (lt -> String))
-> Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
Parser Int String
-> ((lt -> Int) -> Format String (lt -> String))
-> Pattern (lt -> lt) (lt -> String) String
twelveHour Parser Int String
forall {u}. ParsecT String u Identity Int
paddedNum (lt -> Int) -> Format String (lt -> String)
forall b a r. Show b => (a -> b) -> Format r (a -> r)
f_shown_two
  where
    paddedNum :: ParsecT String u Identity Int
paddedNum = (Char -> Char -> Int
forall n. (Num n, Read n) => Char -> Char -> n
digitsToInt (Char -> Char -> Int)
-> ParsecT String u Identity Char
-> ParsecT String u Identity (Char -> Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Char -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'0' ParsecT String u Identity (Char -> Int)
-> ParsecT String u Identity Char -> ParsecT String u Identity Int
forall a b.
ParsecT String u Identity (a -> b)
-> ParsecT String u Identity a -> ParsecT String u Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> String -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf [Char
'1'..Char
'9']) ParsecT String u Identity Int
-> ParsecT String u Identity Int -> ParsecT String u Identity Int
forall a.
ParsecT String u Identity a
-> ParsecT String u Identity a -> ParsecT String u Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Char -> Char -> Int
forall n. (Num n, Read n) => Char -> Char -> n
digitsToInt (Char -> Char -> Int)
-> ParsecT String u Identity Char
-> ParsecT String u Identity (Char -> Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Char -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'1' ParsecT String u Identity (Char -> Int)
-> ParsecT String u Identity Char -> ParsecT String u Identity Int
forall a b.
ParsecT String u Identity (a -> b)
-> ParsecT String u Identity a -> ParsecT String u Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> String -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf [Char
'0'..Char
'2'])

-- | The hour of day in the 12-hour clock, /space/-padded to two characters (the @strftime@ @%l@ convention), e.g.
--   @\" 3\"@.  Like 'phh' it folds the 24-hour value into 1-12 and combines with an AM\/PM designator on parse.
phhSpace :: HasLocalTime lt => Pattern (lt -> lt) (lt -> String) String
phhSpace :: forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
phhSpace = Parser Int String
-> ((lt -> Int) -> Format String (lt -> String))
-> Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
Parser Int String
-> ((lt -> Int) -> Format String (lt -> String))
-> Pattern (lt -> lt) (lt -> String) String
twelveHour (Int -> Int -> Int -> Parser Int String
pDigitsSpace Int
2 Int
1 Int
12) (Int -> (lt -> Int) -> Format String (lt -> String)
forall b a r. Show b => Int -> (a -> b) -> Format r (a -> r)
f_shown_spad Int
2)

-- | Shared builder for the 12-hour clock hour: @numP@ parses the 1-12 value and @mkFmt@ renders it (given a getter of
--   the folded 1-12 hour).  Only the 1-12 position of the hour is rewritten on parse, preserving the AM\/PM half so it
--   stays order-independent with 'pp'\/'ppp'.
twelveHour :: HasLocalTime lt => Parser Int String -> ((lt -> Int) -> Format String (lt -> String)) -> Pattern (lt -> lt) (lt -> String) String
twelveHour :: forall lt.
HasLocalTime lt =>
Parser Int String
-> ((lt -> Int) -> Format String (lt -> String))
-> Pattern (lt -> lt) (lt -> String) String
twelveHour Parser Int String
numP (lt -> Int) -> Format String (lt -> String)
mkFmt = Parser (lt -> lt) String
-> Format String (lt -> String)
-> Pattern (lt -> lt) (lt -> String) String
forall a b r. Parser a r -> Format r b -> Pattern a b r
Pattern Parser (lt -> lt) String
par ((lt -> Int) -> Format String (lt -> String)
mkFmt (Int -> Int
forall {a}. Integral a => a -> a
to12 (Int -> Int) -> (lt -> Int) -> lt -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. lt -> Int
forall lt. HasLocalTime lt => lt -> Int
LT.hour))
  where
    par :: Parser (lt -> lt) String
par = (Int -> lt -> lt
forall {lt}. HasLocalTime lt => Int -> lt -> lt
adjust (Int -> lt -> lt) -> Parser Int String -> Parser (lt -> lt) String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Int String
numP) Parser (lt -> lt) String -> String -> Parser (lt -> lt) String
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"hour: 01-12"
    adjust :: Int -> lt -> lt
adjust Int
n lt
lt = Int -> lt -> lt
forall {lt}. HasLocalTime lt => Int -> lt -> lt
LT.setHour (Int
12 Int -> Int -> Int
forall a. Num a => a -> a -> a
* (lt -> Int
forall lt. HasLocalTime lt => lt -> Int
LT.hour lt
lt Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
12) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
n Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12)) lt
lt
    to12 :: a -> a
to12 a
h = if a
h' a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0 then a
12 else a
h' where h' :: a
h' = a
h a -> a -> a
forall a. Integral a => a -> a -> a
`mod` a
12

-- | The hour of day in the 24-hour clock as @w@ digits, zero-padded; a width of @1@ means /no padding/.  Values 00-23.
phour :: HasLocalTime lt => Int -> Pattern (lt -> lt) (lt -> String) String
phour :: forall lt.
HasLocalTime lt =>
Int -> Pattern (lt -> lt) (lt -> String) String
phour Int
w = (lt -> Int)
-> (Int -> lt -> lt)
-> Parser Int String
-> ((lt -> Int) -> Format String (lt -> String))
-> String
-> Pattern (lt -> lt) (lt -> String) String
forall s a.
(s -> a)
-> (a -> s -> s)
-> Parser a String
-> ((s -> a) -> Format String (s -> String))
-> String
-> Pattern (s -> s) (s -> String) String
pat_field lt -> Int
forall lt. HasLocalTime lt => lt -> Int
LT.hour Int -> lt -> lt
forall {lt}. HasLocalTime lt => Int -> lt -> lt
LT.setHour (Int -> Int -> Int -> Int -> Parser Int String
pDigits Int
w Int
2 Int
0 Int
23) (Int -> (lt -> Int) -> Format String (lt -> String)
forall b a r. Show b => Int -> (a -> b) -> Format r (a -> r)
f_shown_pad Int
w) String
"hour: 00-23"

-- | The double digit hour of day in the 24-hour clock (@'phour' 2@); a value 00-23.
pHH :: HasLocalTime lt => Pattern (lt -> lt) (lt -> String) String
pHH :: forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pHH = Int -> Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
Int -> Pattern (lt -> lt) (lt -> String) String
phour Int
2

hour' :: HasLocalTime lt => Pattern (TimeInfo -> TimeInfo) (lt -> String) String
hour' :: forall lt.
HasLocalTime lt =>
Pattern (TimeInfo -> TimeInfo) (lt -> String) String
hour' = Lens TimeInfo TimeInfo Int Int
-> (lt -> Int)
-> Parser Int String
-> ((lt -> Int) -> Format String (lt -> String))
-> String
-> Pattern (TimeInfo -> TimeInfo) (lt -> String) String
forall s a s' a'.
Lens s s a a
-> (s' -> a')
-> Parser a String
-> ((s' -> a') -> Format String (s' -> String))
-> String
-> Pattern (s -> s) (s' -> String) String
pat_lens_field (Int -> f Int) -> TimeInfo -> f TimeInfo
Lens TimeInfo TimeInfo Int Int
PT.hour lt -> Int
forall lt. HasLocalTime lt => lt -> Int
LT.hour (Parser Int String
forall {u}. ParsecT String u Identity Int
p_a Parser Int String -> Parser Int String -> Parser Int String
forall a.
ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser Int String
forall {u}. ParsecT String u Identity Int
p_b) (lt -> Int) -> Format String (lt -> String)
forall b a r. Show b => (a -> b) -> Format r (a -> r)
f_shown_two String
"hour: 00-23"
  where
    p_a :: ParsecT String u Identity Int
p_a = Char -> Char -> Int
forall n. (Num n, Read n) => Char -> Char -> n
digitsToInt (Char -> Char -> Int)
-> ParsecT String u Identity Char
-> ParsecT String u Identity (Char -> Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf [Char
'0', Char
'1'] ParsecT String u Identity (Char -> Int)
-> ParsecT String u Identity Char -> ParsecT String u Identity Int
forall a b.
ParsecT String u Identity (a -> b)
-> ParsecT String u Identity a -> ParsecT String u Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT String u Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
digit 
    p_b :: ParsecT String u Identity Int
p_b = Char -> Char -> Int
forall n. (Num n, Read n) => Char -> Char -> n
digitsToInt (Char -> Char -> Int)
-> ParsecT String u Identity Char
-> ParsecT String u Identity (Char -> Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Char -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
P.char Char
'2' ParsecT String u Identity (Char -> Int)
-> ParsecT String u Identity Char -> ParsecT String u Identity Int
forall a b.
ParsecT String u Identity (a -> b)
-> ParsecT String u Identity a -> ParsecT String u Identity b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> String -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf [Char
'0'..Char
'3']

-- | The minute of the hour as @w@ digits, zero-padded; a width of @1@ means /no padding/.  Values 00-59.
pminute :: HasLocalTime lt => Int -> Pattern (lt -> lt) (lt -> String) String
pminute :: forall lt.
HasLocalTime lt =>
Int -> Pattern (lt -> lt) (lt -> String) String
pminute Int
w = (lt -> Int)
-> (Int -> lt -> lt)
-> Parser Int String
-> ((lt -> Int) -> Format String (lt -> String))
-> String
-> Pattern (lt -> lt) (lt -> String) String
forall s a.
(s -> a)
-> (a -> s -> s)
-> Parser a String
-> ((s -> a) -> Format String (s -> String))
-> String
-> Pattern (s -> s) (s -> String) String
pat_field lt -> Int
forall lt. HasLocalTime lt => lt -> Int
LT.minute Int -> lt -> lt
forall {lt}. HasLocalTime lt => Int -> lt -> lt
LT.setMinute (Int -> Int -> Int -> Int -> Parser Int String
pDigits Int
w Int
2 Int
0 Int
59) (Int -> (lt -> Int) -> Format String (lt -> String)
forall b a r. Show b => Int -> (a -> b) -> Format r (a -> r)
f_shown_pad Int
w) String
"minute: 00-59"

-- | The double digit minute of the hour (@'pminute' 2@); a value 00-59.
pmm :: HasLocalTime lt => Pattern (lt -> lt) (lt -> String) String
pmm :: forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pmm = Int -> Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
Int -> Pattern (lt -> lt) (lt -> String) String
pminute Int
2

minute' :: HasLocalTime lt => Pattern (TimeInfo -> TimeInfo) (lt -> String) String
minute' :: forall lt.
HasLocalTime lt =>
Pattern (TimeInfo -> TimeInfo) (lt -> String) String
minute' = Lens TimeInfo TimeInfo Int Int
-> (lt -> Int)
-> Parser Int String
-> ((lt -> Int) -> Format String (lt -> String))
-> String
-> Pattern (TimeInfo -> TimeInfo) (lt -> String) String
forall s a s' a'.
Lens s s a a
-> (s' -> a')
-> Parser a String
-> ((s' -> a') -> Format String (s' -> String))
-> String
-> Pattern (s -> s) (s' -> String) String
pat_lens_field (Int -> f Int) -> TimeInfo -> f TimeInfo
Lens TimeInfo TimeInfo Int Int
PT.minute lt -> Int
forall lt. HasLocalTime lt => lt -> Int
LT.minute Parser Int String
forall n. (Num n, Read n) => Parser n String
p_sixty (lt -> Int) -> Format String (lt -> String)
forall b a r. Show b => (a -> b) -> Format r (a -> r)
f_shown_two String
"minute: 00-59"

-- | The second of the minute as @w@ digits, zero-padded; a width of @1@ means /no padding/.  Values 00-59.
psecond :: HasLocalTime lt => Int -> Pattern (lt -> lt) (lt -> String) String
psecond :: forall lt.
HasLocalTime lt =>
Int -> Pattern (lt -> lt) (lt -> String) String
psecond Int
w = (lt -> Int)
-> (Int -> lt -> lt)
-> Parser Int String
-> ((lt -> Int) -> Format String (lt -> String))
-> String
-> Pattern (lt -> lt) (lt -> String) String
forall s a.
(s -> a)
-> (a -> s -> s)
-> Parser a String
-> ((s -> a) -> Format String (s -> String))
-> String
-> Pattern (s -> s) (s -> String) String
pat_field lt -> Int
forall lt. HasLocalTime lt => lt -> Int
LT.second Int -> lt -> lt
forall {lt}. HasLocalTime lt => Int -> lt -> lt
LT.setSecond (Int -> Int -> Int -> Int -> Parser Int String
pDigits Int
w Int
2 Int
0 Int
59) (Int -> (lt -> Int) -> Format String (lt -> String)
forall b a r. Show b => Int -> (a -> b) -> Format r (a -> r)
f_shown_pad Int
w) String
"second: 00-59"

-- | The double digit second of the minute (@'psecond' 2@); a value 00-59.
pss :: HasLocalTime lt => Pattern (lt -> lt) (lt -> String) String
pss :: forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pss = Int -> Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
Int -> Pattern (lt -> lt) (lt -> String) String
psecond Int
2

second' :: HasLocalTime lt => Pattern (TimeInfo -> TimeInfo) (lt -> String) String
second' :: forall lt.
HasLocalTime lt =>
Pattern (TimeInfo -> TimeInfo) (lt -> String) String
second' = Lens TimeInfo TimeInfo Int Int
-> (lt -> Int)
-> Parser Int String
-> ((lt -> Int) -> Format String (lt -> String))
-> String
-> Pattern (TimeInfo -> TimeInfo) (lt -> String) String
forall s a s' a'.
Lens s s a a
-> (s' -> a')
-> Parser a String
-> ((s' -> a') -> Format String (s' -> String))
-> String
-> Pattern (s -> s) (s' -> String) String
pat_lens_field (Int -> f Int) -> TimeInfo -> f TimeInfo
Lens TimeInfo TimeInfo Int Int
PT.second lt -> Int
forall lt. HasLocalTime lt => lt -> Int
LT.second Parser Int String
forall n. (Num n, Read n) => Parser n String
p_sixty (lt -> Int) -> Format String (lt -> String)
forall b a r. Show b => (a -> b) -> Format r (a -> r)
f_shown_two String
"second: 00-59"

-- | Fractional seconds of a fixed width @n@ (1-9 digits, since the underlying resolution is nanoseconds).  Formatting
--   shows exactly @n@ zero-padded digits (dropping any finer resolution); parsing reads exactly @n@ digits and scales
--   them back up to nanoseconds (so @'pfrac' 3@ parses milliseconds).  A width outside 1-9 is a programmer error.
--
--   NOTE: this is the first pattern that takes a parameter (all the others are nullary values).  The parameterized form
--   was chosen because @pf@\/@pF@ are already taken by the standard date\/time patterns and because it covers every
--   width uniformly.  If parameterized patterns stay rare we may revisit this; a trailing-zero-trimming variant (the
--   NodaTime @F@ specifier) could also be added later.
pfrac :: HasLocalTime lt => Int -> Pattern (lt -> lt) (lt -> String) String
pfrac :: forall lt.
HasLocalTime lt =>
Int -> Pattern (lt -> lt) (lt -> String) String
pfrac Int
n
  | Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
1 Bool -> Bool -> Bool
|| Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
9 = String -> Pattern (lt -> lt) (lt -> String) String
forall a. HasCallStack => String -> a
error String
"pfrac: fractional second width must be between 1 and 9"
  | Bool
otherwise = Parser (lt -> lt) String
-> Format String (lt -> String)
-> Pattern (lt -> lt) (lt -> String) String
forall a b r. Parser a r -> Format r b -> Pattern a b r
Pattern Parser (lt -> lt) String
forall {u}. ParsecT String u Identity (lt -> lt)
par Format String (lt -> String)
forall {r'}. Format r' (lt -> r')
fmt
  where
    scale :: Int
scale = Int
10 Int -> Int -> Int
forall a b. (Num a, Integral b) => a -> b -> a
^ (Int
9 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n) :: Int
    par :: ParsecT String u Identity (lt -> lt)
par = ((Int -> lt -> lt
forall {lt}. HasLocalTime lt => Int -> lt -> lt
LT.setNanosecond (Int -> lt -> lt) -> (String -> Int) -> String -> lt -> lt
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
scale) (Int -> Int) -> (String -> Int) -> String -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Int
forall a. Read a => String -> a
read) (String -> lt -> lt)
-> ParsecT String u Identity String
-> ParsecT String u Identity (lt -> lt)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int
-> ParsecT String u Identity Char
-> ParsecT String u Identity String
forall s (m :: * -> *) t u a.
Stream s m t =>
Int -> ParsecT s u m a -> ParsecT s u m [a]
count Int
n ParsecT String u Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
digit) ParsecT String u Identity (lt -> lt)
-> String -> ParsecT String u Identity (lt -> lt)
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> (String
"fractional second: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
n String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" digits")
    fmt :: Format r' (lt -> r')
fmt = Int -> Char -> Format r' (Builder -> r')
forall a r. Buildable a => Int -> Char -> Format r (a -> r)
left Int
n Char
'0' Format r' (Builder -> r')
-> Format r' (lt -> r') -> Format r' (lt -> r')
forall r r' a.
Format r (Builder -> r') -> Format r' a -> Format r a
%. (lt -> Int) -> Format r' (lt -> r')
forall b a r. Show b => (a -> b) -> Format r (a -> r)
f_shown (\lt
lt -> lt -> Int
forall lt. HasLocalTime lt => lt -> Int
LT.nanosecond lt
lt Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
scale)

-- | 12 hour clock time period designation short form; either @A@ or @P@.  See 'ppp' for the long form.
pp ::  HasLocalTime lt => Pattern (lt -> lt) (lt -> String) String
pp :: forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pp = Parser (lt -> lt) String
-> Format String (lt -> String)
-> Pattern (lt -> lt) (lt -> String) String
forall a b r. Parser a r -> Format r b -> Pattern a b r
Pattern Parser (lt -> lt) String
forall {u}. ParsecT String u Identity (lt -> lt)
par ((Bool -> String) -> Format String (lt -> String)
forall lt.
HasLocalTime lt =>
(Bool -> String) -> Format String (lt -> String)
amPmFormat Bool -> String
render)
  where
    par :: ParsecT String u Identity (lt -> lt)
par = (Bool -> lt -> lt
forall lt. HasLocalTime lt => Bool -> lt -> lt
amPmSetter (Bool -> lt -> lt)
-> ParsecT String u Identity Bool
-> ParsecT String u Identity (lt -> lt)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT String u Identity Bool
forall {u}. ParsecT String u Identity Bool
desig) ParsecT String u Identity (lt -> lt)
-> String -> ParsecT String u Identity (lt -> lt)
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"period: A or P"
    desig :: ParsecT String u Identity Bool
desig = (Bool
True Bool
-> ParsecT String u Identity Char -> ParsecT String u Identity Bool
forall a b.
a -> ParsecT String u Identity b -> ParsecT String u Identity a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
"Pp") ParsecT String u Identity Bool
-> ParsecT String u Identity Bool -> ParsecT String u Identity Bool
forall a.
ParsecT String u Identity a
-> ParsecT String u Identity a -> ParsecT String u Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Bool
False Bool
-> ParsecT String u Identity Char -> ParsecT String u Identity Bool
forall a b.
a -> ParsecT String u Identity b -> ParsecT String u Identity a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ String -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
"Aa")
    render :: Bool -> String
render Bool
isPM = if Bool
isPM then String
"P" else String
"A"

-- | 12 hour clock time period designation full form; either @AM@ or @PM@.  When parsing, this only sets whether the
--   hour is in the morning or afternoon; combine with 'phh' to parse a full 12-hour time.
ppp ::  HasLocalTime lt => Pattern (lt -> lt) (lt -> String) String
ppp :: forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
ppp = Parser (lt -> lt) String
-> Format String (lt -> String)
-> Pattern (lt -> lt) (lt -> String) String
forall a b r. Parser a r -> Format r b -> Pattern a b r
Pattern Parser (lt -> lt) String
forall {u}. ParsecT String u Identity (lt -> lt)
par ((Bool -> String) -> Format String (lt -> String)
forall lt.
HasLocalTime lt =>
(Bool -> String) -> Format String (lt -> String)
amPmFormat Bool -> String
render)
  where
    par :: ParsecT String u Identity (lt -> lt)
par = (Bool -> lt -> lt
forall lt. HasLocalTime lt => Bool -> lt -> lt
amPmSetter (Bool -> lt -> lt)
-> ParsecT String u Identity Bool
-> ParsecT String u Identity (lt -> lt)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT String u Identity Bool
forall {u}. ParsecT String u Identity Bool
desig) ParsecT String u Identity (lt -> lt)
-> String -> ParsecT String u Identity (lt -> lt)
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"period: AM or PM"
    desig :: ParsecT String u Identity Bool
desig = (\Char
c -> Char
c Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
"Pp") (Char -> Bool)
-> ParsecT String u Identity Char -> ParsecT String u Identity Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
"AaPp" ParsecT String u Identity Bool
-> ParsecT String u Identity Char -> ParsecT String u Identity Bool
forall a b.
ParsecT String u Identity a
-> ParsecT String u Identity b -> ParsecT String u Identity a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* String -> ParsecT String u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
"Mm"
    render :: Bool -> String
render Bool
isPM = if Bool
isPM then String
"PM" else String
"AM"

-- | 12 hour clock time period designator using an explicit @(am, pm)@ pair, instead of the built-in @AM@\/@PM@ literals.
--   This is the calendar-agnostic core behind the locale-aware 'ppp''.  Parsing matches either designator
--   case-insensitively (PM tried first); as with 'ppp' it only sets morning\/afternoon, so combine it with 'phh'.
pPeriod :: HasLocalTime lt => (String, String) -> Pattern (lt -> lt) (lt -> String) String
pPeriod :: forall lt.
HasLocalTime lt =>
(String, String) -> Pattern (lt -> lt) (lt -> String) String
pPeriod (String
am, String
pm) = Parser (lt -> lt) String
-> Format String (lt -> String)
-> Pattern (lt -> lt) (lt -> String) String
forall a b r. Parser a r -> Format r b -> Pattern a b r
Pattern Parser (lt -> lt) String
par ((Bool -> String) -> Format String (lt -> String)
forall lt.
HasLocalTime lt =>
(Bool -> String) -> Format String (lt -> String)
amPmFormat Bool -> String
render)
  where
    par :: Parser (lt -> lt) String
par = (Bool -> lt -> lt
forall lt. HasLocalTime lt => Bool -> lt -> lt
amPmSetter (Bool -> lt -> lt)
-> ParsecT String () Identity Bool -> Parser (lt -> lt) String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT String () Identity Bool
desig) Parser (lt -> lt) String -> String -> Parser (lt -> lt) String
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"period"
    desig :: ParsecT String () Identity Bool
desig = (Bool
True Bool
-> ParsecT String () Identity String
-> ParsecT String () Identity Bool
forall a b.
a -> ParsecT String () Identity b -> ParsecT String () Identity a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String -> ParsecT String () Identity String
caseInsensitiveString String
pm)) ParsecT String () Identity Bool
-> ParsecT String () Identity Bool
-> ParsecT String () Identity Bool
forall a.
ParsecT String () Identity a
-> ParsecT String () Identity a -> ParsecT String () Identity a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Bool
False Bool
-> ParsecT String () Identity String
-> ParsecT String () Identity Bool
forall a b.
a -> ParsecT String () Identity b -> ParsecT String () Identity a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ ParsecT String () Identity String
-> ParsecT String () Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String -> ParsecT String () Identity String
caseInsensitiveString String
am))
    render :: Bool -> String
render Bool
isPM = if Bool
isPM then String
pm else String
am

-- | 12 hour clock time period designator in the given 'Locale' (e.g. the POSIX @AM_STR@\/@PM_STR@); the locale-aware
--   counterpart to 'ppp'.  NOTE: some locales (e.g. German) leave these designators empty, in which case this pattern
--   cannot round-trip; prefer a 24-hour pattern there.
ppp' :: HasLocalTime lt => Locale -> Pattern (lt -> lt) (lt -> String) String
ppp' :: forall lt.
HasLocalTime lt =>
Locale -> Pattern (lt -> lt) (lt -> String) String
ppp' Locale
loc = (String, String) -> Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
(String, String) -> Pattern (lt -> lt) (lt -> String) String
pPeriod (Locale -> String
amName Locale
loc, Locale -> String
pmName Locale
loc)

-- | Rewrite only the AM\/PM half of the hour (morning \<-\> afternoon), preserving the 1-12 position set by 'phh'.
amPmSetter :: HasLocalTime lt => Bool -> lt -> lt
amPmSetter :: forall lt. HasLocalTime lt => Bool -> lt -> lt
amPmSetter Bool
isPM lt
lt = Int -> lt -> lt
forall {lt}. HasLocalTime lt => Int -> lt -> lt
LT.setHour (Int
h12 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ if Bool
isPM then Int
12 else Int
0) lt
lt
  where h12 :: Int
h12 = lt -> Int
forall lt. HasLocalTime lt => lt -> Int
LT.hour lt
lt Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12

-- | Render the AM\/PM designator, choosing the form via the supplied function (True == PM).
amPmFormat :: HasLocalTime lt => (Bool -> String) -> Format String (lt -> String)
amPmFormat :: forall lt.
HasLocalTime lt =>
(Bool -> String) -> Format String (lt -> String)
amPmFormat Bool -> String
render = (lt -> Builder) -> Format String (lt -> String)
forall a r. (a -> Builder) -> Format r (a -> r)
later (Text -> Builder
TLB.fromText (Text -> Builder) -> (lt -> Text) -> lt -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> Text) -> (lt -> String) -> lt -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> String
render (Bool -> String) -> (lt -> Bool) -> lt -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= (Int
12 :: Int)) (Int -> Bool) -> (lt -> Int) -> lt -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. lt -> Int
forall lt. HasLocalTime lt => lt -> Int
LT.hour)

-- | Short format pattern. Currently defined as "HH:mm" but should eventually follow the locale
pt :: HasLocalTime lt => Pattern (lt -> lt) (lt -> String) String
pt :: forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pt = Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pHH Pattern (lt -> lt) (lt -> String) String
-> Pattern Char String String
-> Pattern (lt -> lt) (lt -> String) String
forall a b r c. Pattern a b r -> Pattern c r r -> Pattern a b r
<% Char -> Pattern Char String String
char Char
':' Pattern (lt -> lt) (lt -> String) String
-> Pattern (lt -> lt) (lt -> String) String
-> Pattern (lt -> lt) (lt -> String) String
forall a. Semigroup a => a -> a -> a
<> Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pmm

-- | Long format pattern. Currently defined as "HH:mm:ss" but should eventually follow locale
pT ::  HasLocalTime lt => Pattern (lt -> lt) (lt -> String) String
pT :: forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pT = Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pHH Pattern (lt -> lt) (lt -> String) String
-> Pattern Char String String
-> Pattern (lt -> lt) (lt -> String) String
forall a b r c. Pattern a b r -> Pattern c r r -> Pattern a b r
<% Char -> Pattern Char String String
char Char
':' Pattern (lt -> lt) (lt -> String) String
-> Pattern (lt -> lt) (lt -> String) String
-> Pattern (lt -> lt) (lt -> String) String
forall a. Semigroup a => a -> a -> a
<> Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pmm Pattern (lt -> lt) (lt -> String) String
-> Pattern Char String String
-> Pattern (lt -> lt) (lt -> String) String
forall a b r c. Pattern a b r -> Pattern c r r -> Pattern a b r
<% Char -> Pattern Char String String
char Char
':' Pattern (lt -> lt) (lt -> String) String
-> Pattern (lt -> lt) (lt -> String) String
-> Pattern (lt -> lt) (lt -> String) String
forall a. Semigroup a => a -> a -> a
<> Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pss
-- | The round-trippable time pattern, "HH:mm:ss.fffffffff" (nanosecond precision).
pr ::  HasLocalTime lt => Pattern (lt -> lt) (lt -> String) String
pr :: forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pr = Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
Pattern (lt -> lt) (lt -> String) String
pT Pattern (lt -> lt) (lt -> String) String
-> Pattern Char String String
-> Pattern (lt -> lt) (lt -> String) String
forall a b r c. Pattern a b r -> Pattern c r r -> Pattern a b r
<% Char -> Pattern Char String String
char Char
'.' Pattern (lt -> lt) (lt -> String) String
-> Pattern (lt -> lt) (lt -> String) String
-> Pattern (lt -> lt) (lt -> String) String
forall a. Semigroup a => a -> a -> a
<> Int -> Pattern (lt -> lt) (lt -> String) String
forall lt.
HasLocalTime lt =>
Int -> Pattern (lt -> lt) (lt -> String) String
pfrac Int
9