+read2' ∷ Num n ⇒ Parser n
+{-# INLINEABLE read2' #-}
+read2' = do n1 ← (char ' ' *> pure 0) <|> digit'
+ n2 ← digit'
+ return (n1 * 10 + n2)
+
+digit' ∷ Num n ⇒ Parser n
+{-# INLINE digit' #-}
+digit' = fromIntegral <$> fromC <$> P.digit
+ where
+ {-# INLINE fromC #-}
+ fromC c = ord c - ord '0'
+
+show4digitsTZ ∷ TimeZone → AsciiBuilder
+show4digitsTZ tz
+ = case timeZoneMinutes tz of
+ offset | offset < 0 → A.toAsciiBuilder "-" ⊕ showTZ' (negate offset)
+ | otherwise → A.toAsciiBuilder "+" ⊕ showTZ' offset
+ where
+ showTZ' offset
+ = let h = offset `div` 60
+ m = offset - h * 60
+ in
+ show2 h ⊕ show2 m
+
+read4digitsTZ ∷ Parser TimeZone
+read4digitsTZ
+ = do sign ← (char '+' *> return 1)
+ <|>
+ (char '-' *> return (-1))
+ hour ← read2
+ minute ← read2
+ let tz = TimeZone {
+ timeZoneMinutes = sign * (hour * 60 + minute)
+ , timeZoneSummerOnly = False
+ , timeZoneName = timeZoneOffsetString tz
+ }
+ return tz
+
+assertWeekDayIsGood ∷ Monad m ⇒ Int → Day → m ()
+{-# INLINEABLE assertWeekDayIsGood #-}
+assertWeekDayIsGood givenWD gregDay
+ = let (_, _, correctWD ) = toWeekDate gregDay
+ (year, month, day) = toGregorian gregDay
+ in
+ unless (givenWD ≡ correctWD)
+ ∘ fail
+ $ concat [ "Gregorian day "
+ , show year
+ , "-"
+ , show month
+ , "-"
+ , show day
+ , " is "
+ , toStr $ longWeekDayName correctWD
+ , ", not "
+ , toStr $ longWeekDayName givenWD
+ ]
+ where
+ toStr ∷ AsciiBuilder → String
+ toStr = A.toString ∘ A.fromAsciiBuilder
+
+assertGregorianDateIsGood ∷ Monad m ⇒ Integer → Int → Int → m Day
+{-# INLINEABLE assertGregorianDateIsGood #-}
+assertGregorianDateIsGood year month day
+ = case fromGregorianValid year month day of
+ Nothing
+ → fail $ concat [ "Invalid gregorian day: "
+ , show year
+ , "-"
+ , show month
+ , "-"
+ , show day
+ ]
+ Just gregDay
+ → return gregDay
+
+assertTimeOfDayIsGood ∷ Monad m ⇒ Int → Int → Pico → m TimeOfDay
+{-# INLINEABLE assertTimeOfDayIsGood #-}
+assertTimeOfDayIsGood hour minute second
+ = case makeTimeOfDayValid hour minute second of
+ Nothing
+ → fail $ concat [ "Invalid time of day: "
+ , show hour
+ , ":"
+ , show minute
+ , ":"
+ , showFixed True second
+ ]
+ Just tod
+ → return tod
+
+optionMaybe ∷ Alternative f ⇒ f a → f (Maybe a)
+{-# INLINE optionMaybe #-}
+optionMaybe p
+ = option Nothing (Just <$> p)
+
+finishOff ∷ Parser α → Parser α
+{-# INLINE finishOff #-}
+finishOff = ((endOfInput *>) ∘ return =≪)
+
+parseAttempt ∷ Exception e
+ ⇒ (String → e)
+ → Parser α
+ → ByteString
+ → Attempt α
+{-# INLINEABLE parseAttempt #-}
+parseAttempt f p bs
+ = case parseOnly (finishOff p) bs of
+ Right α → Success α
+ Left e → Failure $ f e
+
+parseAttempt' ∷ Parser α → Ascii → Attempt α
+{-# INLINE parseAttempt' #-}
+parseAttempt' = (∘ A.toByteString) ∘ parseAttempt StringException