git.iko.soy/purescript-intl
on ddae583 help sign in
11 files changed+188−535
since splitsnapshots
unifiedsplit
.gitignore−1 .travis.yml+1−1 README.md+1−2 bower.json−5 src/Data/Intl/DateTimeFormat.js+6−24 src/Data/Intl/DateTimeFormat.purs+116−167 src/Data/Intl/DateTimeFormat/Class.purs−41 src/Data/Intl/DateTimeFormat/Generic.purs+39−5 src/Data/Intl/DateTimeFormat/Types.js−3 src/Data/Intl/DateTimeFormat/Types.purs+2−216 test/Test/Main.purs+23−70
.gitignore−1
@@ -6,4 +6,3 @@ node_modules
66# Generated files
77.psci
88output
9−.purs-repl
.travis.yml+1−1
@@ -16,7 +16,7 @@ script:
1616 - bower install --production
1717 - npm run -s build
1818 - bower install
19− - npm -s test
19+ - LC_TIME="en_GB.UTF-8" npm -s test
2020after_success:
2121- >-
2222 test $TRAVIS_TAG &&
README.md+1−2
@@ -1,7 +1,6 @@
11# PureScript bindings to Intl - JavaScript Internalisation API
22
3−[![Maintainer: coot](https://img.shields.io/badge/maintainer-coot-lightgrey.svg)](http://github.com/coot)
4−[![Documentation](https://pursuit.purescript.org/packages/purescript-intl/badge)](https://pursuit.purescript.org/packages/purescript-intl)
3+[![Maintainer: coot](https://img.shields.io/badge/maintainer-coot-lightgrey.svg)](http://github.com/coot) [![documentation](https://pursuit.purescript.org/packages/purescript-intl)](https://pursuit.purescript.org/packages/purescript-intl)
54[![Build Status](https://travis-ci.org/coot/purescript-intl.svg?branch=master)](https://travis-ci.org/coot/purescript-intl)
65
76[Intl](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)
bower.json−5
@@ -6,11 +6,6 @@
66 "bower_components",
77 "output"
88 ],
9− "license": "MPL-2.0",
10− "repository": {
11− "type": "git",
12− "url": "git://github.com/coot/purescript-intl.git"
13− },
149 "dependencies": {
1510 "purescript-prelude": "^3.0.0",
1611 "purescript-console": "^3.0.0",
src/Data/Intl/DateTimeFormat.js+6−24
@@ -1,17 +1,17 @@
11"use strict";
22
3+exports["undefined"] = undefined;
4+
35exports.dateTimeFormatImpl = function(locales) {
46 return function(options) {
57 return new Intl.DateTimeFormat(locales, options);
68 };
79};
810
9−exports.createDateTimeFormatImpl = function(throwError, pure, locales, opts) {
10− try {
11− return pure(Intl.DateTimeFormat(locales, opts));
12− } catch (e) {
13− return throwError(e.message);
14− }
11+exports.createDateTimeFormatterImpl = function(locales) {
12+ return function(opts) {
13+ return Intl.DateTimeFormat(locales, opts);
14+ };
1515};
1616
1717exports.formatJSDate = function(formatter) {
@@ -19,21 +19,3 @@ exports.formatJSDate = function(formatter) {
1919 return formatter.format(date)
2020 };
2121};
22−
23−exports.formatToPartsImpl = function(formatter) {
24− return function(date) {
25− return formatter.formatToParts(date);
26− };
27−};
28−
29−exports.supportedLocalesOfImpl = function(Left, Right, locales) {
30− try {
31− return Right(Intl.DateTimeFormat.supportedLocalesOf(locales))
32− } catch (e) {
33− return Left(e.message)
34− }
35−}
36−
37−exports.resolvedOptionsImpl = function(formatter) {
38− return formatter.resolvedOptions();
39−};
src/Data/Intl/DateTimeFormat.purs+116−167
@@ -1,39 +1,48 @@
1−module Data.Intl.DateTimeFormat
1+module Data.Intl.DateTimeFormat
22 ( LocalesOption
33 , LocaleMatcher(..)
44 , TimeZone(..)
55 , FormatMatcher(..)
6+ , WeekdayYearMonthDayHourMinuteSecond(..)
7+ , WeekdayYearMonthDay(..)
8+ , YearMonthDay(..)
9+ , YearMonth(..)
10+ , MonthDay(..)
11+ , HourMinuteSecond(..)
12+ , HourMinute(..)
13+ , Undefined
14+ , undefined
615 , DateTimeFormatOptions(..)
716 , DateTimeFormatOptions'
817 , DateTimeComponents(..)
9− , DateTimeFormat
10− , createDateTimeFormat
18+ , DateTimeFormatter
19+ , createDateTimeFormatter
1120 , formatJSDate
1221 , module Data.Intl.DateTimeFormat.Types
13− , supportedLocalesOf
14− , formatToParts
15− , resolvedOptions
22+
23+ -- private
24+ , formatDateTimeOptions
25+ , DateTimeFormatOptions_
1626 ) where
1727
1828import Data.Intl.DateTimeFormat.Types
1929
20−import Control.Monad.Error.Class (throwError)
21−import Data.Either (Either(..))
22−import Data.Foreign (F, Foreign, ForeignError(..), isUndefined, readString)
23−import Data.Foreign.Index ((!))
24−import Data.Function.Uncurried (Fn3, Fn4, runFn3, runFn4)
25−import Data.Intl.DateTimeFormat.Class (class FormatComponent, FormatComponentRecord(FormatComponentRecord), formatComponent)
30+import Data.Generic.Rep (class Generic)
31+import Data.Intl.DateTimeFormat.Generic (class FormatComponent, defaultComponentRecord, formatComponent, genericFormatComponent)
2632import Data.JSDate (JSDate)
27−import Data.Maybe (Maybe(..), fromMaybe, maybe)
28−import Data.Newtype (class Newtype, un)
33+import Data.Maybe (Maybe, fromMaybe, maybe)
34+import Data.Newtype (class Newtype)
2935import Data.StrMap (union)
3036import Data.Symbol (SProxy(..))
31−import Data.Traversable (sequence)
32−import Data.Variant (Variant, case_, default, on)
33−import Prelude (class Eq, class Show, Unit, bind, id, pure, show, (#), ($), (<$>), (<<<), (>>=))
37+import Data.Variant (Variant, default, on)
38+import Prelude (class Eq, class Show, Unit, id, show, (#), ($))
3439import Unsafe.Coerce (unsafeCoerce)
3540
3641foreign import data LocalesOption' :: Type
42+foreign import data DateTimeFormat :: Type
43+
44+foreign import data Undefined :: Type
45+foreign import undefined :: Undefined
3746
3847foreign import dateTimeFormatImpl :: LocalesOption' -> DateTimeFormatOptions_ -> DateTimeFormat
3948
@@ -86,6 +95,85 @@ instance showFormatMatcher :: Show FormatMatcher where
8695 show FMBasic = "basic"
8796 show FMBestFit = "best fit"
8897
98+newtype WeekdayYearMonthDayHourMinuteSecond = WeekdayYearMonthDayHourMinuteSecond
99+ { weekday :: StringRep
100+ , year :: NumericRep
101+ , month :: MonthRep
102+ , day :: NumericRep
103+ , hour :: NumericRep
104+ , minute :: NumericRep
105+ , second :: NumericRep
106+ }
107+
108+derive instance genericWeekdayYearMonthDayHourMinuteSecond :: Generic WeekdayYearMonthDayHourMinuteSecond _
109+
110+instance formatComponentWeekdayYearMonthDayHourMinuteSecond :: FormatComponent WeekdayYearMonthDayHourMinuteSecond where
111+ formatComponent = genericFormatComponent
112+
113+newtype WeekdayYearMonthDay = WeekdayYearMonthDay
114+ { weekday :: StringRep
115+ , year :: NumericRep
116+ , month :: MonthRep
117+ , day :: NumericRep
118+ }
119+
120+derive instance genericWeekdayYearMonthDay :: Generic WeekdayYearMonthDay _
121+
122+instance formatComponentWeekdayYearMonthDay :: FormatComponent WeekdayYearMonthDay where
123+ formatComponent = genericFormatComponent
124+
125+newtype YearMonthDay = YearMonthDay
126+ { year :: NumericRep
127+ , month :: MonthRep
128+ , day :: NumericRep
129+ }
130+
131+derive instance genericYearMonthDay :: Generic YearMonthDay _
132+
133+instance formatComponentYearMonthDay :: FormatComponent YearMonthDay where
134+ formatComponent = genericFormatComponent
135+
136+newtype YearMonth = YearMonth
137+ { year :: NumericRep
138+ , month :: MonthRep
139+ }
140+
141+derive instance genericYearMonth :: Generic YearMonth _
142+
143+instance formatComponentYearMonth :: FormatComponent YearMonth where
144+ formatComponent = genericFormatComponent
145+
146+newtype MonthDay = MonthDay
147+ { month :: MonthRep
148+ , day :: NumericRep
149+ }
150+
151+derive instance genericMonthDay :: Generic MonthDay _
152+
153+instance formatComponentMonthDay :: FormatComponent MonthDay where
154+ formatComponent = genericFormatComponent
155+
156+newtype HourMinuteSecond = HourMinuteSecond
157+ { hour :: NumericRep
158+ , minute :: NumericRep
159+ , second :: NumericRep
160+ }
161+
162+derive instance genericHourMinuteSecond :: Generic HourMinuteSecond _
163+
164+instance formatComponentHourMinuteSecond :: FormatComponent HourMinuteSecond where
165+ formatComponent = genericFormatComponent
166+
167+newtype HourMinute = HourMinute
168+ { hour :: NumericRep
169+ , minute :: NumericRep
170+ }
171+
172+derive instance genericHourMinute :: Generic HourMinute _
173+
174+instance formatComponentHourMinute :: FormatComponent HourMinute where
175+ formatComponent = genericFormatComponent
176+
89177type DateTimeComponents a =
90178 Variant
91179 ( weekdayYearMonthDayHourMinuteSecond :: WeekdayYearMonthDayHourMinuteSecond
@@ -120,7 +208,7 @@ formatDateTimeOptions (DateTimeFormatOptions opts comps) = merge opts' (compsCoe
120208 , hour12: fromMaybe (unsafeCoerce undefined) opts.hour12
121209 , formatMatcher: maybe undefinedString show opts.formatMatcher
122210 }
123− comps' = un FormatComponentRecord $ case_
211+ comps' = default (defaultComponentRecord)
124212 # on (SProxy :: SProxy "weekdayYearMonthDayHourMinuteSecond") formatComponent
125213 # on (SProxy :: SProxy "weekdayYearMonthDay") formatComponent
126214 # on (SProxy :: SProxy "yearMonthDay") formatComponent
@@ -186,158 +274,19 @@ formatDateTimeOptions (DateTimeFormatOptions opts comps) = merge opts' (compsCoe
186274 -> DateTimeFormatOptions_
187275 merge a b = unsafeCoerce $ union (unsafeCoerce a) (unsafeCoerce b)
188276
189−foreign import data DateTimeFormat :: Type
277+foreign import data DateTimeFormatter :: Type
278+
279+foreign import createDateTimeFormatterImpl
280+ :: LocalesOption'
281+ -> DateTimeFormatOptions_
282+ -> DateTimeFormatter
190283
191−foreign import createDateTimeFormatImpl
192− :: Fn4
193− (forall a. String -> F a)
194− (forall a. a -> F a)
195− LocalesOption'
196− DateTimeFormatOptions_
197− (F DateTimeFormat)
198−
199−-- | Examples
200−-- | ``` purescript
201−-- | import Data.Variant (inj)
202−-- |
203−-- | fmtHourMinute = F DateTimeFormat
204−-- | fmtHourMinute = createDateTimeFormat locale opts
205−-- | where
206−-- | locale = inj (SProxy :: SProxy "locale") "en-GB"
207−-- | opts = (DateTimeFormatOptions
208−-- | { localeMatcher: Nothing
209−-- | , timeZone: (Just (TimeZone "Europe/London"))
210−-- | , hour12: Just false
211−-- | , formatMatcher: Nothing
212−-- | }
213−-- | (inj (SProxy :: SProxy "hourMinute")
214−-- | (HourMinute {hour: TwoDigit, minute: TwoDigit}))
215−-- |
216−-- |
217−-- | fmtDate :: F DateTimeFormat
218−-- | fmtDate = createDateTimeFormat locale opts
219−-- | wher
220−-- | locale = inj (SProxy :: SProxy "locale") "en-GB"
221−-- | opts :: DateTimeFormatOptions'
222−-- | opts =
223−-- | (DateTimeFormatOptions
224−-- | { localeMatcher: Nothing
225−-- | , timeZone: (Just (TimeZone "Europe/London"))
226−-- | , hour12: Just true
227−-- | , formatMatcher: Nothing
228−-- | }
229−-- | (inj
230−-- | (SProxy :: SProxy "weekdayYearMonthDayHourMinuteSecond")
231−-- | (WeekdayYearMonthDayHourMinuteSecond
232−-- | { weekday: Short
233−-- | , year: Numeric
234−-- | , month: MonthLong
235−-- | , day: Numeric
236−-- | , hour: Numeric
237−-- | , minute: Numeric
238−-- | , second: Numeric
239−-- | }
240−-- | )
241−-- | )
242−-- | )
243−-- | ```
244−-- | You have predifined types: `WeekdayYearMonthDayHourMinuteSecond`,
245−-- | `WeekdayYearMonthDay`, `YearMonthDay`, `YearMonth`, `MonthDay`,
246−-- | `HourMinuteSecond`, `HourMinute`. But you can also provide your own by
247−-- | implementing `FormatComponent` class (or by deriving it), e.g.
248−-- | ``` purescript
249−-- | newtype EraYear = EraYear
250−-- | { era :: StringRep
251−-- | , year :: NumericRep
252−-- | }
253−-- |
254−-- | derive instance genericEraYear :: Generic EraYear _
255−-- |
256−-- | instance formatComponentEraYear :: FormatComponent EraYear where
257−-- | formatComponent = genericFormatComponent
258−-- |
259−-- | fmtEraYear :: F DateTimeFormat
260−-- | fmtEraYear = createDateTimeFormat locales opts
261−-- | where
262−-- | locale = inj (SProxy :: SProxy "locale") "en-GB"
263−-- | opts :: DateTimeFormatOptions EraYear
264−-- | opts =
265−-- | (DateTimeFormatOptions
266−-- | { localeMatcher: Nothing
267−-- | , timeZone: (Just (TimeZone "Europe/London"))
268−-- | , hour12: Just true
269−-- | , formatMatcher: Nothing
270−-- | }
271−-- | (inj
272−-- | (SProxy :: SProxy "custom")
273−-- | (EraYear
274−-- | { era: Long
275−-- | , year: Numeric
276−-- | }
277−-- | )
278−-- | )
279−-- | )
280−-- | ```
281−createDateTimeFormat
284+createDateTimeFormatter
282285 :: forall a
283286 .(FormatComponent a)
284287 => LocalesOption
285288 -> DateTimeFormatOptions a
286− -> F DateTimeFormat
287−createDateTimeFormat ls opts =
288− runFn4 createDateTimeFormatImpl
289− (throwError <<< pure <<< ForeignError)
290− pure
291− (toLocale ls)
292− (formatDateTimeOptions opts)
293−
294−-- | Examples
295−-- | ``` purescript
296−-- | formatJSDate (either (const "") id $ runExcept fmtHourMinute) date -- "12:00"
297−-- | formatJSDate (either (const "") id $ fmtDate) date -- "Tue, January 2, 2018, 12:00:00 PM"
298−-- | formatJSDate (either (const "") id $ fmtEraYear) date -- "2018 Anno Domini"
299−-- | ```
300−foreign import formatJSDate :: DateTimeFormat -> JSDate -> String
301−
302−foreign import supportedLocalesOfImpl
303− :: Fn3
304− (String -> Either String (Array String))
305− (Array String -> Either String (Array String))
306− (Array String)
307− (Either String (Array String))
308−
309−foreign import formatToPartsImpl :: DateTimeFormat -> JSDate -> Array Foreign
310−
311−formatToParts :: DateTimeFormat -> JSDate -> F (Array FormatParts)
312−formatToParts formatter date = sequence $ readFormatParts <$> formatToPartsImpl formatter date
313−
314−supportedLocalesOf :: Array String -> Either String (Array String)
315−supportedLocalesOf locales = runFn3 supportedLocalesOfImpl Left Right locales
316−
317−foreign import resolvedOptionsImpl :: DateTimeFormat -> Foreign
318−
319−resolvedOptions :: DateTimeFormat -> F ResolvedOptions
320−resolvedOptions fmt = do
321− locale <- obj ! "locale" >>= readString
322− calendar <- obj ! "calendar" >>= readString
323− numberingSystem <- obj ! "numberingSystem" >>= readString
324− timeZone <- obj ! "timeZone" >>= readString
325− era <- obj ! "era" >>= readMaybeString
326− weekday <- obj ! "weekday" >>= readMaybeString
327− year <- obj ! "year" >>= readMaybeString
328− day <- obj ! "day" >>= readMaybeString
329− hour <- obj ! "hour" >>= readMaybeString
330− minute <- obj ! "minute" >>= readMaybeString
331− second <- obj ! "second" >>= readMaybeString
332− timeZoneName <- obj ! "timeZoneName" >>= readMaybeString
333−
334− pure $ ResolvedOptions { locale, calendar, numberingSystem, timeZone, era, weekday, year, day, hour, minute, second, timeZoneName }
335−
336− where
337− obj = resolvedOptionsImpl fmt
289+ -> DateTimeFormatter
290+createDateTimeFormatter ls opts = createDateTimeFormatterImpl (toLocale ls) (formatDateTimeOptions opts)
338291
339− readMaybeString :: Foreign -> F (Maybe String)
340− readMaybeString f =
341− if isUndefined f
342− then pure Nothing
343− else Just <$> readString f
292+foreign import formatJSDate :: DateTimeFormatter -> JSDate -> String
src/Data/Intl/DateTimeFormat/Class.pursdeleted−41
@@ -1,41 +0,0 @@
1−module Data.Intl.DateTimeFormat.Class where
2−
3−import Data.Maybe (Maybe(..))
4−import Data.Newtype (class Newtype)
5−import Prelude (class Eq, Unit)
6−
7−newtype FormatComponentRecord = FormatComponentRecord
8− { era :: Maybe String
9− , weekday :: Maybe String
10− , year :: Maybe String
11− , month :: Maybe String
12− , day :: Maybe String
13− , hour :: Maybe String
14− , minute :: Maybe String
15− , second :: Maybe String
16− , timeZoneName :: Maybe String
17− }
18−
19−derive instance newtypeFormatComponentRecord :: Newtype FormatComponentRecord _
20−
21−derive instance eqFormatComponentRecord :: Eq FormatComponentRecord
22−
23−defaultComponentRecord :: FormatComponentRecord
24−defaultComponentRecord = FormatComponentRecord
25− { era: Nothing
26− , weekday: Nothing
27− , year: Nothing
28− , month: Nothing
29− , day: Nothing
30− , hour: Nothing
31− , minute: Nothing
32− , second: Nothing
33− , timeZoneName: Nothing
34− }
35−
36−
37−class FormatComponent a where
38− formatComponent :: a -> FormatComponentRecord
39−
40−instance unitFormatComponent :: FormatComponent Unit where
41− formatComponent _ = defaultComponentRecord
src/Data/Intl/DateTimeFormat/Generic.purs+39−5
@@ -1,17 +1,51 @@
11module Data.Intl.DateTimeFormat.Generic
2− ( class GenericFormatComponent
2+ ( class FormatComponent
3+ , formatComponent
4+ , class GenericFormatComponent
35 , genericFormatComponent'
46 , genericFormatComponent
57 , class GenericFormatComponentFields
68 , genericFormatComponentFields
9+ , defaultComponentRecord
10+ , FormatComponentRecord
711 ) where
812
913import Data.Generic.Rep (class Generic, Constructor(Constructor), Field(..), NoConstructors, Product(..), Rec(..), from)
10−import Data.Intl.DateTimeFormat.Class (FormatComponentRecord(..))
1114import Data.Intl.DateTimeFormat.Types (MonthRep, NumericRep, TimeZoneNameRep, StringRep)
1215import Data.Maybe (Maybe(..))
1316import Data.StrMap (StrMap, lookup, singleton, union)
14−import Prelude (show)
17+import Prelude (Unit, show)
18+
19+type FormatComponentRecord =
20+ { era :: Maybe String
21+ , weekday :: Maybe String
22+ , year :: Maybe String
23+ , month :: Maybe String
24+ , day :: Maybe String
25+ , hour :: Maybe String
26+ , minute :: Maybe String
27+ , second :: Maybe String
28+ , timeZoneName :: Maybe String
29+ }
30+
31+defaultComponentRecord :: FormatComponentRecord
32+defaultComponentRecord =
33+ { era: Nothing
34+ , weekday: Nothing
35+ , year: Nothing
36+ , month: Nothing
37+ , day: Nothing
38+ , hour: Nothing
39+ , minute: Nothing
40+ , second: Nothing
41+ , timeZoneName: Nothing
42+ }
43+
44+class FormatComponent a where
45+ formatComponent :: a -> FormatComponentRecord
46+
47+instance unitFormatComponent :: FormatComponent Unit where
48+ formatComponent _ = defaultComponentRecord
1549
1650class GenericFormatComponent a where
1751 genericFormatComponent' :: a -> FormatComponentRecord
@@ -20,7 +54,7 @@ class GenericFormatComponentFields a where
2054 genericFormatComponentFields :: a -> StrMap String
2155
2256instance genericFormatComponentNoConsturctors :: GenericFormatComponent NoConstructors where
23− genericFormatComponent' a = FormatComponentRecord
57+ genericFormatComponent' a =
2458 { era: Nothing
2559 , weekday: Nothing
2660 , year: Nothing
@@ -80,7 +114,7 @@ instance genericFormatComponentFieldsProduct
80114instance genericFormatComponentRec
81115 :: (GenericFormatComponentFields a)
82116 => GenericFormatComponent (Rec a) where
83− genericFormatComponent' (Rec a) = FormatComponentRecord
117+ genericFormatComponent' (Rec a) =
84118 { era: "era" `lookup` u
85119 , weekday: "weekday" `lookup` u
86120 , year: "year" `lookup` u
src/Data/Intl/DateTimeFormat/Types.jsdeleted−3
@@ -1,3 +0,0 @@
1−"use strict";
2−
3−exports["undefined"] = undefined;
src/Data/Intl/DateTimeFormat/Types.purs+2−216
@@ -1,37 +1,9 @@
1−module Data.Intl.DateTimeFormat.Types
2− ( StringRep(..)
3− , NumericRep(..)
4− , MonthRep(..)
5− , TimeZoneNameRep(..)
6− , FormatParts(..)
7− , readFormatParts
8− , ResolvedOptions(..)
9− , WeekdayYearMonthDayHourMinuteSecond(..)
10− , WeekdayYearMonthDay(..)
11− , YearMonthDay(..)
12− , YearMonth(..)
13− , MonthDay(..)
14− , HourMinuteSecond(..)
15− , HourMinute(..)
16− , Undefined
17− , undefined
18− ) where
1+module Data.Intl.DateTimeFormat.Types where
192
20−import Data.Foreign (F, Foreign, ForeignError(..), fail, readString)
21−import Data.Foreign.Index ((!))
22−import Data.Intl.DateTimeFormat.Class (class FormatComponent, FormatComponentRecord(..), defaultComponentRecord)
23−import Data.Maybe (Maybe(..))
24−import Data.Newtype (class Newtype, over)
25−import Prelude (class Eq, class Show, bind, pure, show, ($), (<>), (>>=))
26−
27−foreign import data Undefined :: Type
28−
29−foreign import undefined :: Undefined
3+import Prelude (class Show)
304
315data StringRep = Narrow | Short | Long
326
33−derive instance eqStringRep :: Eq StringRep
34−
357instance showStringRep :: Show StringRep where
368 show Narrow = "narrow"
379 show Short = "short"
@@ -39,16 +11,12 @@ instance showStringRep :: Show StringRep where
3911
4012data NumericRep = Numeric | TwoDigit
4113
42−derive instance eqNumericRep :: Eq NumericRep
43−
4414instance showNumericRep :: Show NumericRep where
4515 show Numeric = "numeric"
4616 show TwoDigit = "2-digit"
4717
4818data MonthRep = MonthNumeric | MonthTwoDigit | MonthNarrow | MonthShort | MonthLong
4919
50−derive instance eqMonthRep :: Eq MonthRep
51−
5220instance showMonthRep :: Show MonthRep where
5321 show MonthNumeric = "numeric"
5422 show MonthTwoDigit = "2-digit"
@@ -58,189 +26,7 @@ instance showMonthRep :: Show MonthRep where
5826
5927data TimeZoneNameRep = TimeZoneNameShort | TimeZoneNameLong
6028
61−derive instance eqTimeZoneNameRep :: Eq TimeZoneNameRep
62−
6329instance showTimeZoneRep :: Show TimeZoneNameRep where
6430 show TimeZoneNameShort = "short"
6531 show TimeZoneNameLong = "long"
6632
67−data FormatParts
68− = Era String
69− | Year String
70− | Month String
71− | Weekday String
72− | Day String
73− | Hour String
74− | Minute String
75− | DayPeriod String
76− | Literal String
77−
78−derive instance eqFormatParts :: Eq FormatParts
79−
80−readFormatParts :: Foreign -> F FormatParts
81−readFormatParts val = do
82− type_ <- val ! "type" >>= readString
83− value <- val ! "value" >>= readString
84− case type_ of
85− "era" -> pure $ Era value
86− "year" -> pure $ Year value
87− "month" -> pure $ Month value
88− "weekday" -> pure $ Weekday value
89− "month" -> pure $ Month value
90− "day" -> pure $ Day value
91− "hour" -> pure $ Hour value
92− "minute" -> pure $ Minute value
93− "dayperiod" -> pure $ DayPeriod value
94− "literal" -> pure $ Literal value
95− _ -> fail $ ForeignError ("type " <> type_ <> " is not supported by purescript-intl")
96−
97−newtype ResolvedOptions = ResolvedOptions
98− { locale :: String
99− , numberingSystem :: String
100− , calendar :: String
101− , timeZone :: String
102− , era :: Maybe String
103− , weekday :: Maybe String
104− , year :: Maybe String
105− , day :: Maybe String
106− , hour :: Maybe String
107− , minute :: Maybe String
108− , second :: Maybe String
109− , timeZoneName :: Maybe String
110− }
111−
112−derive instance newtypeResolvedOptions :: Newtype ResolvedOptions _
113−
114−derive instance eqResolvedOptions :: Eq ResolvedOptions
115−
116−newtype WeekdayYearMonthDayHourMinuteSecond = WeekdayYearMonthDayHourMinuteSecond
117− { weekday :: StringRep
118− , year :: NumericRep
119− , month :: MonthRep
120− , day :: NumericRep
121− , hour :: NumericRep
122− , minute :: NumericRep
123− , second :: NumericRep
124− }
125−
126−derive instance newtypeWeekdayYearMonthDayHourMinuteSecond :: Newtype WeekdayYearMonthDayHourMinuteSecond _
127−
128−derive instance eqWeekdayYearMonthDayHourMinuteSecond :: Eq WeekdayYearMonthDayHourMinuteSecond
129−
130−instance formatComponentWeekdayYearMonthDayHourMinuteSecond :: FormatComponent WeekdayYearMonthDayHourMinuteSecond where
131− formatComponent (WeekdayYearMonthDayHourMinuteSecond { weekday, year, month, day, hour, minute, second }) = over FormatComponentRecord
132− (\r -> r { weekday = Just (show weekday)
133− , year = Just (show year)
134− , month = Just (show month)
135− , day = Just (show day)
136− , hour = Just (show hour)
137− , minute = Just (show minute)
138− , second = Just (show second)
139− }
140− ) defaultComponentRecord
141−
142−newtype WeekdayYearMonthDay = WeekdayYearMonthDay
143− { weekday :: StringRep
144− , year :: NumericRep
145− , month :: MonthRep
146− , day :: NumericRep
147− }
148−
149−derive instance newtypeWeekdayYearMonthDay :: Newtype WeekdayYearMonthDay _
150−
151−derive instance eqWeekdayYearMonthDay :: Eq WeekdayYearMonthDay
152−
153−instance formatComponentWeekdayYearMonthDay :: FormatComponent WeekdayYearMonthDay where
154− formatComponent (WeekdayYearMonthDay { weekday, year, month, day }) = over FormatComponentRecord
155− (\r -> r { weekday = Just (show weekday)
156− , year = Just (show year)
157− , month = Just (show month)
158− , day = Just (show day)
159− }
160− ) defaultComponentRecord
161−
162−
163−newtype YearMonthDay = YearMonthDay
164− { year :: NumericRep
165− , month :: MonthRep
166− , day :: NumericRep
167− }
168−
169−derive instance newtypeYearMonthDay :: Newtype YearMonthDay _
170−
171−derive instance eqYearMonthDay :: Eq YearMonthDay
172−
173−instance formatComponentYearMonthDay :: FormatComponent YearMonthDay where
174− formatComponent (YearMonthDay { year, month, day }) = over FormatComponentRecord
175− (\r -> r { year = Just (show year)
176− , month = Just (show month)
177− , day = Just (show day)
178− }
179− ) defaultComponentRecord
180−
181−
182−newtype YearMonth = YearMonth
183− { year :: NumericRep
184− , month :: MonthRep
185− }
186−
187−derive instance newtypeYearMonth :: Newtype YearMonth _
188−
189−derive instance eqYearMonth :: Eq YearMonth
190−
191−instance formatComponentYearMonth :: FormatComponent YearMonth where
192− formatComponent (YearMonth { year, month }) = over FormatComponentRecord
193− (\r -> r { year = Just (show year)
194− , month = Just (show month)
195− }
196− ) defaultComponentRecord
197−
198−newtype MonthDay = MonthDay
199− { month :: MonthRep
200− , day :: NumericRep
201− }
202−
203−derive instance newtypeMonthDay :: Newtype MonthDay _
204−
205−derive instance eqMonthDay :: Eq MonthDay
206−
207−instance formatComponentMonthDay :: FormatComponent MonthDay where
208− formatComponent (MonthDay { month, day }) = over FormatComponentRecord
209− (\r -> r { month = Just (show month)
210− , day = Just (show day)
211− }
212− ) defaultComponentRecord
213−
214−newtype HourMinuteSecond = HourMinuteSecond
215− { hour :: NumericRep
216− , minute :: NumericRep
217− , second :: NumericRep
218− }
219−
220−derive instance newtypeHourMinuteSecond :: Newtype HourMinuteSecond _
221−
222−derive instance eqHourMinuteSecond :: Eq HourMinuteSecond
223−
224−instance formatComponentHourMinuteSecond :: FormatComponent HourMinuteSecond where
225− formatComponent (HourMinuteSecond { hour, minute, second }) = over FormatComponentRecord
226− (\r -> r { hour = Just (show hour)
227− , minute = Just (show minute)
228− , second = Just (show second)
229− }
230− ) defaultComponentRecord
231−
232−newtype HourMinute = HourMinute
233− { hour :: NumericRep
234− , minute :: NumericRep
235− }
236−
237−derive instance newtypeHourMinute :: Newtype HourMinute _
238−
239−derive instance eqHourMinute :: Eq HourMinute
240−
241−instance formatComponentHourMinute :: FormatComponent HourMinute where
242− formatComponent (HourMinute { hour, minute }) = over FormatComponentRecord
243− (\r -> r { hour = Just (show hour)
244− , minute = Just (show minute)
245− }
246− ) defaultComponentRecord
test/Test/Main.purs+23−70
@@ -4,22 +4,17 @@ import Prelude
44
55import Control.Monad.Eff (Eff)
66import Control.Monad.Eff.Console (CONSOLE)
7−import Control.Monad.Except (runExcept)
87import Data.DateTime (Date, DateTime(..), Month(..), canonicalDate)
9−import Data.Either (Either(..), fromRight, isLeft)
108import Data.Enum (toEnum)
11−import Data.Foldable (intercalate)
12−import Data.Foreign (F, renderForeignError)
139import Data.Generic.Rep (class Generic)
14−import Data.Intl.DateTimeFormat (DateTimeFormatOptions(DateTimeFormatOptions), DateTimeFormatOptions', HourMinute(HourMinute), HourMinuteSecond(HourMinuteSecond), LocalesOption, MonthDay(MonthDay), MonthRep(MonthTwoDigit, MonthNumeric, MonthNarrow, MonthShort, MonthLong), NumericRep(Numeric, TwoDigit), ResolvedOptions(..), StringRep(Short, Long), TimeZone(TimeZone), WeekdayYearMonthDay(WeekdayYearMonthDay), WeekdayYearMonthDayHourMinuteSecond(WeekdayYearMonthDayHourMinuteSecond), YearMonth(YearMonth), YearMonthDay(YearMonthDay), createDateTimeFormat, formatJSDate, resolvedOptions, supportedLocalesOf)
15−import Data.Intl.DateTimeFormat.Class (class FormatComponent, FormatComponentRecord(..))
16−import Data.Intl.DateTimeFormat.Generic (genericFormatComponent)
10+import Data.Intl.DateTimeFormat (DateTimeFormatOptions(..), DateTimeFormatOptions', HourMinute(HourMinute), HourMinuteSecond(HourMinuteSecond), LocalesOption, MonthDay(..), MonthRep(..), NumericRep(Numeric, TwoDigit), StringRep(..), TimeZone(TimeZone), WeekdayYearMonthDay(..), WeekdayYearMonthDayHourMinuteSecond(WeekdayYearMonthDayHourMinuteSecond), YearMonth(..), YearMonthDay(..), createDateTimeFormatter, formatJSDate)
11+import Data.Intl.DateTimeFormat.Generic (class FormatComponent, genericFormatComponent)
1712import Data.JSDate (JSDate, fromDateTime)
18−import Data.Maybe (Maybe(..), isJust, isNothing)
13+import Data.Maybe (Maybe(..))
1914import Data.Symbol (SProxy(..))
2015import Data.Time (Time(..))
2116import Data.Variant (inj)
22−import Partial.Unsafe (unsafeCrashWith, unsafePartial)
17+import Partial.Unsafe (unsafeCrashWith)
2318import Test.Assert (ASSERT, assert')
2419
2520type Tests = Eff (console :: CONSOLE, assert :: ASSERT) Unit
@@ -37,7 +32,7 @@ instance formatComponentEraYear :: FormatComponent EraYear where
3732newtype Era = Era StringRep
3833
3934instance formatComponentEra :: FormatComponent Era where
40− formatComponent (Era r) = FormatComponentRecord
35+ formatComponent (Era r) =
4136 { era: Just (show r)
4237 , weekday: Nothing
4338 , year: Nothing
@@ -53,28 +48,11 @@ main :: Tests
5348main = do
5449 let
5550
56− unsafeFromF :: forall a. F a -> a
57− unsafeFromF = unsafePartial fromRight <<< runExcept
58−
5951 locales :: LocalesOption
6052 locales = inj (SProxy :: SProxy "locale") "en-US"
6153
62− fmtError =
63− createDateTimeFormat (inj (SProxy :: SProxy "locale") "") opts
64− where
65− opts :: DateTimeFormatOptions'
66− opts =
67− (DateTimeFormatOptions
68− { localeMatcher: Nothing
69− , timeZone: (Just (TimeZone "Europe/London"))
70− , hour12: Just false
71− , formatMatcher: Nothing
72− }
73− (inj (SProxy :: SProxy "hourMinute") (HourMinute {hour: TwoDigit, minute: TwoDigit}))
74− )
75−
76− fmtHourMinute = unsafeFromF $
77− createDateTimeFormat locales opts
54+ fmtHourMinute =
55+ createDateTimeFormatter locales opts
7856 where
7957 opts :: DateTimeFormatOptions'
8058 opts =
@@ -87,8 +65,8 @@ main = do
8765 (inj (SProxy :: SProxy "hourMinute") (HourMinute {hour: TwoDigit, minute: TwoDigit}))
8866 )
8967
90− fmtHourMinuteSecond = unsafeFromF $
91− createDateTimeFormat locales opts
68+ fmtHourMinuteSecond =
69+ createDateTimeFormatter locales opts
9270 where
9371 opts :: DateTimeFormatOptions'
9472 opts =
@@ -101,8 +79,8 @@ main = do
10179 (inj (SProxy :: SProxy "hourMinuteSecond") (HourMinuteSecond {hour: Numeric, minute: Numeric, second: Numeric}))
10280 )
10381
104− fmtWeekdayYearMonthDayHourMinuteSecond = unsafeFromF $
105− createDateTimeFormat locales opts
82+ fmtWeekdayYearMonthDayHourMinuteSecond =
83+ createDateTimeFormatter locales opts
10684 where
10785 opts :: DateTimeFormatOptions'
10886 opts =
@@ -127,8 +105,8 @@ main = do
127105 )
128106 )
129107
130− fmtWeekdayYearMonthDay = unsafeFromF $
131− createDateTimeFormat locales opts
108+ fmtWeekdayYearMonthDay =
109+ createDateTimeFormatter locales opts
132110 where
133111 opts :: DateTimeFormatOptions'
134112 opts =
@@ -150,8 +128,8 @@ main = do
150128 )
151129 )
152130
153− fmtYearMonthDay = unsafeFromF $
154− createDateTimeFormat locales opts
131+ fmtYearMonthDay =
132+ createDateTimeFormatter locales opts
155133 where
156134 opts :: DateTimeFormatOptions'
157135 opts =
@@ -172,8 +150,8 @@ main = do
172150 )
173151 )
174152
175− fmtYearMonth = unsafeFromF $
176− createDateTimeFormat locales opts
153+ fmtYearMonth =
154+ createDateTimeFormatter locales opts
177155 where
178156 opts :: DateTimeFormatOptions'
179157 opts =
@@ -193,8 +171,8 @@ main = do
193171 )
194172 )
195173
196− fmtMonthDay = unsafeFromF $
197− createDateTimeFormat locales opts
174+ fmtMonthDay =
175+ createDateTimeFormatter locales opts
198176 where
199177 opts :: DateTimeFormatOptions'
200178 opts =
@@ -214,8 +192,8 @@ main = do
214192 )
215193 )
216194
217− fmtEraYear = unsafeFromF $
218− createDateTimeFormat locales opts
195+ fmtEraYear =
196+ createDateTimeFormatter locales opts
219197 where
220198 opts :: DateTimeFormatOptions EraYear
221199 opts =
@@ -235,8 +213,8 @@ main = do
235213 )
236214 )
237215
238− fmtEra = unsafeFromF $
239− createDateTimeFormat locales opts
216+ fmtEra =
217+ createDateTimeFormatter locales opts
240218 where
241219 opts :: DateTimeFormatOptions Era
242220 opts =
@@ -280,9 +258,6 @@ main = do
280258 case jsDate of
281259 Nothing -> unsafeCrashWith "jsDate not parsed"
282260 Just d -> do
283−
284− assert' "fmtError expected to return error" $ isLeft (runExcept fmtError)
285−
286261 let fmtDate1 = formatJSDate fmtWeekdayYearMonthDayHourMinuteSecond d
287262 fmtDate1Expected = "Tue, January 2, 2018, 12:00:00 PM"
288263 assert' ("fmtWeekdayYearMonthDayHourMinuteSecond: got: '" <> fmtDate1 <> "' expected: '" <> fmtDate1Expected <> "'")
@@ -319,25 +294,3 @@ main = do
319294 fmtDate9Expected = "1 2, 2018 AD"
320295 assert' ("fmtEra: got '" <> fmtDate9 <> "' expected: '" <> fmtDate9Expected <> "'")
321296 $ fmtDate9 == fmtDate9Expected
322−
323− let slocs = supportedLocalesOf ["en-US", "jp-JP"]
324− assert' ("supportedLocalesOf: got: " <> show slocs) $ slocs == Right ["en-US"]
325−
326− let err = supportedLocalesOf ["en_US"]
327− assert' ("supportedLocalesOf got: " <> show err) $ isLeft err
328−
329− -- formatToParts is not supported in node
330− -- let parts = runExcept $ formatToParts fmtHourMinute d
331− -- assert' ("") $ isRight parts
332−
333− case runExcept (resolvedOptions fmtHourMinuteSecond) of
334− Left errs-> assert' ("resolvedOptions error: " <> (intercalate "; " $ renderForeignError <$> errs)) false
335− Right (ResolvedOptions {locale, year, day, weekday, hour, minute, second}) -> do
336− assert' ("resolvedOptions locale: got: " <> locale) $ (locale == "en-US") || (locale == "en")
337− assert' ("resolvedOptions year: got Just") $ isNothing year
338− assert' ("resolvedOptions day: got Just") $ isNothing day
339− assert' ("resolvedOptions weekday: got Just") $ isNothing weekday
340− assert' ("resolvedOptions hour: got Nothing") $ isJust hour
341− assert' ("resolvedOptions minute: got Nothing") $ isJust minute
342− assert' ("resolvedOptions second: got Nothing") $ isJust second
343−