module Bookhound.Parsers.DateTime (date, time, timeZoneOffset, localDateTime, offsetDateTime, dateTime, year, day, month, hour, minute, second) where import Bookhound.Parser (Parser, check, withErrorN) import Bookhound.ParserCombinators (IsMatch (..), within, (<#>), (<|>), (|+), (|?)) import Bookhound.Parsers.Char (colon, dash, digit, dot, plus) import Data.Maybe (fromMaybe) import Data.Time (Day, LocalTime (..), TimeOfDay (..), TimeZone, ZonedTime (..), fromGregorian, minutesToTimeZone) date :: Parser Day date :: Parser Day date = forall a. Int -> String -> Parser a -> Parser a withErrorN (-Int 1) String "Date" forall a b. (a -> b) -> a -> b $ Integer -> Int -> Int -> Day fromGregorian forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Parser Integer year forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b <*> forall a b. Parser a -> Parser b -> Parser b within Parser Char dash Parser Int month forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b <*> Parser Int day time :: Parser TimeOfDay time :: Parser TimeOfDay time = forall a. Int -> String -> Parser a -> Parser a withErrorN (-Int 1) String "Time" forall a b. (a -> b) -> a -> b $ do Int h <- Parser Int hour Int m <- Parser Char colon forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b *> Parser Int minute Int s <- Parser Char colon forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b *> Parser Int second Maybe String decimals <- ((Parser Char dot forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b *> Parser String secondDecimals) |?) pure $ Int -> Int -> Pico -> TimeOfDay TimeOfDay Int h Int m forall a b. (a -> b) -> a -> b $ forall a. Read a => String -> a read (forall a. Show a => a -> String show Int s forall a. Semigroup a => a -> a -> a <> forall (t :: * -> *) m a. (Foldable t, Monoid m) => (a -> m) -> t a -> m foldMap (String "." ++) Maybe String decimals) timeZoneOffset :: Parser TimeZone timeZoneOffset :: Parser TimeZone timeZoneOffset = forall a. Int -> String -> Parser a -> Parser a withErrorN (-Int 1) String "Timezone Offset" forall a b. (a -> b) -> a -> b $ do Bool pos <- (Bool True forall (f :: * -> *) a b. Functor f => a -> f b -> f a <$ Parser Char plus) forall a. Parser a -> Parser a -> Parser a <|> (Bool False forall (f :: * -> *) a b. Functor f => a -> f b -> f a <$ Parser Char dash) Int h <- Parser Int hour Int m <- forall a. a -> Maybe a -> a fromMaybe Int 0 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> (Parser Int minute |?) pure $ Int -> TimeZone minutesToTimeZone forall a b. (a -> b) -> a -> b $ (if Bool pos then Int 1 else (-Int 1)) forall a. Num a => a -> a -> a * (Int h forall a. Num a => a -> a -> a * Int 60 forall a. Num a => a -> a -> a + Int m) localDateTime :: Parser LocalTime localDateTime :: Parser LocalTime localDateTime = forall a. Int -> String -> Parser a -> Parser a withErrorN (-Int 1) String "Local DateTime" forall a b. (a -> b) -> a -> b $ Day -> TimeOfDay -> LocalTime LocalTime forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> (Parser Day date forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a <* forall a. IsMatch a => [a] -> Parser a oneOf [Char 'T', Char 't', Char ' ']) forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b <*> Parser TimeOfDay time offsetDateTime :: Parser ZonedTime offsetDateTime :: Parser ZonedTime offsetDateTime = forall a. Int -> String -> Parser a -> Parser a withErrorN (-Int 1) String "Offset DateTime" forall a b. (a -> b) -> a -> b $ LocalTime -> TimeZone -> ZonedTime ZonedTime forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Parser LocalTime localDateTime forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b <*> (forall a. IsMatch a => a -> Parser a is Char ' ' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b *> Parser TimeZone timeZoneOffset) dateTime :: Parser ZonedTime dateTime :: Parser ZonedTime dateTime = forall a. Int -> String -> Parser a -> Parser a withErrorN (-Int 1) String "DateTime" forall a b. (a -> b) -> a -> b $ ((LocalTime -> TimeZone -> ZonedTime `ZonedTime` Int -> TimeZone minutesToTimeZone Int 0) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Parser LocalTime localDateTime forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a <* forall a. IsMatch a => a -> Parser a is Char 'Z') forall a. Parser a -> Parser a -> Parser a <|> Parser ZonedTime offsetDateTime year :: Parser Integer year :: Parser Integer year = forall a. Read a => String -> a read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Parser Char digit forall a. Parser a -> Int -> Parser [a] <#> Int 4 day :: Parser Int day :: Parser Int day = forall a. String -> (a -> Bool) -> Parser a -> Parser a check String "Day" (forall a. Ord a => a -> a -> a -> Bool range Int 1 Int 31) forall a b. (a -> b) -> a -> b $ forall a. Read a => String -> a read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Parser Char digit forall a. Parser a -> Int -> Parser [a] <#> Int 2 month :: Parser Int month :: Parser Int month = forall a. String -> (a -> Bool) -> Parser a -> Parser a check String "Month" (forall a. Ord a => a -> a -> a -> Bool range Int 1 Int 12) forall a b. (a -> b) -> a -> b $ forall a. Read a => String -> a read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Parser Char digit forall a. Parser a -> Int -> Parser [a] <#> Int 2 hour :: Parser Int hour :: Parser Int hour = forall a. String -> (a -> Bool) -> Parser a -> Parser a check String "Hour" (forall a. Ord a => a -> a -> a -> Bool range Int 0 Int 23) forall a b. (a -> b) -> a -> b $ forall a. Read a => String -> a read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Parser Char digit forall a. Parser a -> Int -> Parser [a] <#> Int 2 minute :: Parser Int minute :: Parser Int minute = forall a. String -> (a -> Bool) -> Parser a -> Parser a check String "Minute" (forall a. Ord a => a -> a -> a -> Bool range Int 0 Int 59) forall a b. (a -> b) -> a -> b $ forall a. Read a => String -> a read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Parser Char digit forall a. Parser a -> Int -> Parser [a] <#> Int 2 second :: Parser Int second :: Parser Int second = forall a. String -> (a -> Bool) -> Parser a -> Parser a check String "Second" (forall a. Ord a => a -> a -> a -> Bool range Int 0 Int 59) forall a b. (a -> b) -> a -> b $ forall a. Read a => String -> a read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> Parser Char digit forall a. Parser a -> Int -> Parser [a] <#> Int 2 secondDecimals :: Parser String secondDecimals :: Parser String secondDecimals = forall a. String -> (a -> Bool) -> Parser a -> Parser a check String "Pico Seconds" ((forall a. Ord a => a -> a -> Bool <= Int 12) forall b c a. (b -> c) -> (a -> b) -> a -> c . forall (t :: * -> *) a. Foldable t => t a -> Int length) (Parser Char digit |+) range :: Ord a => a -> a -> a -> Bool range :: forall a. Ord a => a -> a -> a -> Bool range a mn a mx a x = a x forall a. Ord a => a -> a -> Bool >= a mn Bool -> Bool -> Bool && a x forall a. Ord a => a -> a -> Bool <= a mx