Skip to content

Commit 79f0395

Browse files
authored
Add support for parsing weeks (#29)
* Add support for parsing weeks * Add test for verbose weeks
1 parent 7d58fbe commit 79f0395

File tree

2 files changed

+27
-3
lines changed

2 files changed

+27
-3
lines changed

source/library/Database/PostgreSQL/Simple/Interval/Unstable.hs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -581,9 +581,7 @@ render x =
581581
<> " us"
582582

583583
-- | Parses an interval. This is not a general purpose parser. It only supports
584-
-- the formats that PostgreSQL generates. For example, it will fail to parse an
585-
-- interval like @"1 week"@ because PostgreSQL never uses weeks when rendering
586-
-- intervals.
584+
-- the formats that PostgreSQL generates.
587585
parse :: A.Parser Interval
588586
parse =
589587
-- Start with parsers that have non-empty prefixes, in order to avoid
@@ -636,6 +634,7 @@ parsePostgresVerbose = do
636634
flip A.sepBy " " $
637635
A.choice
638636
[ Years <$> A.signed A.decimal <* maybePlural " year",
637+
Weeks <$> A.signed A.decimal <* maybePlural " week",
639638
Months <$> A.signed A.decimal <* maybePlural " mon",
640639
Days <$> A.signed A.decimal <* maybePlural " day",
641640
Hours <$> A.signed A.decimal <* maybePlural " hour",
@@ -652,6 +651,7 @@ parsePostgres = do
652651
flip A.sepBy " " $
653652
A.choice
654653
[ Years <$> A.signed A.decimal <* maybePlural " year",
654+
Weeks <$> A.signed A.decimal <* maybePlural " week",
655655
Months <$> A.signed A.decimal <* maybePlural " mon",
656656
Days <$> A.signed A.decimal <* maybePlural " day"
657657
]
@@ -688,6 +688,7 @@ maybePlural word = (<>) <$> A.string word <*> A.option "" "s"
688688
-- are accepted, like years and months.
689689
data Component
690690
= Years !Integer
691+
| Weeks !Integer
691692
| Months !Integer
692693
| Days !Integer
693694
| Hours !Integer
@@ -701,6 +702,7 @@ data Component
701702
fromComponent :: Component -> Maybe Interval
702703
fromComponent c = case c of
703704
Years y -> fromYears =<< Bits.toIntegralSized y
705+
Weeks w -> fromWeeks =<< Bits.toIntegralSized w
704706
Months m -> fromMonths <$> Bits.toIntegralSized m
705707
Days d -> fromDays <$> Bits.toIntegralSized d
706708
Hours h -> fromHours =<< Bits.toIntegralSized h
@@ -722,6 +724,7 @@ fromComponents =
722724
negateComponent :: Component -> Component
723725
negateComponent c = case c of
724726
Years y -> Years (-y)
727+
Weeks w -> Weeks (-w)
725728
Months m -> Months (-m)
726729
Days d -> Days (-d)
727730
Hours h -> Hours (-h)

source/test-suite/Main.hs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,27 @@ spec = H.describe "Database.PostgreSQL.Simple.Interval" $ do
402402
let actual = Attoparsec.parseOnly I.parse "-infinity"
403403
actual `H.shouldBe` Right (I.MkInterval minBound minBound minBound)
404404

405+
H.describe "weeks" $ do
406+
H.it "succeeds with zero" $ do
407+
let actual = Attoparsec.parseOnly I.parse "0 weeks"
408+
actual `H.shouldBe` Right (I.MkInterval 0 0 0)
409+
410+
H.it "succeeds with implicit positive" $ do
411+
let actual = Attoparsec.parseOnly I.parse "1 week"
412+
actual `H.shouldBe` Right (I.MkInterval 0 7 0)
413+
414+
H.it "succeeds with explicit positive" $ do
415+
let actual = Attoparsec.parseOnly I.parse "+2 weeks"
416+
actual `H.shouldBe` Right (I.MkInterval 0 14 0)
417+
418+
H.it "succeeds with negative" $ do
419+
let actual = Attoparsec.parseOnly I.parse "-3 weeks"
420+
actual `H.shouldBe` Right (I.MkInterval 0 (-21) 0)
421+
422+
H.it "succeeds with verbose" $ do
423+
let actual = Attoparsec.parseOnly I.parse "@ 4 weeks"
424+
actual `H.shouldBe` Right (I.MkInterval 0 28 0)
425+
405426
Monad.forM_ intervalStyles $ \(_, field) ->
406427
Monad.forM_ examples $ \example -> do
407428
let input = field example

0 commit comments

Comments
 (0)