packages feed

text-time 0.1.0 → 0.2.0

raw patch · 8 files changed

+148/−116 lines, 8 filesdep +formatting

Dependencies added: formatting

Files

CHANGES.md view
@@ -1,3 +1,7 @@-# Version 0.1 (2016-12-???)+# Version 0.2 (2016-12-14) -  *+  * ISO formatter++# Version 0.1 (2016-12-13)++  * ISO parser
README.md view
@@ -3,7 +3,7 @@  # Welcome to Text Time library -This library contains fast parser for ISO date from Text into UTCTime data+This library contains fast parser and formatter for iso dates in Text.   
src/Data/Text/Time.hs view
@@ -2,10 +2,12 @@  -- | Parser for ISO date from ByteString module Data.Text.Time-    ( module Data.Text.Time.Parsers+    ( module Data.Text.Time.Parse+    , module Data.Text.Time.Format     ) where  -import Data.Text.Time.Parsers+import Data.Text.Time.Parse+import Data.Text.Time.Format  
+ src/Data/Text/Time/Format.hs view
@@ -0,0 +1,15 @@+{-# LANGUAGE OverloadedStrings #-}++module Data.Text.Time.Format+    ( formatISODateTime+    ) where++import Data.Text.Lazy (Text)+import Formatting (format, (%))+import Formatting.Time (dateDash, hms)+import Data.Time ( UTCTime )+++-- | Format ISO date.+formatISODateTime :: UTCTime -> Text+formatISODateTime utc = format (dateDash % "T" % hms) utc utc
+ src/Data/Text/Time/Parse.hs view
@@ -0,0 +1,106 @@+-- | This code is adapted from sqlite-simple package++module Data.Text.Time.Parse+    ( parseISODateTime+    , parseUTCTimeOrError+    ) where++import           Control.Applicative+import           Control.Monad (when)+import qualified Data.Attoparsec.Text as A+import           Data.Bits ((.&.))+import           Data.Char (isDigit, ord)+import qualified Data.Text as T+import           Data.Time ( Day+                           , TimeOfDay+                           , UTCTime(..)+                           , fromGregorian+                           , fromGregorianValid+                           , makeTimeOfDayValid+                           , midnight+                           , timeOfDayToTime+                           )+++-- | Parse ISO date. If date can't be parsed then this function will return default value instead of error+parseISODateTime :: T.Text -> UTCTime+parseISODateTime str =+    case parseUTCTimeOrError str of+        Left _ -> defaultUTCTime+        Right dt -> dt+++-- | Default time if date can't be parsed+defaultUTCTime :: UTCTime+defaultUTCTime = UTCTime (fromGregorian 1 1 1) 0+++parseUTCTimeOrError :: T.Text -> Either String UTCTime+parseUTCTimeOrError = A.parseOnly getUTCTime++-- | Create UTCTime parser for ISO date time+-- This code is based on code from sqlite-simple package+--+getUTCTime :: A.Parser UTCTime+getUTCTime = do+    day  <- getDay+    time <- ((A.char ' ' <|> A.char 'T') *> getTimeOfDay) <|> pure midnight+    let time' = timeOfDayToTime time+    return (UTCTime day time')+++-- | Date parser+getDay :: A.Parser Day+getDay = do+    yearStr <- A.takeWhile isDigit+    when (T.length yearStr < 4) (fail "year must consist of at least 4 digits")++    let year = toNum yearStr+    month <- (A.char '-' *> digits "month") <|> pure 1+    day   <- (A.char '-' *> digits "day") <|> pure 1+    case fromGregorianValid year month day of+      Nothing -> fail "invalid date"+      Just x  -> return $! x+++getTimeOfDay :: A.Parser TimeOfDay+getTimeOfDay = do+    hour   <- digits "hours"+    _      <- A.char ':'+    minute <- digits "minutes"+    -- Allow omission of seconds.  If seconds is omitted, don't try to+    -- parse the sub-second part.+    (sec,subsec)+           <- ((,) <$> (A.char ':' *> digits "seconds") <*> fract) <|> pure (0,0)++    let picos' = sec + subsec++    case makeTimeOfDayValid hour minute picos' of+      Nothing -> fail "invalid time of day"+      Just x  -> return $! x++    where+      fract =+        (A.char '.' *> (decimal <$> A.takeWhile1 isDigit)) <|> pure 0+++toNum :: Num n => T.Text -> n+toNum = T.foldl' (\a c -> 10*a + digit c) 0+{-# INLINE toNum #-}++digit :: Num n => Char -> n+digit c = fromIntegral (ord c .&. 0x0f)+{-# INLINE digit #-}++digits :: Num n => String -> A.Parser n+digits msg = do+  x <- A.anyChar+  y <- A.anyChar+  if isDigit x && isDigit y+  then return $! (10 * digit x + digit y)+  else fail (msg ++ " is not 2 digits")+{-# INLINE digits #-}++decimal :: Fractional a => T.Text -> a+decimal str = toNum str / 10^(T.length str)+{-# INLINE decimal #-}
− src/Data/Text/Time/Parsers.hs
@@ -1,107 +0,0 @@--module Data.Text.Time.Parsers-    ( parseISODateTime-    , parseUTCTimeOrError-    ) where---- import Prelude-import           Control.Applicative-import           Control.Monad (when)-import qualified Data.Attoparsec.Text as A-import           Data.Bits ((.&.))-import           Data.Char (isDigit, ord)-import qualified Data.Text as T-import           Data.Time ( Day-                           , TimeOfDay-                           , UTCTime(..)-                           , fromGregorian-                           , fromGregorianValid-                           , makeTimeOfDayValid-                           , midnight-                           , timeOfDayToTime-                           )----- | Parse ISO date. If date can't be parsed then this function will return default value instead of error--- Adapted from sqlite-simple package-parseISODateTime :: T.Text -> UTCTime-parseISODateTime str =-    case parseUTCTimeOrError str of-        Left _ -> defaultUTCTime-        Right dt -> dt----- | Default time if date can't be parsed-defaultUTCTime :: UTCTime-defaultUTCTime = UTCTime (fromGregorian 1 1 1) 0---parseUTCTimeOrError :: T.Text -> Either String UTCTime-parseUTCTimeOrError = A.parseOnly getUTCTime---- | Create UTCTime parser for ISO date time--- This code is based on code from sqlite-simple package----getUTCTime :: A.Parser UTCTime-getUTCTime = do-    day  <- getDay-    time <- ((A.char ' ' <|> A.char 'T') *> getTimeOfDay) <|> pure midnight-    let time' = timeOfDayToTime time-    return (UTCTime day time')----- | Date parser-getDay :: A.Parser Day-getDay = do-    yearStr <- A.takeWhile isDigit-    when (T.length yearStr < 4) (fail "year must consist of at least 4 digits")--    let year = toNum yearStr-    month <- (A.char '-' *> digits "month") <|> pure 1-    day   <- (A.char '-' *> digits "day") <|> pure 1-    case fromGregorianValid year month day of-      Nothing -> fail "invalid date"-      Just x  -> return $! x---getTimeOfDay :: A.Parser TimeOfDay-getTimeOfDay = do-    hour   <- digits "hours"-    _      <- A.char ':'-    minute <- digits "minutes"-    -- Allow omission of seconds.  If seconds is omitted, don't try to-    -- parse the sub-second part.-    (sec,subsec)-           <- ((,) <$> (A.char ':' *> digits "seconds") <*> fract) <|> pure (0,0)--    let picos' = sec + subsec--    case makeTimeOfDayValid hour minute picos' of-      Nothing -> fail "invalid time of day"-      Just x  -> return $! x--    where-      fract =-        (A.char '.' *> (decimal <$> A.takeWhile1 isDigit)) <|> pure 0---toNum :: Num n => T.Text -> n-toNum = T.foldl' (\a c -> 10*a + digit c) 0-{-# INLINE toNum #-}--digit :: Num n => Char -> n-digit c = fromIntegral (ord c .&. 0x0f)-{-# INLINE digit #-}--digits :: Num n => String -> A.Parser n-digits msg = do-  x <- A.anyChar-  y <- A.anyChar-  if isDigit x && isDigit y-  then return $! (10 * digit x + digit y)-  else fail (msg ++ " is not 2 digits")-{-# INLINE digits #-}--decimal :: Fractional a => T.Text -> a-decimal str = toNum str / 10^(T.length str)-{-# INLINE decimal #-}
test-src/Data/Text/TimeSpec.hs view
@@ -9,7 +9,7 @@ spec :: Spec spec = do -  describe "Parsers" $ do+  describe "Parse" $ do      it "iso format: YYYY" $ do         parseISODateTime "2014" `shouldBe` UTCTime (fromGregorian 2014 1 1) 0@@ -27,3 +27,10 @@     it "iso format: YYYY-MM-DD HH:MM:SS" $ do         let t = timeOfDayToTime (TimeOfDay 12 34 56)         parseISODateTime "2014-04-23 12:34:56" `shouldBe` UTCTime (fromGregorian 2014 4 23) t+++  describe "Format" $ do++    it "to iso" $ do+        formatISODateTime (UTCTime (fromGregorian 2014 1 1) 13513) `shouldBe` "2014-01-01T03:45:13"+
text-time.cabal view
@@ -1,5 +1,5 @@ name:           text-time-version:        0.1.0+version:        0.2.0 synopsis:       Library for Time parsing from Text into UTCTime License:        BSD3 License-file:   LICENSE@@ -9,7 +9,7 @@                 LICENSE,                 benchmark/*.hs description:-    Fast parser for ISO date from Text to UTCTime+    Fast parser and formatter for ISO date to and from Text homepage:       https://github.com/klangner/text-time author:         Krzysztof Langner maintainer:     klangner@gmail.com@@ -28,12 +28,14 @@   build-depends:                     base >= 4.7 && < 5,                     attoparsec < 0.14,+                    formatting < 7,                     text < 2,                     time < 2   exposed-modules:                     Data.Text.Time   other-modules:-                    Data.Text.Time.Parsers+                    Data.Text.Time.Parse+                    Data.Text.Time.Format  test-suite unit-tests   type:             exitcode-stdio-1.0@@ -45,9 +47,12 @@                     QuickCheck >=2.6 && <3,                     Cabal >=1.16.0 && <2,                     attoparsec < 0.14,+                    formatting < 7,                     text < 2,                     time < 2   other-modules:+                    Data.Text.Time.Parse+                    Data.Text.Time.Format                     Data.Text.Time,                     Data.Text.TimeSpec   hs-source-dirs: