Skip to content

Commit d75a54e

Browse files
authored
Merge pull request #51 from garyb/negative-year-fix
Format/unformat dates with negative years
2 parents c21cf33 + 8ef3391 commit d75a54e

File tree

2 files changed

+19
-14
lines changed

2 files changed

+19
-14
lines changed

src/Data/Formatter/DateTime.purs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import Data.Generic.Rep (class Generic)
3535
import Data.Generic.Rep.Show (genericShow)
3636
import Data.Int as Int
3737
import Data.List as List
38-
import Data.Maybe (Maybe(..), maybe, fromMaybe)
38+
import Data.Maybe (Maybe(..), fromMaybe, isJust, maybe)
3939
import Data.Newtype (unwrap)
4040
import Data.Ord (abs)
4141
import Data.String as Str
@@ -189,23 +189,24 @@ formatCommand dt@(DT.DateTime d t) = case _ of
189189
MillisecondsTwoDigits → padSingleDigit $ (_ / 10) $ fromEnum $ T.millisecond t
190190
Placeholder s → s
191191

192-
--TODO we need leftpad here
193-
194192
padSingleDigit Int String
195193
padSingleDigit i
196-
| i < 10 = "0" <> (show i)
194+
| i < 0 = "-" <> padSingleDigit (-i)
195+
| i < 10 = "0" <> (show i)
197196
| otherwise = show i
198197

199198
padDoubleDigit Int String
200199
padDoubleDigit i
200+
| i < 0 = "-" <> padDoubleDigit (-i)
201201
| i < 10 = "00" <> (show i)
202202
| i < 100 = "0" <> (show i)
203203
| otherwise = show i
204204

205205
padQuadrupleDigit Int String
206206
padQuadrupleDigit i
207-
| i < 10 = "000" <> (show i)
208-
| i < 100 = "00" <> (show i)
207+
| i < 0 = "-" <> padQuadrupleDigit (-i)
208+
| i < 10 = "000" <> (show i)
209+
| i < 100 = "00" <> (show i)
209210
| i < 1000 = "0" <> (show i)
210211
| otherwise = show i
211212

@@ -223,7 +224,6 @@ data Meridiem = AM | PM
223224

224225
derive instance eqMeridiemEq Meridiem
225226

226-
-- TODO: consider using Map Int
227227
type UnformatAccum =
228228
{ year Maybe Int
229229
, month Maybe Int
@@ -284,8 +284,6 @@ adjustMeridiem (Just AM) n = n
284284
adjustMeridiem Nothing 24 = 0
285285
adjustMeridiem Nothing n = n
286286

287-
288-
289287
exactLength e. ReaderT { maxLength Int, length Int | e } (Either String) Unit
290288
exactLength = ask >>= \({maxLength, length}) → lift if maxLength /= length
291289
then Left $ "Expected " <> (show maxLength) <> " digits but got " <> (show length)
@@ -314,6 +312,15 @@ takeMany :: ∀ f a. Alternative f ⇒ Z.Lazy (f (List.List a)) ⇒ Int → f a
314312
takeMany 0 _ = pure List.Nil
315313
takeMany n v = takeSome n v <|> pure List.Nil
316314

315+
parseSignedInt m
316+
. Monad m
317+
Int
318+
ReaderT { length Int, num Int, maxLength Int } (Either String) Unit
319+
String
320+
P.ParserT String m Int
321+
parseSignedInt maxLength validators errMsg = do
322+
isNegative ← isJust <$> PC.optionMaybe (PS.char '-')
323+
(if isNegative then negate else identity) <$> parseInt maxLength validators errMsg
317324

318325
parseInt m
319326
. Monad m
@@ -333,9 +340,9 @@ parseInt maxLength validators errMsg = do
333340
unformatCommandParser FormatterCommand P.ParserT String (State UnformatAccum) Unit
334341
unformatCommandParser = case _ of
335342
YearFull → _{year = _} `modifyWithParser`
336-
(parseInt 4 exactLength "Incorrect full year")
343+
(parseSignedInt 4 exactLength "Incorrect full year")
337344
YearTwoDigits → _{year = _} `modifyWithParser`
338-
(parseInt 2 exactLength "Incorrect 2-digit year")
345+
(parseSignedInt 2 exactLength "Incorrect 2-digit year")
339346
YearAbsolute → _{year = _} `modifyWithParser`
340347
(lift2 (*)
341348
(PC.option 1 $ PC.try $ PS.string "-" <#> (const (-1)))
@@ -405,8 +412,6 @@ unformatParser f = do
405412
unState s = case runState s initialAccum of
406413
Tuple (Tuple e state) res → pure (Tuple (e $> res) state)
407414

408-
409-
410415
unformatDateTime String String Either String DT.DateTime
411416
unformatDateTime pattern str =
412417
parseFormatString pattern >>= (_ `unformat` str)
@@ -419,7 +424,6 @@ parseMeridiem = (PC.try <<< PS.string) `oneOfAs`
419424
, Tuple "PM" PM
420425
]
421426

422-
423427
parseDayOfWeekName m. Monad m P.ParserT String m D.Weekday
424428
parseDayOfWeekName = (PC.try <<< PS.string) `oneOfAs`
425429
[ Tuple "Monday" D.Monday

test/src/DateTime.purs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ datetimeTest = describe "Data.Formatter.DateTime" do
4848
, { format: "HHmmssSSS", dateStr: "134530123", date: makeDateTime 2017 4 10 13 45 30 123 }
4949
, { format: "HHmm", dateStr: "1345", date: makeDateTime 2017 4 10 13 45 30 123 }
5050
, { format: "X", dateStr: "1499779279", date: makeDateTime 2017 7 11 13 21 19 0 }
51+
, { format: "YYYY", dateStr: "-2000" , date: makeDateTime (-2000) 0 0 0 0 0 0 }
5152
]
5253
(\({ format, dateStr, date }) → do
5354
(format `FDT.formatDateTime` date) `shouldEqual` (Right dateStr)

0 commit comments

Comments
 (0)