Skip to content

Commit d04489e

Browse files
committed
fix number parser in duration
1 parent b847301 commit d04489e

File tree

3 files changed

+27
-24
lines changed

3 files changed

+27
-24
lines changed

src/Data/Formatter/Interval.purs

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,39 +5,49 @@ module Data.Formatter.Interval
55

66
import Prelude
77
import Data.Interval as I
8+
import Math as Math
89
import Text.Parsing.Parser as P
910
import Text.Parsing.Parser.Combinators as PC
1011
import Text.Parsing.Parser.String as PS
1112
import Control.Alt ((<|>))
12-
import Data.Array (length, some)
13+
import Data.Array (some)
14+
import Data.Function (on)
1315
import Data.Formatter.Internal (digit, foldDigits)
14-
import Data.Int (toNumber)
16+
import Data.Int (toNumber, floor)
1517
import Data.Monoid (mempty)
1618

1719

18-
nums P.Parser String Int
19-
nums = foldDigits <$> some digit
20+
numOfDigits Int Int
21+
numOfDigits 0 = 0
22+
numOfDigits n = 1 + (floor $ log10 $ toNumber n)
2023

21-
-- TODO try to use unformatNumberParser here
22-
number P.Parser String Number
23-
number = do
24-
whole ← nums
25-
_ ← (PC.try $ PS.string ".") <|> (PC.try $ PS.string ",") <|> pure ""
26-
restdigits ← PC.try (some digit) <|> pure [0]
27-
let rest = foldDigits restdigits
28-
pure $ if rest == 0 then toNumber whole else toNumber whole + ((toNumber rest) / (toNumber $ length restdigits))
24+
log10 Number Number
25+
log10 n = Math.log10e * Math.log n
26+
27+
integer P.Parser String Int
28+
integer = some digit <#> foldDigits
2929

30+
pow :: Int -> Int -> Number
31+
pow = Math.pow `on` toNumber
3032

33+
fractional P.Parser String Number
34+
fractional = integer <#> case _ of
35+
0 -> 0.0
36+
n -> (toNumber n) / (pow 10 $ numOfDigits n)
37+
38+
number P.Parser String Number
39+
number = (+)
40+
<$> (integer <#> toNumber)
41+
<*> (PC.option 0.0 $ PC.try $ PS.oneOf ['.', ','] *> fractional)
3142

3243
component String P.Parser String Number
3344
component designator = number <* PS.string designator
3445

3546
tryOr :: a. a P.Parser String a P.Parser String a
3647
tryOr a p = PC.option a $ PC.try p
3748

38-
parseDuration :: P.Parser String (I.Duration)
39-
-- parseDuration = PS.string "P" *> weekDuration
40-
parseDuration = PS.string "P" *> (weekDuration <|> fullDuration)-- <* PS.eof
49+
parseDuration :: P.Parser String I.Duration
50+
parseDuration = PS.string "P" *> (weekDuration <|> fullDuration) <* PS.eof
4151
where
4252
weekDuration :: P.Parser String I.Duration
4353
weekDuration = PC.try $ I.week <$> component "W"

src/Data/Formatter/Number.purs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ module Data.Formatter.Number
1111
, formatNumber
1212
, formatOrShowNumber
1313
, unformatNumber
14-
-- TODO move to internal or add doc
15-
, unformatNumberParser
1614
) where
1715

1816
import Prelude
@@ -22,7 +20,7 @@ import Data.Array as Arr
2220
import Data.Array (many, some)
2321
import Data.Maybe (Maybe(..), fromMaybe, isJust)
2422
import Data.Traversable (for)
25-
import Data.Either (Either(..), either)
23+
import Data.Either (Either, either)
2624
import Data.Int as Int
2725
import Data.String as Str
2826

@@ -219,11 +217,6 @@ unformatNumber ∷ String → String → Either String Number
219217
unformatNumber pattern str =
220218
parseFormatString pattern >>= flip unformat str
221219

222-
unformatNumberParser String P.Parser String Number
223-
unformatNumberParser pattern = case P.runParser pattern formatParser of
224-
Left e → P.fail $ P.parseErrorMessage e
225-
Right p → unformatParser p
226-
227220
-- Supposed to be used in chaining, because after calling format number there is no
228221
-- good way to extract number back to show.
229222
formatOrShowNumber String Number String

test/src/Main.purs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ timeInterval = do
173173
log "- Data.Formatter.Interval.parseDuration"
174174
assertParserRes (P.runParser "P1W" FI.parseDuration) (Right $ I.day 7.0)
175175
assertParserRes (P.runParser "P1.0W" FI.parseDuration) (Right $ I.day 7.0)
176-
assertParserRes (P.runParser "P1.0D" FI.parseDuration) (Right $ I.day 1.0)
176+
assertParserRes (P.runParser "P1.9748600D" FI.parseDuration) (Right $ I.day 1.97486)
177177
assertParserRes (P.runParser "P1DT1H1M1S" FI.parseDuration) (Right $ I.day 1.0 <> I.hours 1.0 <> I.minutes 1.0 <> I.seconds 1.0)
178178
timeTest :: forall e. Tests e Unit
179179
timeTest = do

0 commit comments

Comments
 (0)