Skip to content

Commit 47f8362

Browse files
authored
Merge pull request #8 from dgendill/master
hh, MM, and YY < 10 show leading zero
2 parents 10576c0 + 0982de6 commit 47f8362

File tree

5 files changed

+162
-55
lines changed

5 files changed

+162
-55
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44
/output/
55
/.psci*
66
/src/.webpack.js
7+
.psc-ide-port

bower.json

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,14 @@
77
"output"
88
],
99
"dependencies": {
10-
"purescript-console": "^2.0.0",
11-
"purescript-arrays": "^3.0.0",
12-
"purescript-tuples": "^3.0.0",
13-
"purescript-maybe": "^2.0.1",
14-
"purescript-either": "^2.0.0",
10+
"purescript-prelude": "^2.1.0",
1511
"purescript-parsing": "^3.0.0",
1612
"purescript-fixed-points": "^2.0.0",
17-
"purescript-const": "^2.0.0",
1813
"purescript-datetime": "^2.0.0"
1914
},
2015
"devDependencies": {
16+
"purescript-aff": "^2.0.2",
17+
"purescript-console": "^2.0.0",
2118
"purescript-psci-support": "^2.0.0",
2219
"purescript-debug": "^2.0.0"
2320
}

src/Data/Formatter/DateTime.purs

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ module Data.Formatter.DateTime
99
, unformatDateTime
1010
) where
1111

12-
import Prelude
13-
14-
import Control.Lazy as Lazy
12+
import Prelude
13+
14+
import Control.Lazy as Lazy
1515
import Control.Monad.State (State, runState, put, modify)
1616
import Control.Monad.Trans.Class (lift)
1717

18+
import Data.Ord (abs)
1819
import Data.Array (some)
1920
import Data.Array as Arr
2021
import Data.Bifunctor (lmap)
@@ -31,13 +32,14 @@ import Data.String as Str
3132
import Data.Time as T
3233
import Data.Time.Duration as Dur
3334
import Data.Tuple (Tuple(..))
34-
35+
import Data.Foldable (foldr)
3536
import Data.Formatter.Internal (digit, foldDigits)
3637

3738
import Text.Parsing.Parser as P
3839
import Text.Parsing.Parser.Combinators as PC
3940
import Text.Parsing.Parser.String as PS
4041

42+
4143
data FormatterF a
4244
= YearFull a
4345
| YearTwoDigits a
@@ -109,6 +111,18 @@ parseFormatString ∷ String → Either String Formatter
109111
parseFormatString s =
110112
lmap P.parseErrorMessage $ P.runParser s formatParser
111113

114+
-- | Formatting function that accepts a number that is a year,
115+
-- | and strips away the non-significant digits, leaving only the
116+
-- | ones and tens positions.
117+
formatYearTwoDigits :: Int -> String
118+
formatYearTwoDigits i = case dateLength of
119+
1 -> "0" <> dateString
120+
2 -> dateString
121+
_ -> Str.drop (dateLength - 2) dateString
122+
where
123+
dateString = show $ abs i
124+
dateLength = Str.length $ dateString
125+
112126

113127
placeholderContent P.Parser String String
114128
placeholderContent =
@@ -155,24 +169,18 @@ formatF
155169
formatF cb dt@(DT.DateTime d t) = case _ of
156170
YearFull a →
157171
(show $ fromEnum $ D.year d) <> cb a
158-
YearTwoDigits a →
159-
let
160-
y = fromEnum $ D.year d
161-
adjustedYear
162-
| y > 2000 = y - 2000
163-
| y > 1900 = y - 1900
164-
-- A bit strange situation when user wants to format year from not 20th or 21st centuries as
165-
-- two digits.
166-
| otherwise = y
167-
in show y <> cb a
172+
YearTwoDigits a ->
173+
let y = (fromEnum $ D.year d)
174+
in (formatYearTwoDigits y) <> cb a
168175
YearAbsolute a →
169176
show (fromEnum $ D.year d) <> cb a
170177
MonthFull a →
171178
show (D.month d) <> cb a
172179
MonthShort a →
173180
printShortMonth (D.month d) <> cb a
174181
MonthTwoDigits a →
175-
show (fromEnum $ D.month d) <> cb a
182+
let month = fromEnum $ D.month d
183+
in (padSingleDigit month) <> cb a
176184
DayOfMonth a →
177185
show (fromEnum $ D.day d) <> cb a
178186
UnixTimestamp a →
@@ -183,7 +191,7 @@ formatF cb dt@(DT.DateTime d t) = case _ of
183191
show (fromEnum $ T.hour t) <> cb a
184192
Hours12 a →
185193
let fix12 h = if h == 0 then 12 else h
186-
in show (fix12 $ (fromEnum $ T.hour t) `mod` 12) <> cb a
194+
in (padSingleDigit $ fix12 $ (fromEnum $ T.hour t) `mod` 12) <> cb a
187195
Meridiem a →
188196
(if (fromEnum $ T.hour t) >= 12 then "PM" else "AM") <> cb a
189197
Minutes a →
@@ -196,6 +204,10 @@ formatF cb dt@(DT.DateTime d t) = case _ of
196204
s <> cb a
197205
End""
198206

207+
padSingleDigit :: Int -> String
208+
padSingleDigit i
209+
| i < 10 = "0" <> (show i)
210+
| otherwise = show i
199211

200212
format Formatter DT.DateTime String
201213
format f dt = formatF (flip format dt) dt $ unroll f

test/src/Main.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
'use strict';
2+
3+
exports.exit = function(int) {
4+
process.exit(int);
5+
}

test/src/Main.purs

Lines changed: 125 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,42 @@
11
module Test.Main where
22

33
import Prelude
4+
import Control.Monad.Aff.Console as AffC
5+
import Data.Date as D
6+
import Data.DateTime as DTi
7+
import Data.Formatter.DateTime as FDT
8+
import Data.Formatter.Number as FN
9+
import Data.Time as T
10+
import Debug.Trace as DT
11+
import Control.Monad.Aff (Aff, Canceler, runAff)
12+
import Control.Monad.Aff.Class (liftAff)
413
import Control.Monad.Eff (Eff)
5-
import Control.Monad.Eff.Console (CONSOLE, log)
6-
14+
import Control.Monad.Eff.Console (CONSOLE)
15+
import Control.Monad.Eff.Exception (EXCEPTION, error)
16+
import Control.Monad.Error.Class (throwError)
17+
import Control.Monad.State (StateT, put, get, execStateT)
18+
import Data.DateTime (DateTime)
19+
import Data.Either (Either(..), either)
20+
import Data.Enum (toEnum)
721
import Data.Functor.Mu (roll)
8-
import Data.Formatter.Number as FN
9-
import Data.Formatter.DateTime as FDT
1022
import Data.Maybe (fromMaybe)
11-
import Data.Either (Either(..))
12-
import Data.Enum (toEnum)
1323

14-
import Data.DateTime as DTi
15-
import Data.Date as D
16-
import Data.Time as T
17-
import Debug.Trace as DT
24+
type Tests e a = StateT Boolean (Aff (exception :: EXCEPTION, console :: CONSOLE | e)) a
25+
26+
27+
execTests :: forall a e c.
28+
StateT a (Aff ( process :: PROCESS | e)) c ->
29+
a ->
30+
Eff (process :: PROCESS | e) (Canceler ( process :: PROCESS | e ))
31+
execTests fn state = runAff (\s -> exit 1) (\s -> exit 0) (execStateT fn state)
32+
33+
34+
log :: forall e. String -> Tests e Unit
35+
log message = liftAff $ AffC.log message
36+
37+
38+
foreign import data PROCESS :: !
39+
foreign import exit :: Int -> forall e. Eff (process :: PROCESS | e) Unit
1840

1941

2042
fnOne FN.Formatter
@@ -36,6 +58,7 @@ fnTwo =
3658
, sign: true
3759
}
3860

61+
3962
fnThree FN.Formatter
4063
fnThree =
4164
{ comma: false
@@ -46,9 +69,18 @@ fnThree =
4669
}
4770

4871

49-
numeral e. Eff (console CONSOLE |e) Unit
50-
numeral = do
51-
log $ "NUMERAL TESTS\n\n"
72+
fdtOne FDT.Formatter
73+
fdtOne =
74+
roll $ FDT.Placeholder "format string is "
75+
$ roll $ FDT.YearFull
76+
$ roll $ FDT.Placeholder "-"
77+
$ roll $ FDT.MonthShort
78+
$ roll FDT.End
79+
80+
81+
numeralTests :: forall e. Tests e Unit
82+
numeralTests = do
83+
log $ "\nNUMERAL TESTS\n"
5284

5385
log $ "\nPRINT FORMATTER"
5486
log $ FN.printFormatter fnOne
@@ -84,31 +116,84 @@ numeral = do
84116
log $ "\n UNFORMAT NUMBER"
85117
DT.traceAnyA $ FN.unformatNumber "0.00" "12.00"
86118

87-
fdtOne FDT.Formatter
88-
fdtOne =
89-
roll $ FDT.Placeholder "format string is "
90-
$ roll $ FDT.YearFull
91-
$ roll $ FDT.Placeholder "-"
92-
$ roll $ FDT.MonthShort
93-
$ roll FDT.End
94119

95-
testDateTime DTi.DateTime
96-
testDateTime =
120+
-- April 12th 2017 at 11:34:34:234
121+
-- 4/12/2017
122+
makeDateTime Int -> DTi.DateTime
123+
makeDateTime year =
97124
DTi.DateTime
98-
(D.canonicalDate (fromMaybe bottom $ toEnum 1234) D.April (fromMaybe bottom $ toEnum 12))
125+
(D.canonicalDate (fromMaybe bottom $ toEnum year) D.April (fromMaybe bottom $ toEnum 12))
99126
(T.Time
100127
(fromMaybe bottom $ toEnum 11)
101128
(fromMaybe bottom $ toEnum 34)
102129
(fromMaybe bottom $ toEnum 34)
103130
(fromMaybe bottom $ toEnum 234))
104131

105-
timeTest e. Eff (console CONSOLE |e) Unit
106-
timeTest = do
107-
log $ "\n\n DATETIME FORMATTER"
108-
log "\nPRINT FORMATTER"
109-
log $ FDT.printFormatter fdtOne
132+
testDateTime :: DTi.DateTime
133+
testDateTime = makeDateTime 2017
134+
135+
136+
assert :: forall e. String -> String -> Boolean -> Tests e Unit
137+
assert _ success true = log $ " ✓ - Passed - " <> success
138+
assert fail _ false = do
139+
log $ " ☠ - Failed because " <> fail
140+
put false
141+
142+
143+
failTest :: forall e. String -> Tests e Unit
144+
failTest message = do
145+
log message
146+
put false
110147

148+
149+
assertFormatting :: forall e. String -> String -> DateTime -> Tests e Unit
150+
assertFormatting target' format dateTime = do
151+
let result = FDT.formatDateTime format dateTime
152+
let target = Right target'
153+
assert
154+
((show result) <> " does not equal " <> (show target))
155+
((show result) <> " equals " <> (show target))
156+
(result == target)
157+
158+
159+
timeTest :: forall e. Tests e Unit
160+
timeTest = do
161+
log "- Data.Formatter.DateTime.formatDateTime"
162+
163+
-- var a = moment(
164+
-- 'April 12th 2017 at 11:34:34:234',
165+
-- 'MMMM Do YYYY [at] HH:mm:ss:SSS'
166+
-- );
167+
-- a.format('MMMM Do YYYY [at] HH:mm:ss:SSS')
168+
-- testDateTime = April 12th 2017 at 11:34:34:234
169+
assertFormatting "04/12/2017" "MM/DD/YYYY" testDateTime
170+
assertFormatting "April" "MMMM" testDateTime
171+
assertFormatting "2017-12-04" "YYYY-DD-MM" testDateTime
172+
assertFormatting "2017-Apr" "YYYY-MMM" testDateTime
173+
174+
-- This should probably be am (lowercase), if the desired
175+
-- functionality of the library is to mirror momentjs
176+
assertFormatting "11:34:34:234 AM" "hh:mm:ss:SSS a" testDateTime
177+
assertFormatting "17" "YY" testDateTime
178+
log " --- Format 20017 with YY"
179+
assertFormatting "17" "YY" (makeDateTime 20017)
180+
log " --- Format 0 with YY"
181+
assertFormatting "00" "YY" (makeDateTime 0)
182+
log " --- Format -1 with YY"
183+
assertFormatting "01" "YY" (makeDateTime (-1))
184+
185+
log "- Data.Formatter.DateTime.unformatDateTime "
186+
187+
let dt = FDT.unformatDateTime "YYYY-DD-MM SSS" "2017-12-04 234"
188+
either
189+
(const $ failTest "Could not parse 017-12-04 234")
190+
(assertFormatting "2017-12-04 234" "YYYY-DD-MM SSS")
191+
dt
192+
193+
formattingTests :: forall e. Tests e Unit
194+
formattingTests = do
111195
log $ "\nPARSE FORMAT STRING"
196+
112197
DT.traceAnyA $ FDT.parseFormatString "YYYY-MM-DD"
113198
DT.traceAnyA $ FDT.parseFormatString "YY-Q-dddd HH:mm Z"
114199

@@ -123,8 +208,15 @@ timeTest = do
123208
log $ "\nUNFORMATDATETIME"
124209
DT.traceAnyA $ FDT.unformatDateTime "YYYY-DD-MM SSS" "3456-09-10 333"
125210

126-
127-
main forall e. Eff (console CONSOLE | e) Unit
128-
main = do
129-
timeTest
130-
numeral
211+
main :: forall e.
212+
Eff ( process :: PROCESS, exception :: EXCEPTION, console :: CONSOLE | e)
213+
(Canceler ( process :: PROCESS, exception :: EXCEPTION, console :: CONSOLE | e))
214+
main = execTests tests true
215+
where
216+
tests = do
217+
log "Testing time functions..."
218+
timeTest
219+
passed <- get
220+
when (passed /= true) (throwError (error "Tests did not pass."))
221+
--numeralTests
222+
--formattingTests

0 commit comments

Comments
 (0)