packages feed

attoparsec-iso8601 1.0.2.0 → 1.0.2.1

raw patch · 5 files changed

+232/−232 lines, 5 filesdep ~attoparsecdep ~basedep ~textnew-uploaderPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: attoparsec, base, text, time

API changes (from Hackage documentation)

Files

− Data/Attoparsec/Time.hs
@@ -1,174 +0,0 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE NoImplicitPrelude #-}-{-# LANGUAGE ScopedTypeVariables #-}--- |--- Module:      Data.Aeson.Parser.Time--- Copyright:   (c) 2015-2016 Bryan O'Sullivan--- License:     BSD3--- Maintainer:  Bryan O'Sullivan <bos@serpentine.com>--- Stability:   experimental--- Portability: portable------ Parsers for parsing dates and times.--module Data.Attoparsec.Time-    (-      day-    , localTime-    , timeOfDay-    , timeZone-    , utcTime-    , zonedTime-    , month-    , quarter-    ) where--import Prelude.Compat--import Control.Applicative ((<|>))-import Control.Monad (void, when)-import Data.Attoparsec.Text as A-import Data.Attoparsec.Time.Internal (toPico)-import Data.Bits ((.&.))-import Data.Char (isDigit, ord)-import Data.Fixed (Pico)-import Data.Int (Int64)-import Data.Maybe (fromMaybe)-import Data.Time.Calendar (Day, fromGregorianValid)-import Data.Time.Calendar.Quarter.Compat (Quarter, QuarterOfYear (..), fromYearQuarter)-import Data.Time.Calendar.Month.Compat (Month, fromYearMonthValid)-import Data.Time.Clock (UTCTime(..))-import qualified Data.Text as T-import qualified Data.Time.LocalTime as Local---- | Parse a date of the form @[+,-]YYYY-MM-DD@.-day :: Parser Day-day = do-  absOrNeg <- negate <$ char '-' <|> id <$ char '+' <|> pure id-  y <- (decimal <* char '-') <|> fail "date must be of form [+,-]YYYY-MM-DD"-  m <- (twoDigits <* char '-') <|> fail "date must be of form [+,-]YYYY-MM-DD"-  d <- twoDigits <|> fail "date must be of form [+,-]YYYY-MM-DD"-  maybe (fail "invalid date") return (fromGregorianValid (absOrNeg y) m d)---- | Parse a month of the form @[+,-]YYYY-MM@.-month :: Parser Month-month = do-  absOrNeg <- negate <$ char '-' <|> id <$ char '+' <|> pure id-  y <- (decimal <* char '-') <|> fail "month must be of form [+,-]YYYY-MM"-  m <- twoDigits <|> fail "month must be of form [+,-]YYYY-MM"-  maybe (fail "invalid month") return (fromYearMonthValid (absOrNeg y) m)---- | Parse a quarter of the form @[+,-]YYYY-QN@.-quarter :: Parser Quarter-quarter = do-  absOrNeg <- negate <$ char '-' <|> id <$ char '+' <|> pure id-  y <- (decimal <* char '-') <|> fail "month must be of form [+,-]YYYY-MM"-  _ <- char 'q' <|> char 'Q'-  q <- parseQ-  return $! fromYearQuarter (absOrNeg y) q-  where-    parseQ = Q1 <$ char '1'-      <|> Q2 <$ char '2'-      <|> Q3 <$ char '3'-      <|> Q4 <$ char '4'---- | Parse a two-digit integer (e.g. day of month, hour).-twoDigits :: Parser Int-twoDigits = do-  a <- digit-  b <- digit-  let c2d c = ord c .&. 15-  return $! c2d a * 10 + c2d b---- | Parse a time of the form @HH:MM[:SS[.SSS]]@.-timeOfDay :: Parser Local.TimeOfDay-timeOfDay = do-  h <- twoDigits-  m <- char ':' *> twoDigits-  s <- option 0 (char ':' *> seconds)-  if h < 24 && m < 60 && s < 61-    then return (Local.TimeOfDay h m s)-    else fail "invalid time"--data T = T {-# UNPACK #-} !Int {-# UNPACK #-} !Int64---- | Parse a count of seconds, with the integer part being two digits--- long.-seconds :: Parser Pico-seconds = do-  real <- twoDigits-  mc <- peekChar-  case mc of-    Just '.' -> do-      t <- anyChar *> takeWhile1 isDigit-      return $! parsePicos real t-    _ -> return $! fromIntegral real- where-  parsePicos a0 t = toPico (fromIntegral (t' * 10^n))-    where T n t'  = T.foldl' step (T 12 (fromIntegral a0)) t-          step ma@(T m a) c-              | m <= 0    = ma-              | otherwise = T (m-1) (10 * a + fromIntegral (ord c) .&. 15)---- | Parse a time zone, and return 'Nothing' if the offset from UTC is--- zero. (This makes some speedups possible.)-timeZone :: Parser (Maybe Local.TimeZone)-timeZone = do-  let maybeSkip c = do ch <- peekChar'; when (ch == c) (void anyChar)-  maybeSkip ' '-  ch <- satisfy $ \c -> c == 'Z' || c == '+' || c == '-'-  if ch == 'Z'-    then return Nothing-    else do-      h <- twoDigits-      mm <- peekChar-      m <- case mm of-             Just ':'           -> anyChar *> twoDigits-             Just d | isDigit d -> twoDigits-             _                  -> return 0-      let off | ch == '-' = negate off0-              | otherwise = off0-          off0 = h * 60 + m-      case undefined of-        _   | off == 0 ->-              return Nothing-            | off < -720 || off > 840 || m > 59 ->-              fail "invalid time zone offset"-            | otherwise ->-              let !tz = Local.minutesToTimeZone off-              in return (Just tz)---- | Parse a date and time, of the form @YYYY-MM-DD HH:MM[:SS[.SSS]]@.--- The space may be replaced with a @T@.  The number of seconds is optional--- and may be followed by a fractional component.-localTime :: Parser Local.LocalTime-localTime = Local.LocalTime <$> day <* daySep <*> timeOfDay-  where daySep = satisfy (\c -> c == 'T' || c == ' ')---- | Behaves as 'zonedTime', but converts any time zone offset into a--- UTC time.-utcTime :: Parser UTCTime-utcTime = do-  lt@(Local.LocalTime d t) <- localTime-  mtz <- timeZone-  case mtz of-    Nothing -> let !tt = Local.timeOfDayToTime t-               in return (UTCTime d tt)-    Just tz -> return $! Local.localTimeToUTC tz lt---- | Parse a date with time zone info. Acceptable formats:------ @YYYY-MM-DD HH:MM Z@--- @YYYY-MM-DD HH:MM:SS Z@--- @YYYY-MM-DD HH:MM:SS.SSS Z@------ The first space may instead be a @T@, and the second space is--- optional.  The @Z@ represents UTC.  The @Z@ may be replaced with a--- time zone offset of the form @+0000@ or @-08:00@, where the first--- two digits are hours, the @:@ is optional and the second two digits--- (also optional) are minutes.-zonedTime :: Parser Local.ZonedTime-zonedTime = Local.ZonedTime <$> localTime <*> (fromMaybe utc <$> timeZone)--utc :: Local.TimeZone-utc = Local.TimeZone 0 False ""
− Data/Attoparsec/Time/Internal.hs
@@ -1,49 +0,0 @@-{-# LANGUAGE NoImplicitPrelude #-}--- |--- Module:      Data.Aeson.Internal.Time--- Copyright:   (c) 2015-2016 Bryan O'Sullivan--- License:     BSD3--- Maintainer:  Bryan O'Sullivan <bos@serpentine.com>--- Stability:   experimental--- Portability: portable--module Data.Attoparsec.Time.Internal-    (-      TimeOfDay64(..)-    , fromPico-    , toPico-    , diffTimeOfDay64-    , toTimeOfDay64-    ) where--import Prelude.Compat--import Data.Fixed (Fixed(MkFixed), Pico)-import Data.Int (Int64)-import Data.Time (TimeOfDay(..))-import Data.Time.Clock.Compat--toPico :: Integer -> Pico-toPico = MkFixed--fromPico :: Pico -> Integer-fromPico (MkFixed i) = i---- | Like TimeOfDay, but using a fixed-width integer for seconds.-data TimeOfDay64 = TOD {-# UNPACK #-} !Int-                       {-# UNPACK #-} !Int-                       {-# UNPACK #-} !Int64--posixDayLength :: DiffTime-posixDayLength = 86400--diffTimeOfDay64 :: DiffTime -> TimeOfDay64-diffTimeOfDay64 t-  | t >= posixDayLength = TOD 23 59 (60000000000000 + pico (t - posixDayLength))-  | otherwise = TOD (fromIntegral h) (fromIntegral m) s-    where (h,mp) = pico t `quotRem` 3600000000000000-          (m,s)  = mp `quotRem` 60000000000000-          pico   = fromIntegral . diffTimeToPicoseconds--toTimeOfDay64 :: TimeOfDay -> TimeOfDay64-toTimeOfDay64 (TimeOfDay h m s) = TOD h m (fromIntegral (fromPico s))
attoparsec-iso8601.cabal view
@@ -1,6 +1,6 @@ name:            attoparsec-iso8601-version:         1.0.2.0-synopsis:        Parsing of ISO 8601 dates, originally from aeson.+version:         1.0.2.1+synopsis:        Parsing of ISO 8601 dates, originally from aeson description:     Parsing of ISO 8601 dates, originally from aeson. license:         BSD3 license-file:    LICENSE@@ -14,7 +14,7 @@ homepage:        https://github.com/haskell/aeson bug-reports:     https://github.com/haskell/aeson/issues build-type:      Simple-tested-with:     GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.3, GHC == 8.10.1+tested-with:     GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.4, GHC == 8.10.4, GHC == 9.0.1 extra-source-files:   README.md @@ -29,19 +29,19 @@   manual: True  library-  hs-source-dirs:      .+  hs-source-dirs:      src   default-language:    Haskell2010   ghc-options:         -Wall   exposed-modules:     Data.Attoparsec.Time.Internal     Data.Attoparsec.Time   build-depends:-    attoparsec >= 0.13.0.1 && < 0.14.0.0,-    base >= 4.7 && < 5,-    base-compat-batteries >= 0.10.0 && < 0.12,+    attoparsec >= 0.14.2 && < 0.15,+    base >= 4.9 && < 5,+    base-compat-batteries >= 0.10.0 && < 0.13,     time-compat >= 1.9.4 && < 1.10,-    text >= 1.1.1.0 && < 1.3.0.0,-    time >= 1.1.1.4 && < 1.12+    text >= 1.2.3.0 && < 1.3.0.0 || >= 2.0 && <2.1,+    time >= 1.6.0.1 && < 1.13    if flag(fast)     ghc-options: -O0
+ src/Data/Attoparsec/Time.hs view
@@ -0,0 +1,174 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE ScopedTypeVariables #-}+-- |+-- Module:      Data.Aeson.Parser.Time+-- Copyright:   (c) 2015-2016 Bryan O'Sullivan+-- License:     BSD3+-- Maintainer:  Bryan O'Sullivan <bos@serpentine.com>+-- Stability:   experimental+-- Portability: portable+--+-- Parsers for parsing dates and times.++module Data.Attoparsec.Time+    (+      day+    , localTime+    , timeOfDay+    , timeZone+    , utcTime+    , zonedTime+    , month+    , quarter+    ) where++import Prelude.Compat++import Control.Applicative ((<|>))+import Control.Monad (void, when)+import Data.Attoparsec.Text (Parser, char, decimal, digit, option, anyChar, peekChar, peekChar', takeWhile1, satisfy)+import Data.Attoparsec.Time.Internal (toPico)+import Data.Bits ((.&.))+import Data.Char (isDigit, ord)+import Data.Fixed (Pico)+import Data.Int (Int64)+import Data.Maybe (fromMaybe)+import Data.Time.Calendar (Day, fromGregorianValid)+import Data.Time.Calendar.Quarter.Compat (Quarter, QuarterOfYear (..), fromYearQuarter)+import Data.Time.Calendar.Month.Compat (Month, fromYearMonthValid)+import Data.Time.Clock (UTCTime(..))+import qualified Data.Text as T+import qualified Data.Time.LocalTime as Local++-- | Parse a date of the form @[+,-]YYYY-MM-DD@.+day :: Parser Day+day = do+  absOrNeg <- negate <$ char '-' <|> id <$ char '+' <|> pure id+  y <- (decimal <* char '-') <|> fail "date must be of form [+,-]YYYY-MM-DD"+  m <- (twoDigits <* char '-') <|> fail "date must be of form [+,-]YYYY-MM-DD"+  d <- twoDigits <|> fail "date must be of form [+,-]YYYY-MM-DD"+  maybe (fail "invalid date") return (fromGregorianValid (absOrNeg y) m d)++-- | Parse a month of the form @[+,-]YYYY-MM@.+month :: Parser Month+month = do+  absOrNeg <- negate <$ char '-' <|> id <$ char '+' <|> pure id+  y <- (decimal <* char '-') <|> fail "month must be of form [+,-]YYYY-MM"+  m <- twoDigits <|> fail "month must be of form [+,-]YYYY-MM"+  maybe (fail "invalid month") return (fromYearMonthValid (absOrNeg y) m)++-- | Parse a quarter of the form @[+,-]YYYY-QN@.+quarter :: Parser Quarter+quarter = do+  absOrNeg <- negate <$ char '-' <|> id <$ char '+' <|> pure id+  y <- (decimal <* char '-') <|> fail "month must be of form [+,-]YYYY-MM"+  _ <- char 'q' <|> char 'Q'+  q <- parseQ+  return $! fromYearQuarter (absOrNeg y) q+  where+    parseQ = Q1 <$ char '1'+      <|> Q2 <$ char '2'+      <|> Q3 <$ char '3'+      <|> Q4 <$ char '4'++-- | Parse a two-digit integer (e.g. day of month, hour).+twoDigits :: Parser Int+twoDigits = do+  a <- digit+  b <- digit+  let c2d c = ord c .&. 15+  return $! c2d a * 10 + c2d b++-- | Parse a time of the form @HH:MM[:SS[.SSS]]@.+timeOfDay :: Parser Local.TimeOfDay+timeOfDay = do+  h <- twoDigits+  m <- char ':' *> twoDigits+  s <- option 0 (char ':' *> seconds)+  if h < 24 && m < 60 && s < 61+    then return (Local.TimeOfDay h m s)+    else fail "invalid time"++data T = T {-# UNPACK #-} !Int {-# UNPACK #-} !Int64++-- | Parse a count of seconds, with the integer part being two digits+-- long.+seconds :: Parser Pico+seconds = do+  real <- twoDigits+  mc <- peekChar+  case mc of+    Just '.' -> do+      t <- anyChar *> takeWhile1 isDigit+      return $! parsePicos real t+    _ -> return $! fromIntegral real+ where+  parsePicos a0 t = toPico (fromIntegral (t' * 10^n))+    where T n t'  = T.foldl' step (T 12 (fromIntegral a0)) t+          step ma@(T m a) c+              | m <= 0    = ma+              | otherwise = T (m-1) (10 * a + fromIntegral (ord c) .&. 15)++-- | Parse a time zone, and return 'Nothing' if the offset from UTC is+-- zero. (This makes some speedups possible.)+timeZone :: Parser (Maybe Local.TimeZone)+timeZone = do+  let maybeSkip c = do ch <- peekChar'; when (ch == c) (void anyChar)+  maybeSkip ' '+  ch <- satisfy $ \c -> c == 'Z' || c == '+' || c == '-'+  if ch == 'Z'+    then return Nothing+    else do+      h <- twoDigits+      mm <- peekChar+      m <- case mm of+             Just ':'           -> anyChar *> twoDigits+             Just d | isDigit d -> twoDigits+             _                  -> return 0+      let off | ch == '-' = negate off0+              | otherwise = off0+          off0 = h * 60 + m+      case undefined of+        _   | off == 0 ->+              return Nothing+            | off < -720 || off > 840 || m > 59 ->+              fail "invalid time zone offset"+            | otherwise ->+              let !tz = Local.minutesToTimeZone off+              in return (Just tz)++-- | Parse a date and time, of the form @YYYY-MM-DD HH:MM[:SS[.SSS]]@.+-- The space may be replaced with a @T@.  The number of seconds is optional+-- and may be followed by a fractional component.+localTime :: Parser Local.LocalTime+localTime = Local.LocalTime <$> day <* daySep <*> timeOfDay+  where daySep = satisfy (\c -> c == 'T' || c == ' ')++-- | Behaves as 'zonedTime', but converts any time zone offset into a+-- UTC time.+utcTime :: Parser UTCTime+utcTime = do+  lt@(Local.LocalTime d t) <- localTime+  mtz <- timeZone+  case mtz of+    Nothing -> let !tt = Local.timeOfDayToTime t+               in return (UTCTime d tt)+    Just tz -> return $! Local.localTimeToUTC tz lt++-- | Parse a date with time zone info. Acceptable formats:+--+-- @YYYY-MM-DD HH:MM Z@+-- @YYYY-MM-DD HH:MM:SS Z@+-- @YYYY-MM-DD HH:MM:SS.SSS Z@+--+-- The first space may instead be a @T@, and the second space is+-- optional.  The @Z@ represents UTC.  The @Z@ may be replaced with a+-- time zone offset of the form @+0000@ or @-08:00@, where the first+-- two digits are hours, the @:@ is optional and the second two digits+-- (also optional) are minutes.+zonedTime :: Parser Local.ZonedTime+zonedTime = Local.ZonedTime <$> localTime <*> (fromMaybe utc <$> timeZone)++utc :: Local.TimeZone+utc = Local.TimeZone 0 False ""
+ src/Data/Attoparsec/Time/Internal.hs view
@@ -0,0 +1,49 @@+{-# LANGUAGE NoImplicitPrelude #-}+-- |+-- Module:      Data.Aeson.Internal.Time+-- Copyright:   (c) 2015-2016 Bryan O'Sullivan+-- License:     BSD3+-- Maintainer:  Bryan O'Sullivan <bos@serpentine.com>+-- Stability:   experimental+-- Portability: portable++module Data.Attoparsec.Time.Internal+    (+      TimeOfDay64(..)+    , fromPico+    , toPico+    , diffTimeOfDay64+    , toTimeOfDay64+    ) where++import Prelude.Compat++import Data.Fixed (Fixed(MkFixed), Pico)+import Data.Int (Int64)+import Data.Time (TimeOfDay(..))+import Data.Time.Clock.Compat (DiffTime, diffTimeToPicoseconds)++toPico :: Integer -> Pico+toPico = MkFixed++fromPico :: Pico -> Integer+fromPico (MkFixed i) = i++-- | Like TimeOfDay, but using a fixed-width integer for seconds.+data TimeOfDay64 = TOD {-# UNPACK #-} !Int+                       {-# UNPACK #-} !Int+                       {-# UNPACK #-} !Int64++posixDayLength :: DiffTime+posixDayLength = 86400++diffTimeOfDay64 :: DiffTime -> TimeOfDay64+diffTimeOfDay64 t+  | t >= posixDayLength = TOD 23 59 (60000000000000 + pico (t - posixDayLength))+  | otherwise = TOD (fromIntegral h) (fromIntegral m) s+    where (h,mp) = pico t `quotRem` 3600000000000000+          (m,s)  = mp `quotRem` 60000000000000+          pico   = fromIntegral . diffTimeToPicoseconds++toTimeOfDay64 :: TimeOfDay -> TimeOfDay64+toTimeOfDay64 (TimeOfDay h m s) = TOD h m (fromIntegral (fromPico s))