module Bookhound.Parsers.DateTime (date, time, timeZoneOffset, localDateTime, offsetDateTime, dateTime, year, day, month, hour, minute, second) where import Bookhound.Parser (Parser, check, withError) import Bookhound.ParserCombinators (IsMatch (..), within, (<#>), (<|>), (|+), (|?)) import Bookhound.Parsers.Char (colon, dash, digit, plus) import Data.Maybe (fromMaybe) import Data.Time (Day, LocalTime (..), TimeOfDay (..), TimeZone, ZonedTime (..), fromGregorian, minutesToTimeZone) date :: Parser Day date :: Parser Day date = forall a. String -> Parser a -> Parser a withError 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. String -> Parser a -> Parser a withError 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 Integer decimals <- forall a. a -> Maybe a -> a fromMaybe Integer 0 forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> ((Parser Char colon forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b *> Parser Integer 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 <> String "." forall a. Semigroup a => a -> a -> a <> forall a. Show a => a -> String show Integer decimals) timeZoneOffset :: Parser TimeZone timeZoneOffset :: Parser TimeZone timeZoneOffset = forall a. String -> Parser a -> Parser a withError 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 Char colon forall (f :: * -> *) a b. Applicative f => f a -> f b -> 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. String -> Parser a -> Parser a withError 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']) 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. String -> Parser a -> Parser a withError 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 <*> Parser TimeZone timeZoneOffset dateTime :: Parser ZonedTime dateTime :: Parser ZonedTime dateTime = forall a. String -> Parser a -> Parser a withError 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 -> Integer -> Parser [a] <#> Integer 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 -> Integer -> Parser [a] <#> Integer 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 -> Integer -> Parser [a] <#> Integer 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 -> Integer -> Parser [a] <#> Integer 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 -> Integer -> Parser [a] <#> Integer 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 -> Integer -> Parser [a] <#> Integer 2 secondDecimals :: Parser Integer secondDecimals :: Parser Integer secondDecimals = forall a. Read a => String -> a read forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> 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