{-# LANGUAGE BangPatterns
           , NumericUnderscores
           , UnboxedTuples #-}

{-| Functions for parsing common time formats.
 -}

module Parser.Lathe.Time
  ( -- * Calendar
    year
  , quarter
    
    -- ** Month
  , month
  , monthDate

    -- ** Week
  , weekDate

    -- ** Ordinal
  , ordinalDate

    -- * Time of day
  , timeOfDay

    -- ** Local
  , localTime

    -- ** Zoned
  , timeZone
  , zonedTime
  ) where

import           Parser.Lathe
import           Parser.Lathe.Binary
import           Parser.Lathe.Numeric.Fractional
import           Parser.Lathe.Radix
import           Parser.Lathe.Unsafe

import           Data.Bits
import           Data.ByteString as B (ByteString)
import qualified Data.ByteString.Unsafe as B
import           Data.Fixed
import           Data.Time.Calendar
import           Data.Time.Calendar.Month
import           Data.Time.Calendar.OrdinalDate
import           Data.Time.Calendar.Quarter
import           Data.Time.Calendar.WeekDate
import           Data.Time.LocalTime



-- | Consume four decimal digits that represent an RFC 3339 full year.
year
  :: e             -- ^ Malformed.
  -> e             -- ^ Reached end.
  -> Parser e Year
year :: forall e. e -> e -> Parser e Year
year e
malformed e
end = Int -> (ByteString -> (# Res e Year #)) -> e -> Parser e Year
forall e a. Int -> (ByteString -> (# Res e a #)) -> e -> Parser e a
unsafeRead Int
4 ByteString -> (# Res e Year #)
forall {a}. Num a => ByteString -> (# Res e a #)
conv e
end
  where
    conv :: ByteString -> (# Res e a #)
conv ByteString
b
      | Just Word8
i0 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
0), let  y0 :: Int
y0 =           (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i0)
      , Just Word8
i1 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
1), let !y1 :: Int
y1 = Int
y0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i1)
      , Just Word8
i2 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
2), let !y2 :: Int
y2 = Int
y1 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i2)
      , Just Word8
i3 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
3), let !y3 :: Int
y3 = Int
y2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i3)
          = let !yyyy :: a
yyyy = Int -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
y3 :: Int)
            in (# a -> Res e a
forall a e. a -> Res e a
Yes a
yyyy #)

      | Bool
otherwise = (# e -> Res e a
forall e a. e -> Res e a
No e
malformed #)



-- | Consume 7 bytes that represent a year quarter, in the @yyyy-Qq@ format.
--
--   Note that year quarters are not defined by ISO 8601, this is an informal convention.
quarter
  :: e                -- ^ Out of bounds.
  -> e                -- ^ Malformed.
  -> e                -- ^ Reached end.
  -> Parser e Quarter
quarter :: forall e. e -> e -> e -> Parser e Quarter
quarter e
oob e
malformed e
end = Int -> (ByteString -> (# Res e Quarter #)) -> e -> Parser e Quarter
forall e a. Int -> (ByteString -> (# Res e a #)) -> e -> Parser e a
unsafeRead Int
7 ByteString -> (# Res e Quarter #)
conv e
end
  where
    conv :: ByteString -> (# Res e Quarter #)
conv ByteString
b
      | Just Word8
i0 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
0), let  y0 :: Int
y0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i0
      , Just Word8
i1 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
1), let !y1 :: Int
y1 = Int
y0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i1)
      , Just Word8
i2 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
2), let !y2 :: Int
y2 = Int
y1 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i2)
      , Just Word8
i3 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
3), let !y3 :: Int
y3 = Int
y2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i3)
      , Word8
0x2D Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==         ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
4
      , Word8
0x51 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==         ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
5
      , Just Word8
q0 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
6)
          = let rq :: Maybe QuarterOfYear
rq = case Word8
q0 of
                       Word8
1 -> QuarterOfYear -> Maybe QuarterOfYear
forall a. a -> Maybe a
Just QuarterOfYear
Q1
                       Word8
2 -> QuarterOfYear -> Maybe QuarterOfYear
forall a. a -> Maybe a
Just QuarterOfYear
Q2
                       Word8
3 -> QuarterOfYear -> Maybe QuarterOfYear
forall a. a -> Maybe a
Just QuarterOfYear
Q3
                       Word8
4 -> QuarterOfYear -> Maybe QuarterOfYear
forall a. a -> Maybe a
Just QuarterOfYear
Q4
                       Word8
_ -> Maybe QuarterOfYear
forall a. Maybe a
Nothing

            in case Maybe QuarterOfYear
rq of
                 Maybe QuarterOfYear
Nothing -> (# e -> Res e Quarter
forall e a. e -> Res e a
No e
oob #)
                 Just QuarterOfYear
q  -> let !yyyy :: Year
yyyy = Int -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
y3 :: Int)
                            in (# Quarter -> Res e Quarter
forall a e. a -> Res e a
Yes (Year -> QuarterOfYear -> Quarter
YearQuarter Year
yyyy QuarterOfYear
q) #)

      | Bool
otherwise = (# e -> Res e Quarter
forall e a. e -> Res e a
No e
malformed #)



-- | Consume 7 bytes that represent an RFC 3339 month, in the @yyyy-mm@ format.
month
  :: e              -- ^ Out of bounds
  -> e              -- ^ Malformed.
  -> e              -- ^ Reached end.
  -> Parser e Month
month :: forall e. e -> e -> e -> Parser e Month
month e
oob e
malformed e
end = Int -> (ByteString -> (# Res e Month #)) -> e -> Parser e Month
forall e a. Int -> (ByteString -> (# Res e a #)) -> e -> Parser e a
unsafeRead Int
7 ByteString -> (# Res e Month #)
conv e
end
  where
    conv :: ByteString -> (# Res e Month #)
conv ByteString
b
      | Just Word8
i0 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
0), let  y0 :: Int
y0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i0
      , Just Word8
i1 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
1), let !y1 :: Int
y1 = Int
y0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i1)
      , Just Word8
i2 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
2), let !y2 :: Int
y2 = Int
y1 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i2)
      , Just Word8
i3 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
3), let !y3 :: Int
y3 = Int
y2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i3)
      , Word8
0x2D Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==         ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
4
      , Just Word8
i5 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
5), let  m0 :: Int
m0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i5
      , Just Word8
i6 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
6), let !m1 :: Int
m1 = Int
m0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i6)
          = case Year -> Int -> Maybe Month
fromYearMonthValid (Int -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
y3 :: Int)) Int
m1 of
              Maybe Month
Nothing -> (# e -> Res e Month
forall e a. e -> Res e a
No e
oob #)
              Just Month
ym -> (# Month -> Res e Month
forall a e. a -> Res e a
Yes Month
ym #)

      | Bool
otherwise = (# e -> Res e Month
forall e a. e -> Res e a
No e
malformed #)



-- | Consume 10 bytes that represent an RFC 3339 month date, in the @yyyy-mm-dd@ format.
monthDate
  :: e            -- ^ Out of bounds.
  -> e            -- ^ Malformed.
  -> e            -- ^ Reached end.
  -> Parser e Day
monthDate :: forall e. e -> e -> e -> Parser e Day
monthDate e
oob e
malformed e
end = Int -> (ByteString -> (# Res e Day #)) -> e -> Parser e Day
forall e a. Int -> (ByteString -> (# Res e a #)) -> e -> Parser e a
unsafeRead Int
10 (e -> e -> ByteString -> (# Res e Day #)
forall e. e -> e -> ByteString -> (# Res e Day #)
convMonthDate e
oob e
malformed) e
end

convMonthDate :: e -> e -> B.ByteString -> (# Res e Day #)
convMonthDate :: forall e. e -> e -> ByteString -> (# Res e Day #)
convMonthDate e
oob e
malformed ByteString
b
  | Just Word8
i0 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
0), let  y0 :: Int
y0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i0
  , Just Word8
i1 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
1), let !y1 :: Int
y1 = Int
y0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i1)
  , Just Word8
i2 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
2), let !y2 :: Int
y2 = Int
y1 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i2)
  , Just Word8
i3 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
3), let !y3 :: Int
y3 = Int
y2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i3)
  , Word8
0x2D Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==         ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
4
  , Just Word8
i5 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
5), let  m0 :: Int
m0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i5
  , Just Word8
i6 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
6), let !m1 :: Int
m1 = Int
m0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i6)
  , Word8
0x2D Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==         ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
7
  , Just Word8
i8 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
8), let  d0 :: Int
d0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i8
  , Just Word8
i9 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
9), let !d1 :: Int
d1 = Int
d0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i9)
      = case Year -> Int -> Int -> Maybe Day
fromGregorianValid (Int -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
y3 :: Int)) Int
m1 Int
d1 of
          Maybe Day
Nothing  -> (# e -> Res e Day
forall e a. e -> Res e a
No e
oob #)
          Just Day
ymd -> (# Day -> Res e Day
forall a e. a -> Res e a
Yes Day
ymd #)

  | Bool
otherwise = (# e -> Res e Day
forall e a. e -> Res e a
No e
malformed #)



-- | Consume 10 bytes that represent an ISO 8601 week date,
--   in the extended @yyyy-Www-d@ format.
weekDate
  :: e            -- ^ Out of bounds.
  -> e            -- ^ Malformed.
  -> e            -- ^ Reached end.
  -> Parser e Day
weekDate :: forall e. e -> e -> e -> Parser e Day
weekDate e
oob e
malformed e
end = Int -> (ByteString -> (# Res e Day #)) -> e -> Parser e Day
forall e a. Int -> (ByteString -> (# Res e a #)) -> e -> Parser e a
unsafeRead Int
10 ByteString -> (# Res e Day #)
conv e
end
  where
    conv :: ByteString -> (# Res e Day #)
conv ByteString
b
      | Just Word8
i0 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
0), let  y0 :: Int
y0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i0
      , Just Word8
i1 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
1), let !y1 :: Int
y1 = Int
y0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i1)
      , Just Word8
i2 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
2), let !y2 :: Int
y2 = Int
y1 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i2)
      , Just Word8
i3 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
3), let !y3 :: Int
y3 = Int
y2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i3)
      , Word8
0x2D Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==         ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
4
      , Word8
0x57 Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==         ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
5
      , Just Word8
i6 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
6), let  w0 :: Int
w0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i6
      , Just Word8
i7 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
7), let !w1 :: Int
w1 = Int
w0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i7)
      , Word8
0x2D Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==         ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
8
      , Just Word8
i9 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
9), let  d0 :: Int
d0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i9
          = case Year -> Int -> Int -> Maybe Day
fromWeekDateValid (Int -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
y3 :: Int)) Int
w1 Int
d0 of
              Maybe Day
Nothing  -> (# e -> Res e Day
forall e a. e -> Res e a
No e
oob #)
              Just Day
ymd -> (# Day -> Res e Day
forall a e. a -> Res e a
Yes Day
ymd #)

      | Bool
otherwise = (# e -> Res e Day
forall e a. e -> Res e a
No e
malformed #)



-- | Consume 8 bytes that represent an ISO 8601 ordinal date, in the @yyyy-ddd@ format.
ordinalDate
  :: e            -- ^ Out of bounds.
  -> e            -- ^ Malformed.
  -> e            -- ^ Reached end.
  -> Parser e Day
ordinalDate :: forall e. e -> e -> e -> Parser e Day
ordinalDate e
oob e
malformed e
end = Int -> (ByteString -> (# Res e Day #)) -> e -> Parser e Day
forall e a. Int -> (ByteString -> (# Res e a #)) -> e -> Parser e a
unsafeRead Int
8 ByteString -> (# Res e Day #)
conv e
end
  where
    conv :: ByteString -> (# Res e Day #)
conv ByteString
b
      | Just Word8
i0 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
0), let  y0 :: Int
y0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i0
      , Just Word8
i1 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
1), let !y1 :: Int
y1 = Int
y0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i1)
      , Just Word8
i2 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
2), let !y2 :: Int
y2 = Int
y1 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i2)
      , Just Word8
i3 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
3), let !y3 :: Int
y3 = Int
y2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i3)
      , Word8
0x2D Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==         ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
4
      , Just Word8
i5 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
5), let  d0 :: Int
d0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i5
      , Just Word8
i6 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
6), let !d1 :: Int
d1 = Int
d0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i6)
      , Just Word8
i7 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
7), let !d2 :: Int
d2 = Int
d1 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i7)
          = case Year -> Int -> Maybe Day
fromOrdinalDateValid (Int -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
y3 :: Int)) Int
d2 of
              Maybe Day
Nothing  -> (# e -> Res e Day
forall e a. e -> Res e a
No e
oob #)
              Just Day
ymd -> (# Day -> Res e Day
forall a e. a -> Res e a
Yes Day
ymd #)

      | Bool
otherwise = (# e -> Res e Day
forall e a. e -> Res e a
No e
malformed #)



fraction :: e -> Int -> Parser e Pico
fraction :: forall e. e -> Int -> Parser e Pico
fraction e
malformed Int
ss = do
  Bool
hasDot <- ( do Word8
w <- Bool -> Parser Bool Word8
forall end. end -> Parser end Word8
word8 Bool
False
                 if Word8
w Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x2E
                   then Bool -> Parser Bool Bool
forall a. a -> Parser Bool a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Bool
True
                   else Bool -> Parser Bool Bool
forall e a. e -> Parser e a
err Bool
False
            )
              Parser Bool Bool -> (Bool -> Parser e Bool) -> Parser e Bool
forall e a x. Parser e a -> (e -> Parser x a) -> Parser x a
`catch` Bool -> Parser e Bool
forall a. a -> Parser e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure

  if Bool -> Bool
not Bool
hasDot
    then Pico -> Parser e Pico
forall a. a -> Parser e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Pico -> Parser e Pico) -> Pico -> Parser e Pico
forall a b. (a -> b) -> a -> b
$! Year -> Pico
forall k (a :: k). Year -> Fixed a
MkFixed (Year -> Pico) -> Year -> Pico
forall a b. (a -> b) -> a -> b
$ Int -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ss Year -> Year -> Year
forall a. Num a => a -> a -> a
* Year
1_000_000_000_000
    else do
      ByteOffset
o <- Parser e ByteOffset
forall never. Parser never ByteOffset
bytesRead
      FracFloat Word64
frac <- FracFloat Word64 -> Parser e (FracFloat Word64)
forall never. FracFloat Word64 -> Parser never (FracFloat Word64)
fracFloat52Dec (Word64 -> Int -> FracFloat Word64
forall word. word -> Int -> FracFloat word
FracFloat Word64
0 Int
0)
      ByteOffset
o' <- Parser e ByteOffset
forall never. Parser never ByteOffset
bytesRead
      if ByteOffset
o ByteOffset -> ByteOffset -> Bool
forall a. Eq a => a -> a -> Bool
== ByteOffset
o'
        then e -> Parser e Pico
forall e a. e -> Parser e a
err e
malformed
        else Pico -> Parser e Pico
forall a. a -> Parser e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Pico -> Parser e Pico) -> Pico -> Parser e Pico
forall a b. (a -> b) -> a -> b
$! Year -> Pico
forall k (a :: k). Year -> Fixed a
MkFixed (Year -> Pico) -> Year -> Pico
forall a b. (a -> b) -> a -> b
$ Int -> Year
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ss Year -> Year -> Year
forall a. Num a => a -> a -> a
* Year
1_000_000_000_000
                                               Year -> Year -> Year
forall a. Num a => a -> a -> a
+ Double -> Year
forall b. Integral b => Double -> b
forall a b. (RealFrac a, Integral b) => a -> b
truncate (Sign -> FracFloat Word64 -> Year -> Double
fracToDouble Sign
Plus FracFloat Word64
frac Year
12)




-- | Consume at least 8 bytes that represent an RFC 3339 time of day,
--   in the @hh:mm:ss[.s…]@ format.
timeOfDay
  :: e                  -- ^ Out of bounds.
  -> e                  -- ^ Malformed.
  -> e                  -- ^ Reached end.
  -> Parser e TimeOfDay
timeOfDay :: forall e. e -> e -> e -> Parser e TimeOfDay
timeOfDay e
oob e
malformed e
end = do
  (Int
hh, Int
mm, Int
ss) <- Int
-> (ByteString -> (# Res e (Int, Int, Int) #))
-> e
-> Parser e (Int, Int, Int)
forall e a. Int -> (ByteString -> (# Res e a #)) -> e -> Parser e a
unsafeRead Int
8 (e -> ByteString -> (# Res e (Int, Int, Int) #)
forall e. e -> ByteString -> (# Res e (Int, Int, Int) #)
convTimeOfDay e
malformed) e
end

  Pico
ssms <- e -> Int -> Parser e Pico
forall e. e -> Int -> Parser e Pico
fraction e
malformed Int
ss

  case Int -> Int -> Pico -> Maybe TimeOfDay
makeTimeOfDayValid Int
hh Int
mm Pico
ssms of
    Maybe TimeOfDay
Nothing  -> e -> Parser e TimeOfDay
forall e a. e -> Parser e a
err e
oob
    Just TimeOfDay
tod -> TimeOfDay -> Parser e TimeOfDay
forall a. a -> Parser e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure TimeOfDay
tod

convTimeOfDay :: e -> B.ByteString -> (# Res e (Int, Int, Int) #)
convTimeOfDay :: forall e. e -> ByteString -> (# Res e (Int, Int, Int) #)
convTimeOfDay e
malformed ByteString
b
  | Just Word8
i0 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
0), let  h0 :: Int
h0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i0
  , Just Word8
i1 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
1), let !h1 :: Int
h1 = Int
h0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i1)
  , Word8
0x3A Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==         ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
2
  , Just Word8
i3 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
3), let  m0 :: Int
m0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i3
  , Just Word8
i4 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
4), let !m1 :: Int
m1 = Int
m0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i4)
  , Word8
0x3A Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==         ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
5
  , Just Word8
i6 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
6), let  s0 :: Int
s0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i6
  , Just Word8
i7 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
7), let !s1 :: Int
s1 = Int
s0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i7)
      = (# (Int, Int, Int) -> Res e (Int, Int, Int)
forall a e. a -> Res e a
Yes (Int
h1, Int
m1, Int
s1) #)

  | Bool
otherwise = (# e -> Res e (Int, Int, Int)
forall e a. e -> Res e a
No e
malformed #)



-- | Consume at least 19 bytes that represent an RFC 3339 full time without time zone,
--   in the @yyyy-mm-ddThh:mm:ss[.s…]@ format.
--
--   Either @t@ or space is accepted instead of @T@.
localTime
  :: e                  -- ^ Out of bounds.
  -> e                  -- ^ Malformed.
  -> e                  -- ^ Reached end.
  -> Parser e LocalTime
localTime :: forall e. e -> e -> e -> Parser e LocalTime
localTime e
oob e
malformed e
end = do
  (Day
ymd, Int
hh, Int
mm, Int
ss) <- Int
-> (ByteString -> (# Res e (Day, Int, Int, Int) #))
-> e
-> Parser e (Day, Int, Int, Int)
forall e a. Int -> (ByteString -> (# Res e a #)) -> e -> Parser e a
unsafeRead Int
19 ByteString -> (# Res e (Day, Int, Int, Int) #)
conv e
end

  Pico
ssms <- e -> Int -> Parser e Pico
forall e. e -> Int -> Parser e Pico
fraction e
malformed Int
ss

  case Int -> Int -> Pico -> Maybe TimeOfDay
makeTimeOfDayValid Int
hh Int
mm Pico
ssms of
    Maybe TimeOfDay
Nothing  -> e -> Parser e LocalTime
forall e a. e -> Parser e a
err e
oob
    Just TimeOfDay
tod -> LocalTime -> Parser e LocalTime
forall a. a -> Parser e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (LocalTime -> Parser e LocalTime)
-> LocalTime -> Parser e LocalTime
forall a b. (a -> b) -> a -> b
$! Day -> TimeOfDay -> LocalTime
LocalTime Day
ymd TimeOfDay
tod
  where
    conv :: ByteString -> (# Res e (Day, Int, Int, Int) #)
conv ByteString
b =
      let !(# Res e Day
uymd #) = e -> e -> ByteString -> (# Res e Day #)
forall e. e -> e -> ByteString -> (# Res e Day #)
convMonthDate e
oob e
malformed ByteString
b
      in case Res e Day
uymd of
           No e
e    -> (# e -> Res e (Day, Int, Int, Int)
forall e a. e -> Res e a
No e
e #)
           Yes Day
ymd ->

             let t :: Word8
t = ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
10
             in if (Word8
t Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0xDF) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x54 Bool -> Bool -> Bool
|| Word8
t Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x20
                  then

                    let !(# Res e (Int, Int, Int)
uhns #) = e -> ByteString -> (# Res e (Int, Int, Int) #)
forall e. e -> ByteString -> (# Res e (Int, Int, Int) #)
convTimeOfDay e
malformed (Int -> ByteString -> ByteString
B.unsafeDrop Int
11 ByteString
b)
                    in case Res e (Int, Int, Int)
uhns of
                         No e
e             -> (# e -> Res e (Day, Int, Int, Int)
forall e a. e -> Res e a
No e
e #)
                         Yes (Int
hh, Int
nn, Int
ss) -> (# (Day, Int, Int, Int) -> Res e (Day, Int, Int, Int)
forall a e. a -> Res e a
Yes (Day
ymd, Int
hh, Int
nn, Int
ss) #)

                  else (# e -> Res e (Day, Int, Int, Int)
forall e a. e -> Res e a
No e
malformed #)



-- | Consume 1 or 6 bytes that represent an RFC 3339 time zone,
--   in the @Z@ and @±hh:mm@ formats respectively.
--
--   @z@ is accepted instead of @Z@.
timeZone
  :: e                 -- ^ Out of bounds.
  -> e                 -- ^ Malformed.
  -> e                 -- ^ Reached end.
  -> Parser e TimeZone
timeZone :: forall e. e -> e -> e -> Parser e TimeZone
timeZone e
oob e
malformed e
end = do
  Word8
z <- e -> Parser e Word8
forall end. end -> Parser end Word8
word8 e
end
  if (Word8
z Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0xDF) Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x5A
    then TimeZone -> Parser e TimeZone
forall a. a -> Parser e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure TimeZone
utc
    else if Word8
z Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x2B
           then Bool -> Parser e TimeZone
longZone Bool
False
           else if Word8
z Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
0x2D
                  then Bool -> Parser e TimeZone
longZone Bool
True
                  else e -> Parser e TimeZone
forall e a. e -> Parser e a
err e
malformed
  where
    longZone :: Bool -> Parser e TimeZone
longZone Bool
m = Int
-> (ByteString -> (# Res e TimeZone #)) -> e -> Parser e TimeZone
forall e a. Int -> (ByteString -> (# Res e a #)) -> e -> Parser e a
unsafeRead Int
5 ByteString -> (# Res e TimeZone #)
conv e
end
      where
        conv :: ByteString -> (# Res e TimeZone #)
conv ByteString
b
          | Just Word8
i0 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
0), let  h0 :: Int
h0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i0
          , Just Word8
i1 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
1), let !h1 :: Int
h1 = Int
h0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i1)
          , Word8
0x3A Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
==         ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
2
          , Just Word8
i3 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
3), let  m0 :: Int
m0 =            Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i3
          , Just Word8
i4 <- Word8 -> Maybe Word8
dec (ByteString -> Int -> Word8
B.unsafeIndex ByteString
b Int
4), let !m1 :: Int
m1 = Int
m0 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
10 Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
i4)
              = if Int
h1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
24 Bool -> Bool -> Bool
|| Int
m1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
60
                  then (# e -> Res e TimeZone
forall e a. e -> Res e a
No e
oob #)
                  else let minus :: Int -> Int
minus = if Bool
m
                                     then Int -> Int
forall a. Num a => a -> a
negate
                                     else Int -> Int
forall a. a -> a
id

                           !offset :: Int
offset = Int -> Int
minus (Int -> Int) -> Int -> Int
forall a b. (a -> b) -> a -> b
$ (Int
h1 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
60) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
m1

                       in (# TimeZone -> Res e TimeZone
forall a e. a -> Res e a
Yes (Int -> Bool -> String -> TimeZone
TimeZone Int
offset Bool
False String
"") #)

          | Bool
otherwise = (# e -> Res e TimeZone
forall e a. e -> Res e a
No e
malformed #)



-- | Consume at least 19 bytes that represent an RFC 3339 full time with a time zone.
--
--   Combines behaviors of both 'timeOfDay' and 'timeZone'.
zonedTime
  :: e                  -- ^ Out of bounds.
  -> e                  -- ^ Malformed.
  -> e                  -- ^ Reached end.
  -> Parser e ZonedTime
zonedTime :: forall e. e -> e -> e -> Parser e ZonedTime
zonedTime e
oob e
malformed e
end = do
  LocalTime
local <- e -> e -> e -> Parser e LocalTime
forall e. e -> e -> e -> Parser e LocalTime
localTime e
oob e
malformed e
end
  TimeZone
zone  <- e -> e -> e -> Parser e TimeZone
forall e. e -> e -> e -> Parser e TimeZone
timeZone e
oob e
malformed e
end
  ZonedTime -> Parser e ZonedTime
forall a. a -> Parser e a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ZonedTime -> Parser e ZonedTime)
-> ZonedTime -> Parser e ZonedTime
forall a b. (a -> b) -> a -> b
$! LocalTime -> TimeZone -> ZonedTime
ZonedTime LocalTime
local TimeZone
zone