Skip to content

Commit 46d4178

Browse files
committed
feat: add gregorian day parser
1 parent bac1368 commit 46d4178

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

src/Text/Megaparsec/Time.hs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module Text.Megaparsec.Time
44
( dateParser
55
, dayParser
66
, durationParser
7+
, gregorianDayParser
78
, hoursParser
89
, minutesParser
910
, secondsParser
@@ -16,11 +17,12 @@ import Control.Monad.Combinators (choice, some)
1617
import Data.Functor (($>))
1718
import Data.List.Extra (lower)
1819
import Data.Maybe (fromMaybe)
19-
import Data.Time (DayOfWeek (..), NominalDiffTime,
20-
TimeOfDay (..),
20+
import Data.Time (Day, DayOfWeek (..),
21+
NominalDiffTime, TimeOfDay (..),
22+
defaultTimeLocale, parseTimeM,
2123
secondsToNominalDiffTime)
2224
import Data.Void (Void)
23-
import Text.Megaparsec (Parsec, try)
25+
import Text.Megaparsec (Parsec, takeRest, try)
2426
import Text.Megaparsec.Char (char, digitChar, space, space1,
2527
string')
2628
import Text.Megaparsec.Utils (posNumParser)
@@ -61,6 +63,12 @@ durationParser = try hours <|> try minutes <|> secondsParser
6163

6264
return $ m + s
6365

66+
gregorianDayParser :: Parsec Void String Day
67+
gregorianDayParser = do
68+
s <- takeRest
69+
parseTimeM False defaultTimeLocale "%F" s <|>
70+
parseTimeM False defaultTimeLocale "%d/%m/%Y" s
71+
6472
hoursParser :: Parsec Void String NominalDiffTime
6573
hoursParser = secondsToNominalDiffTime . (* 3600) <$> posNumParser <* char 'h'
6674

test/Text/Megaparsec/TimeSpec.hs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,18 @@ import Control.Monad (forM_)
88
import Data.Bifunctor (Bifunctor (first))
99
import Data.Either (isLeft)
1010
import Data.List.Extra (lower)
11-
import Data.Time (DayOfWeek (..), TimeOfDay (..),
11+
import Data.Time (Day, DayOfWeek (..), TimeOfDay (..),
1212
defaultTimeLocale, formatTime,
13-
secondsToNominalDiffTime)
13+
fromGregorian, secondsToNominalDiffTime)
1414
import Data.Void (Void)
1515
import Test.Hspec (Spec, context, describe, it, shouldBe,
1616
shouldSatisfy)
1717
import Test.QuickCheck (Arbitrary (..), Gen, elements, forAll,
1818
property, suchThat)
1919
import Text.Megaparsec (Parsec, errorBundlePretty, runParser)
2020
import Text.Megaparsec.Time (dateParser, dayParser, durationParser,
21-
hoursParser, minutesParser,
22-
secondsParser, timeParser)
21+
gregorianDayParser, hoursParser,
22+
minutesParser, secondsParser, timeParser)
2323
import Text.Printf (printf)
2424

2525
instance Arbitrary TimeOfDay where
@@ -32,6 +32,12 @@ instance Arbitrary TimeOfDay where
3232
instance Arbitrary DayOfWeek where
3333
arbitrary = elements [Monday .. Sunday]
3434

35+
instance Arbitrary Day where
36+
arbitrary = fromGregorian
37+
<$> elements [1970 .. 2100]
38+
<*> elements [1 .. 12]
39+
<*> arbitrary
40+
3541
positive
3642
:: Num a
3743
=> Arbitrary a
@@ -156,6 +162,12 @@ spec = do
156162
parseOrPrettyError durationParser (show s) `shouldBe`
157163
Right (secondsToNominalDiffTime (fromInteger s))
158164

165+
describe "gregorian day" $ do
166+
forM_ ["%F", "%d/%m/%Y"] $ \format ->
167+
it format . property $ \d ->
168+
parseOrPrettyError gregorianDayParser (formatTime defaultTimeLocale format d) `shouldBe`
169+
Right d
170+
159171
describe "time" $ do
160172
it "valid" . property $ \t ->
161173
parseOrPrettyError timeParser (formatTime defaultTimeLocale "%R" t) `shouldBe`

0 commit comments

Comments
 (0)