git.iko.soy/purescript-intl
on ddae583 help sign in
.gitignore−1
since splitsnapshots
unifiedsplit
@@ -6,4 +6,3 @@ node_modules
6# Generated files
6# Generated files
7.psci
7.psci
8output
8output
9−.purs-repl
.travis.yml+1−1
@@ -16,7 +16,7 @@ script:
16 - bower install --production
16 - bower install --production
17 - npm run -s build
17 - npm run -s build
18 - bower install
18 - bower install
19− - npm -s test
19+ - LC_TIME="en_GB.UTF-8" npm -s test
20after_success:
20after_success:
21- >-
21- >-
22 test $TRAVIS_TAG &&
22 test $TRAVIS_TAG &&
README.md+1−2
@@ -1,7 +1,6 @@
1# PureScript bindings to Intl - JavaScript Internalisation API
1# PureScript bindings to Intl - JavaScript Internalisation API
2
2
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)
5[![Build Status](https://travis-ci.org/coot/purescript-intl.svg?branch=master)](https://travis-ci.org/coot/purescript-intl)
4[![Build Status](https://travis-ci.org/coot/purescript-intl.svg?branch=master)](https://travis-ci.org/coot/purescript-intl)
6
5
7[Intl](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)
6[Intl](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl)
bower.json−5
@@ -6,11 +6,6 @@
6 "bower_components",
6 "bower_components",
7 "output"
7 "output"
8 ],
8 ],
9− "license": "MPL-2.0",
10− "repository": {
11− "type": "git",
12− "url": "git://github.com/coot/purescript-intl.git"
13− },
14 "dependencies": {
9 "dependencies": {
15 "purescript-prelude": "^3.0.0",
10 "purescript-prelude": "^3.0.0",
16 "purescript-console": "^3.0.0",
11 "purescript-console": "^3.0.0",
src/Data/Intl/DateTimeFormat.js+6−24
@@ -1,17 +1,17 @@
1"use strict";
1"use strict";
2
2
3+exports["undefined"] = undefined;
4+
3exports.dateTimeFormatImpl = function(locales) {
5exports.dateTimeFormatImpl = function(locales) {
4 return function(options) {
6 return function(options) {
5 return new Intl.DateTimeFormat(locales, options);
7 return new Intl.DateTimeFormat(locales, options);
6 };
8 };
7};
9};
8
10
9−exports.createDateTimeFormatImpl = function(throwError, pure, locales, opts) {
11+exports.createDateTimeFormatterImpl = function(locales) {
10− try {
12+ return function(opts) {
11− return pure(Intl.DateTimeFormat(locales, opts));
13+ return Intl.DateTimeFormat(locales, opts);
12− } catch (e) {
14+ };
13− return throwError(e.message);
14− }
15};
15};
16
16
17exports.formatJSDate = function(formatter) {
17exports.formatJSDate = function(formatter) {
@@ -19,21 +19,3 @@ exports.formatJSDate = function(formatter) {
19 return formatter.format(date)
19 return formatter.format(date)
20 };
20 };
21};
21};
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
2 ( LocalesOption
2 ( LocalesOption
3 , LocaleMatcher(..)
3 , LocaleMatcher(..)
4 , TimeZone(..)
4 , TimeZone(..)
5 , FormatMatcher(..)
5 , FormatMatcher(..)
6+ , WeekdayYearMonthDayHourMinuteSecond(..)
7+ , WeekdayYearMonthDay(..)
8+ , YearMonthDay(..)
9+ , YearMonth(..)
10+ , MonthDay(..)
11+ , HourMinuteSecond(..)
12+ , HourMinute(..)
13+ , Undefined
14+ , undefined
6 , DateTimeFormatOptions(..)
15 , DateTimeFormatOptions(..)
7 , DateTimeFormatOptions'
16 , DateTimeFormatOptions'
8 , DateTimeComponents(..)
17 , DateTimeComponents(..)
9− , DateTimeFormat
18+ , DateTimeFormatter
10− , createDateTimeFormat
19+ , createDateTimeFormatter
11 , formatJSDate
20 , formatJSDate
12 , module Data.Intl.DateTimeFormat.Types
21 , module Data.Intl.DateTimeFormat.Types
13− , supportedLocalesOf
22+
14− , formatToParts
23+ -- private
15− , resolvedOptions
24+ , formatDateTimeOptions
25+ , DateTimeFormatOptions_
16 ) where
26 ) where
17
27
18import Data.Intl.DateTimeFormat.Types
28import Data.Intl.DateTimeFormat.Types
19
29
20−import Control.Monad.Error.Class (throwError)
30+import Data.Generic.Rep (class Generic)
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)
31+import Data.Intl.DateTimeFormat.Generic (class FormatComponent, defaultComponentRecord, formatComponent, genericFormatComponent)
26import Data.JSDate (JSDate)
32import Data.JSDate (JSDate)
27−import Data.Maybe (Maybe(..), fromMaybe, maybe)
33+import Data.Maybe (Maybe, fromMaybe, maybe)
28−import Data.Newtype (class Newtype, un)
34+import Data.Newtype (class Newtype)
29import Data.StrMap (union)
35import Data.StrMap (union)
30import Data.Symbol (SProxy(..))
36import Data.Symbol (SProxy(..))
31−import Data.Traversable (sequence)
32−import Data.Variant (Variant, case_, default, on)
37+import Data.Variant (Variant, default, on)
33−import Prelude (class Eq, class Show, Unit, bind, id, pure, show, (#), ($), (<$>), (<<<), (>>=))
38+import Prelude (class Eq, class Show, Unit, id, show, (#), ($))
34import Unsafe.Coerce (unsafeCoerce)
39import Unsafe.Coerce (unsafeCoerce)
35
40
36foreign import data LocalesOption' :: Type
41foreign import data LocalesOption' :: Type
42+foreign import data DateTimeFormat :: Type
43+
44+foreign import data Undefined :: Type
45+foreign import undefined :: Undefined
37
46
38foreign import dateTimeFormatImpl :: LocalesOption' -> DateTimeFormatOptions_ -> DateTimeFormat
47foreign import dateTimeFormatImpl :: LocalesOption' -> DateTimeFormatOptions_ -> DateTimeFormat
39
48
@@ -86,6 +95,85 @@ instance showFormatMatcher :: Show FormatMatcher where
86 show FMBasic = "basic"
95 show FMBasic = "basic"
87 show FMBestFit = "best fit"
96 show FMBestFit = "best fit"
88
97
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+
89type DateTimeComponents a =
177type DateTimeComponents a =
90 Variant
178 Variant
91 ( weekdayYearMonthDayHourMinuteSecond :: WeekdayYearMonthDayHourMinuteSecond
179 ( weekdayYearMonthDayHourMinuteSecond :: WeekdayYearMonthDayHourMinuteSecond
@@ -120,7 +208,7 @@ formatDateTimeOptions (DateTimeFormatOptions opts comps) = merge opts' (compsCoe
120 , hour12: fromMaybe (unsafeCoerce undefined) opts.hour12
208 , hour12: fromMaybe (unsafeCoerce undefined) opts.hour12
121 , formatMatcher: maybe undefinedString show opts.formatMatcher
209 , formatMatcher: maybe undefinedString show opts.formatMatcher
122 }
210 }
123− comps' = un FormatComponentRecord $ case_
211+ comps' = default (defaultComponentRecord)
124 # on (SProxy :: SProxy "weekdayYearMonthDayHourMinuteSecond") formatComponent
212 # on (SProxy :: SProxy "weekdayYearMonthDayHourMinuteSecond") formatComponent
125 # on (SProxy :: SProxy "weekdayYearMonthDay") formatComponent
213 # on (SProxy :: SProxy "weekdayYearMonthDay") formatComponent
126 # on (SProxy :: SProxy "yearMonthDay") formatComponent
214 # on (SProxy :: SProxy "yearMonthDay") formatComponent
@@ -186,158 +274,19 @@ formatDateTimeOptions (DateTimeFormatOptions opts comps) = merge opts' (compsCoe
186 -> DateTimeFormatOptions_
274 -> DateTimeFormatOptions_
187 merge a b = unsafeCoerce $ union (unsafeCoerce a) (unsafeCoerce b)
275 merge a b = unsafeCoerce $ union (unsafeCoerce a) (unsafeCoerce b)
188
276
189−foreign import data DateTimeFormat :: Type
277+foreign import data DateTimeFormatter :: Type
278+
279+foreign import createDateTimeFormatterImpl
280+ :: LocalesOption'
281+ -> DateTimeFormatOptions_
282+ -> DateTimeFormatter
190
283
191−foreign import createDateTimeFormatImpl
284+createDateTimeFormatter
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
282 :: forall a
285 :: forall a
283 .(FormatComponent a)
286 .(FormatComponent a)
284 => LocalesOption
287 => LocalesOption
285 -> DateTimeFormatOptions a
288 -> DateTimeFormatOptions a
286− -> F DateTimeFormat
289+ -> DateTimeFormatter
287−createDateTimeFormat ls opts =
288− runFn4 createDateTimeFormatImpl
289− (throwError <<< pure <<< ForeignError)
290− pure
291− (toLocale ls)
292− (formatDateTimeOptions opts)
290+createDateTimeFormatter ls opts = createDateTimeFormatterImpl (toLocale ls) (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
338
291
339− readMaybeString :: Foreign -> F (Maybe String)
292+foreign import formatJSDate :: DateTimeFormatter -> JSDate -> String
340− readMaybeString f =
341− if isUndefined f
342− then pure Nothing
343− else Just <$> readString f
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 @@
1module Data.Intl.DateTimeFormat.Generic
1module Data.Intl.DateTimeFormat.Generic
2+ ( class FormatComponent
3+ , formatComponent
2− ( class GenericFormatComponent
4+ , class GenericFormatComponent
3 , genericFormatComponent'
5 , genericFormatComponent'
4 , genericFormatComponent
6 , genericFormatComponent
5 , class GenericFormatComponentFields
7 , class GenericFormatComponentFields
6 , genericFormatComponentFields
8 , genericFormatComponentFields
9+ , defaultComponentRecord
10+ , FormatComponentRecord
7 ) where
11 ) where
8
12
9import Data.Generic.Rep (class Generic, Constructor(Constructor), Field(..), NoConstructors, Product(..), Rec(..), from)
13import Data.Generic.Rep (class Generic, Constructor(Constructor), Field(..), NoConstructors, Product(..), Rec(..), from)
10−import Data.Intl.DateTimeFormat.Class (FormatComponentRecord(..))
11import Data.Intl.DateTimeFormat.Types (MonthRep, NumericRep, TimeZoneNameRep, StringRep)
14import Data.Intl.DateTimeFormat.Types (MonthRep, NumericRep, TimeZoneNameRep, StringRep)
12import Data.Maybe (Maybe(..))
15import Data.Maybe (Maybe(..))
13import Data.StrMap (StrMap, lookup, singleton, union)
16import 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
15
49
16class GenericFormatComponent a where
50class GenericFormatComponent a where
17 genericFormatComponent' :: a -> FormatComponentRecord
51 genericFormatComponent' :: a -> FormatComponentRecord
@@ -20,7 +54,7 @@ class GenericFormatComponentFields a where
20 genericFormatComponentFields :: a -> StrMap String
54 genericFormatComponentFields :: a -> StrMap String
21
55
22instance genericFormatComponentNoConsturctors :: GenericFormatComponent NoConstructors where
56instance genericFormatComponentNoConsturctors :: GenericFormatComponent NoConstructors where
23− genericFormatComponent' a = FormatComponentRecord
57+ genericFormatComponent' a =
24 { era: Nothing
58 { era: Nothing
25 , weekday: Nothing
59 , weekday: Nothing
26 , year: Nothing
60 , year: Nothing
@@ -80,7 +114,7 @@ instance genericFormatComponentFieldsProduct
80instance genericFormatComponentRec
114instance genericFormatComponentRec
81 :: (GenericFormatComponentFields a)
115 :: (GenericFormatComponentFields a)
82 => GenericFormatComponent (Rec a) where
116 => GenericFormatComponent (Rec a) where
83− genericFormatComponent' (Rec a) = FormatComponentRecord
117+ genericFormatComponent' (Rec a) =
84 { era: "era" `lookup` u
118 { era: "era" `lookup` u
85 , weekday: "weekday" `lookup` u
119 , weekday: "weekday" `lookup` u
86 , year: "year" `lookup` u
120 , 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
1+module Data.Intl.DateTimeFormat.Types where
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
19
2
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, ($), (<>), (>>=))
3+import Prelude (class Show)
26−
27−foreign import data Undefined :: Type
28−
29−foreign import undefined :: Undefined
30
4
31data StringRep = Narrow | Short | Long
5data StringRep = Narrow | Short | Long
32
6
33−derive instance eqStringRep :: Eq StringRep
34−
35instance showStringRep :: Show StringRep where
7instance showStringRep :: Show StringRep where
36 show Narrow = "narrow"
8 show Narrow = "narrow"
37 show Short = "short"
9 show Short = "short"
@@ -39,16 +11,12 @@ instance showStringRep :: Show StringRep where
39
11
40data NumericRep = Numeric | TwoDigit
12data NumericRep = Numeric | TwoDigit
41
13
42−derive instance eqNumericRep :: Eq NumericRep
43−
44instance showNumericRep :: Show NumericRep where
14instance showNumericRep :: Show NumericRep where
45 show Numeric = "numeric"
15 show Numeric = "numeric"
46 show TwoDigit = "2-digit"
16 show TwoDigit = "2-digit"
47
17
48data MonthRep = MonthNumeric | MonthTwoDigit | MonthNarrow | MonthShort | MonthLong
18data MonthRep = MonthNumeric | MonthTwoDigit | MonthNarrow | MonthShort | MonthLong
49
19
50−derive instance eqMonthRep :: Eq MonthRep
51−
52instance showMonthRep :: Show MonthRep where
20instance showMonthRep :: Show MonthRep where
53 show MonthNumeric = "numeric"
21 show MonthNumeric = "numeric"
54 show MonthTwoDigit = "2-digit"
22 show MonthTwoDigit = "2-digit"
@@ -58,189 +26,7 @@ instance showMonthRep :: Show MonthRep where
58
26
59data TimeZoneNameRep = TimeZoneNameShort | TimeZoneNameLong
27data TimeZoneNameRep = TimeZoneNameShort | TimeZoneNameLong
60
28
61−derive instance eqTimeZoneNameRep :: Eq TimeZoneNameRep
62−
63instance showTimeZoneRep :: Show TimeZoneNameRep where
29instance showTimeZoneRep :: Show TimeZoneNameRep where
64 show TimeZoneNameShort = "short"
30 show TimeZoneNameShort = "short"
65 show TimeZoneNameLong = "long"
31 show TimeZoneNameLong = "long"
66
32
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
4
4
5import Control.Monad.Eff (Eff)
5import Control.Monad.Eff (Eff)
6import Control.Monad.Eff.Console (CONSOLE)
6import Control.Monad.Eff.Console (CONSOLE)
7−import Control.Monad.Except (runExcept)
8import Data.DateTime (Date, DateTime(..), Month(..), canonicalDate)
7import Data.DateTime (Date, DateTime(..), Month(..), canonicalDate)
9−import Data.Either (Either(..), fromRight, isLeft)
10import Data.Enum (toEnum)
8import Data.Enum (toEnum)
11−import Data.Foldable (intercalate)
12−import Data.Foreign (F, renderForeignError)
13import Data.Generic.Rep (class Generic)
9import 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)
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)
15−import Data.Intl.DateTimeFormat.Class (class FormatComponent, FormatComponentRecord(..))
11+import Data.Intl.DateTimeFormat.Generic (class FormatComponent, genericFormatComponent)
16−import Data.Intl.DateTimeFormat.Generic (genericFormatComponent)
17import Data.JSDate (JSDate, fromDateTime)
12import Data.JSDate (JSDate, fromDateTime)
18−import Data.Maybe (Maybe(..), isJust, isNothing)
13+import Data.Maybe (Maybe(..))
19import Data.Symbol (SProxy(..))
14import Data.Symbol (SProxy(..))
20import Data.Time (Time(..))
15import Data.Time (Time(..))
21import Data.Variant (inj)
16import Data.Variant (inj)
22−import Partial.Unsafe (unsafeCrashWith, unsafePartial)
17+import Partial.Unsafe (unsafeCrashWith)
23import Test.Assert (ASSERT, assert')
18import Test.Assert (ASSERT, assert')
24
19
25type Tests = Eff (console :: CONSOLE, assert :: ASSERT) Unit
20type Tests = Eff (console :: CONSOLE, assert :: ASSERT) Unit
@@ -37,7 +32,7 @@ instance formatComponentEraYear :: FormatComponent EraYear where
37newtype Era = Era StringRep
32newtype Era = Era StringRep
38
33
39instance formatComponentEra :: FormatComponent Era where
34instance formatComponentEra :: FormatComponent Era where
40− formatComponent (Era r) = FormatComponentRecord
35+ formatComponent (Era r) =
41 { era: Just (show r)
36 { era: Just (show r)
42 , weekday: Nothing
37 , weekday: Nothing
43 , year: Nothing
38 , year: Nothing
@@ -53,28 +48,11 @@ main :: Tests
53main = do
48main = do
54 let
49 let
55
50
56− unsafeFromF :: forall a. F a -> a
57− unsafeFromF = unsafePartial fromRight <<< runExcept
58−
59 locales :: LocalesOption
51 locales :: LocalesOption
60 locales = inj (SProxy :: SProxy "locale") "en-US"
52 locales = inj (SProxy :: SProxy "locale") "en-US"
61
53
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 $
54+ fmtHourMinute =
77− createDateTimeFormat locales opts
55+ createDateTimeFormatter locales opts
78 where
56 where
79 opts :: DateTimeFormatOptions'
57 opts :: DateTimeFormatOptions'
80 opts =
58 opts =
@@ -87,8 +65,8 @@ main = do
87 (inj (SProxy :: SProxy "hourMinute") (HourMinute {hour: TwoDigit, minute: TwoDigit}))
65 (inj (SProxy :: SProxy "hourMinute") (HourMinute {hour: TwoDigit, minute: TwoDigit}))
88 )
66 )
89
67
90− fmtHourMinuteSecond = unsafeFromF $
68+ fmtHourMinuteSecond =
91− createDateTimeFormat locales opts
69+ createDateTimeFormatter locales opts
92 where
70 where
93 opts :: DateTimeFormatOptions'
71 opts :: DateTimeFormatOptions'
94 opts =
72 opts =
@@ -101,8 +79,8 @@ main = do
101 (inj (SProxy :: SProxy "hourMinuteSecond") (HourMinuteSecond {hour: Numeric, minute: Numeric, second: Numeric}))
79 (inj (SProxy :: SProxy "hourMinuteSecond") (HourMinuteSecond {hour: Numeric, minute: Numeric, second: Numeric}))
102 )
80 )
103
81
104− fmtWeekdayYearMonthDayHourMinuteSecond = unsafeFromF $
82+ fmtWeekdayYearMonthDayHourMinuteSecond =
105− createDateTimeFormat locales opts
83+ createDateTimeFormatter locales opts
106 where
84 where
107 opts :: DateTimeFormatOptions'
85 opts :: DateTimeFormatOptions'
108 opts =
86 opts =
@@ -127,8 +105,8 @@ main = do
127 )
105 )
128 )
106 )
129
107
130− fmtWeekdayYearMonthDay = unsafeFromF $
108+ fmtWeekdayYearMonthDay =
131− createDateTimeFormat locales opts
109+ createDateTimeFormatter locales opts
132 where
110 where
133 opts :: DateTimeFormatOptions'
111 opts :: DateTimeFormatOptions'
134 opts =
112 opts =
@@ -150,8 +128,8 @@ main = do
150 )
128 )
151 )
129 )
152
130
153− fmtYearMonthDay = unsafeFromF $
131+ fmtYearMonthDay =
154− createDateTimeFormat locales opts
132+ createDateTimeFormatter locales opts
155 where
133 where
156 opts :: DateTimeFormatOptions'
134 opts :: DateTimeFormatOptions'
157 opts =
135 opts =
@@ -172,8 +150,8 @@ main = do
172 )
150 )
173 )
151 )
174
152
175− fmtYearMonth = unsafeFromF $
153+ fmtYearMonth =
176− createDateTimeFormat locales opts
154+ createDateTimeFormatter locales opts
177 where
155 where
178 opts :: DateTimeFormatOptions'
156 opts :: DateTimeFormatOptions'
179 opts =
157 opts =
@@ -193,8 +171,8 @@ main = do
193 )
171 )
194 )
172 )
195
173
196− fmtMonthDay = unsafeFromF $
174+ fmtMonthDay =
197− createDateTimeFormat locales opts
175+ createDateTimeFormatter locales opts
198 where
176 where
199 opts :: DateTimeFormatOptions'
177 opts :: DateTimeFormatOptions'
200 opts =
178 opts =
@@ -214,8 +192,8 @@ main = do
214 )
192 )
215 )
193 )
216
194
217− fmtEraYear = unsafeFromF $
195+ fmtEraYear =
218− createDateTimeFormat locales opts
196+ createDateTimeFormatter locales opts
219 where
197 where
220 opts :: DateTimeFormatOptions EraYear
198 opts :: DateTimeFormatOptions EraYear
221 opts =
199 opts =
@@ -235,8 +213,8 @@ main = do
235 )
213 )
236 )
214 )
237
215
238− fmtEra = unsafeFromF $
216+ fmtEra =
239− createDateTimeFormat locales opts
217+ createDateTimeFormatter locales opts
240 where
218 where
241 opts :: DateTimeFormatOptions Era
219 opts :: DateTimeFormatOptions Era
242 opts =
220 opts =
@@ -280,9 +258,6 @@ main = do
280 case jsDate of
258 case jsDate of
281 Nothing -> unsafeCrashWith "jsDate not parsed"
259 Nothing -> unsafeCrashWith "jsDate not parsed"
282 Just d -> do
260 Just d -> do
283−
284− assert' "fmtError expected to return error" $ isLeft (runExcept fmtError)
285−
286 let fmtDate1 = formatJSDate fmtWeekdayYearMonthDayHourMinuteSecond d
261 let fmtDate1 = formatJSDate fmtWeekdayYearMonthDayHourMinuteSecond d
287 fmtDate1Expected = "Tue, January 2, 2018, 12:00:00 PM"
262 fmtDate1Expected = "Tue, January 2, 2018, 12:00:00 PM"
288 assert' ("fmtWeekdayYearMonthDayHourMinuteSecond: got: '" <> fmtDate1 <> "' expected: '" <> fmtDate1Expected <> "'")
263 assert' ("fmtWeekdayYearMonthDayHourMinuteSecond: got: '" <> fmtDate1 <> "' expected: '" <> fmtDate1Expected <> "'")
@@ -319,25 +294,3 @@ main = do
319 fmtDate9Expected = "1 2, 2018 AD"
294 fmtDate9Expected = "1 2, 2018 AD"
320 assert' ("fmtEra: got '" <> fmtDate9 <> "' expected: '" <> fmtDate9Expected <> "'")
295 assert' ("fmtEra: got '" <> fmtDate9 <> "' expected: '" <> fmtDate9Expected <> "'")
321 $ fmtDate9 == fmtDate9Expected
296 $ 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−