git.iko.soy/purescript-intl
on master help sign in
7 files changed+360−189
since splitsnapshots
unifiedsplit
src/Data/Intl/DateTimeFormat.js+3−5 src/Data/Intl/DateTimeFormat.purs+119−118 src/Data/Intl/DateTimeFormat/Class.purs+41 src/Data/Intl/DateTimeFormat/Generic.purs+5−39 src/Data/Intl/DateTimeFormat/Types.js+3 src/Data/Intl/DateTimeFormat/Types.purs+161−3 test/Test/Main.purs+28−24
src/Data/Intl/DateTimeFormat.js+3−5
@@ -1,18 +1,16 @@
11"use strict";
22
3−exports["undefined"] = undefined;
4−
53exports.dateTimeFormatImpl = function(locales) {
64 return function(options) {
75 return new Intl.DateTimeFormat(locales, options);
86 };
97};
108
11−exports.createDateTimeFormatterImpl = function(Left, Right, locales, opts) {
9+exports.createDateTimeFormatImpl = function(throwError, pure, locales, opts) {
1210 try {
13− return Right(Intl.DateTimeFormat(locales, opts));
11+ return pure(Intl.DateTimeFormat(locales, opts));
1412 } catch (e) {
15− return Left(e.message);
13+ return throwError(e.message);
1614 }
1715};
1816
src/Data/Intl/DateTimeFormat.purs+119−118
@@ -1,22 +1,13 @@
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
156 , DateTimeFormatOptions(..)
167 , DateTimeFormatOptions'
178 , DateTimeComponents(..)
18− , DateTimeFormatter
19− , createDateTimeFormatter
9+ , DateTimeFormat
10+ , createDateTimeFormat
2011 , formatJSDate
2112 , module Data.Intl.DateTimeFormat.Types
2213 , supportedLocalesOf
@@ -26,27 +17,23 @@ module Data.Intl.DateTimeFormat
2617
2718import Data.Intl.DateTimeFormat.Types
2819
20+import Control.Monad.Error.Class (throwError)
2921import Data.Either (Either(..))
30−import Data.Foreign (F, Foreign, isUndefined, readString)
22+import Data.Foreign (F, Foreign, ForeignError(..), isUndefined, readString)
3123import Data.Foreign.Index ((!))
3224import Data.Function.Uncurried (Fn3, Fn4, runFn3, runFn4)
33−import Data.Generic.Rep (class Generic)
34−import Data.Intl.DateTimeFormat.Generic (class FormatComponent, defaultComponentRecord, formatComponent, genericFormatComponent)
25+import Data.Intl.DateTimeFormat.Class (class FormatComponent, FormatComponentRecord(FormatComponentRecord), formatComponent)
3526import Data.JSDate (JSDate)
3627import Data.Maybe (Maybe(..), fromMaybe, maybe)
37−import Data.Newtype (class Newtype)
28+import Data.Newtype (class Newtype, un)
3829import Data.StrMap (union)
3930import Data.Symbol (SProxy(..))
4031import Data.Traversable (sequence)
41−import Data.Variant (Variant, default, on)
42−import Prelude (class Eq, class Show, Unit, bind, id, pure, show, (#), ($), (<$>), (>>=))
32+import Data.Variant (Variant, case_, default, on)
33+import Prelude (class Eq, class Show, Unit, bind, id, pure, show, (#), ($), (<$>), (<<<), (>>=))
4334import Unsafe.Coerce (unsafeCoerce)
4435
4536foreign import data LocalesOption' :: Type
46−foreign import data DateTimeFormat :: Type
47−
48−foreign import data Undefined :: Type
49−foreign import undefined :: Undefined
5037
5138foreign import dateTimeFormatImpl :: LocalesOption' -> DateTimeFormatOptions_ -> DateTimeFormat
5239
@@ -99,85 +86,6 @@ instance showFormatMatcher :: Show FormatMatcher where
9986 show FMBasic = "basic"
10087 show FMBestFit = "best fit"
10188
102−newtype WeekdayYearMonthDayHourMinuteSecond = WeekdayYearMonthDayHourMinuteSecond
103− { weekday :: StringRep
104− , year :: NumericRep
105− , month :: MonthRep
106− , day :: NumericRep
107− , hour :: NumericRep
108− , minute :: NumericRep
109− , second :: NumericRep
110− }
111−
112−derive instance genericWeekdayYearMonthDayHourMinuteSecond :: Generic WeekdayYearMonthDayHourMinuteSecond _
113−
114−instance formatComponentWeekdayYearMonthDayHourMinuteSecond :: FormatComponent WeekdayYearMonthDayHourMinuteSecond where
115− formatComponent = genericFormatComponent
116−
117−newtype WeekdayYearMonthDay = WeekdayYearMonthDay
118− { weekday :: StringRep
119− , year :: NumericRep
120− , month :: MonthRep
121− , day :: NumericRep
122− }
123−
124−derive instance genericWeekdayYearMonthDay :: Generic WeekdayYearMonthDay _
125−
126−instance formatComponentWeekdayYearMonthDay :: FormatComponent WeekdayYearMonthDay where
127− formatComponent = genericFormatComponent
128−
129−newtype YearMonthDay = YearMonthDay
130− { year :: NumericRep
131− , month :: MonthRep
132− , day :: NumericRep
133− }
134−
135−derive instance genericYearMonthDay :: Generic YearMonthDay _
136−
137−instance formatComponentYearMonthDay :: FormatComponent YearMonthDay where
138− formatComponent = genericFormatComponent
139−
140−newtype YearMonth = YearMonth
141− { year :: NumericRep
142− , month :: MonthRep
143− }
144−
145−derive instance genericYearMonth :: Generic YearMonth _
146−
147−instance formatComponentYearMonth :: FormatComponent YearMonth where
148− formatComponent = genericFormatComponent
149−
150−newtype MonthDay = MonthDay
151− { month :: MonthRep
152− , day :: NumericRep
153− }
154−
155−derive instance genericMonthDay :: Generic MonthDay _
156−
157−instance formatComponentMonthDay :: FormatComponent MonthDay where
158− formatComponent = genericFormatComponent
159−
160−newtype HourMinuteSecond = HourMinuteSecond
161− { hour :: NumericRep
162− , minute :: NumericRep
163− , second :: NumericRep
164− }
165−
166−derive instance genericHourMinuteSecond :: Generic HourMinuteSecond _
167−
168−instance formatComponentHourMinuteSecond :: FormatComponent HourMinuteSecond where
169− formatComponent = genericFormatComponent
170−
171−newtype HourMinute = HourMinute
172− { hour :: NumericRep
173− , minute :: NumericRep
174− }
175−
176−derive instance genericHourMinute :: Generic HourMinute _
177−
178−instance formatComponentHourMinute :: FormatComponent HourMinute where
179− formatComponent = genericFormatComponent
180−
18189type DateTimeComponents a =
18290 Variant
18391 ( weekdayYearMonthDayHourMinuteSecond :: WeekdayYearMonthDayHourMinuteSecond
@@ -212,7 +120,7 @@ formatDateTimeOptions (DateTimeFormatOptions opts comps) = merge opts' (compsCoe
212120 , hour12: fromMaybe (unsafeCoerce undefined) opts.hour12
213121 , formatMatcher: maybe undefinedString show opts.formatMatcher
214122 }
215− comps' = default (defaultComponentRecord)
123+ comps' = un FormatComponentRecord $ case_
216124 # on (SProxy :: SProxy "weekdayYearMonthDayHourMinuteSecond") formatComponent
217125 # on (SProxy :: SProxy "weekdayYearMonthDay") formatComponent
218126 # on (SProxy :: SProxy "yearMonthDay") formatComponent
@@ -278,25 +186,118 @@ formatDateTimeOptions (DateTimeFormatOptions opts comps) = merge opts' (compsCoe
278186 -> DateTimeFormatOptions_
279187 merge a b = unsafeCoerce $ union (unsafeCoerce a) (unsafeCoerce b)
280188
281−foreign import data DateTimeFormatter :: Type
189+foreign import data DateTimeFormat :: Type
282190
283−foreign import createDateTimeFormatterImpl
191+foreign import createDateTimeFormatImpl
284192 :: Fn4
285− (String -> Either String DateTimeFormatter)
286− (DateTimeFormatter -> Either String DateTimeFormatter)
193+ (forall a. String -> F a)
194+ (forall a. a -> F a)
287195 LocalesOption'
288196 DateTimeFormatOptions_
289− (Either String DateTimeFormatter)
290−
291−createDateTimeFormatter
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
292282 :: forall a
293283 .(FormatComponent a)
294284 => LocalesOption
295285 -> DateTimeFormatOptions a
296− -> Either String DateTimeFormatter
297−createDateTimeFormatter ls opts = runFn4 createDateTimeFormatterImpl Left Right (toLocale ls) (formatDateTimeOptions opts)
298−
299−foreign import formatJSDate :: DateTimeFormatter -> JSDate -> String
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
300301
301302foreign import supportedLocalesOfImpl
302303 :: Fn3
@@ -304,18 +305,18 @@ foreign import supportedLocalesOfImpl
304305 (Array String -> Either String (Array String))
305306 (Array String)
306307 (Either String (Array String))
307−
308−foreign import formatToPartsImpl :: DateTimeFormatter -> JSDate -> Array Foreign
309308
310−formatToParts :: DateTimeFormatter -> JSDate -> F (Array FormatParts)
309+foreign import formatToPartsImpl :: DateTimeFormat -> JSDate -> Array Foreign
310+
311+formatToParts :: DateTimeFormat -> JSDate -> F (Array FormatParts)
311312formatToParts formatter date = sequence $ readFormatParts <$> formatToPartsImpl formatter date
312313
313314supportedLocalesOf :: Array String -> Either String (Array String)
314315supportedLocalesOf locales = runFn3 supportedLocalesOfImpl Left Right locales
315316
316−foreign import resolvedOptionsImpl :: DateTimeFormatter -> Foreign
317+foreign import resolvedOptionsImpl :: DateTimeFormat -> Foreign
317318
318−resolvedOptions :: DateTimeFormatter -> F ResolvedOptions
319+resolvedOptions :: DateTimeFormat -> F ResolvedOptions
319320resolvedOptions fmt = do
320321 locale <- obj ! "locale" >>= readString
321322 calendar <- obj ! "calendar" >>= readString
src/Data/Intl/DateTimeFormat/Class.pursnew file+41
@@ -0,0 +1,41 @@
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+5−39
@@ -1,51 +1,17 @@
11module Data.Intl.DateTimeFormat.Generic
2− ( class FormatComponent
3− , formatComponent
4− , class GenericFormatComponent
2+ ( class GenericFormatComponent
53 , genericFormatComponent'
64 , genericFormatComponent
75 , class GenericFormatComponentFields
86 , genericFormatComponentFields
9− , defaultComponentRecord
10− , FormatComponentRecord
117 ) where
128
139import Data.Generic.Rep (class Generic, Constructor(Constructor), Field(..), NoConstructors, Product(..), Rec(..), from)
10+import Data.Intl.DateTimeFormat.Class (FormatComponentRecord(..))
1411import Data.Intl.DateTimeFormat.Types (MonthRep, NumericRep, TimeZoneNameRep, StringRep)
1512import Data.Maybe (Maybe(..))
1613import Data.StrMap (StrMap, lookup, singleton, union)
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
14+import Prelude (show)
4915
5016class GenericFormatComponent a where
5117 genericFormatComponent' :: a -> FormatComponentRecord
@@ -54,7 +20,7 @@ class GenericFormatComponentFields a where
5420 genericFormatComponentFields :: a -> StrMap String
5521
5622instance genericFormatComponentNoConsturctors :: GenericFormatComponent NoConstructors where
57− genericFormatComponent' a =
23+ genericFormatComponent' a = FormatComponentRecord
5824 { era: Nothing
5925 , weekday: Nothing
6026 , year: Nothing
@@ -114,7 +80,7 @@ instance genericFormatComponentFieldsProduct
11480instance genericFormatComponentRec
11581 :: (GenericFormatComponentFields a)
11682 => GenericFormatComponent (Rec a) where
117− genericFormatComponent' (Rec a) =
83+ genericFormatComponent' (Rec a) = FormatComponentRecord
11884 { era: "era" `lookup` u
11985 , weekday: "weekday" `lookup` u
12086 , year: "year" `lookup` u
src/Data/Intl/DateTimeFormat/Types.jsnew file+3
@@ -0,0 +1,3 @@
1+"use strict";
2+
3+exports["undefined"] = undefined;
src/Data/Intl/DateTimeFormat/Types.purs+161−3
@@ -6,16 +6,32 @@ module Data.Intl.DateTimeFormat.Types
66 , FormatParts(..)
77 , readFormatParts
88 , ResolvedOptions(..)
9+ , WeekdayYearMonthDayHourMinuteSecond(..)
10+ , WeekdayYearMonthDay(..)
11+ , YearMonthDay(..)
12+ , YearMonth(..)
13+ , MonthDay(..)
14+ , HourMinuteSecond(..)
15+ , HourMinute(..)
16+ , Undefined
17+ , undefined
918 ) where
1019
1120import Data.Foreign (F, Foreign, ForeignError(..), fail, readString)
1221import Data.Foreign.Index ((!))
13−import Data.Maybe (Maybe)
14−import Data.Newtype (class Newtype)
15−import Prelude (class Show, bind, pure, ($), (<>), (>>=))
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
1630
1731data StringRep = Narrow | Short | Long
1832
33+derive instance eqStringRep :: Eq StringRep
34+
1935instance showStringRep :: Show StringRep where
2036 show Narrow = "narrow"
2137 show Short = "short"
@@ -23,12 +39,16 @@ instance showStringRep :: Show StringRep where
2339
2440data NumericRep = Numeric | TwoDigit
2541
42+derive instance eqNumericRep :: Eq NumericRep
43+
2644instance showNumericRep :: Show NumericRep where
2745 show Numeric = "numeric"
2846 show TwoDigit = "2-digit"
2947
3048data MonthRep = MonthNumeric | MonthTwoDigit | MonthNarrow | MonthShort | MonthLong
3149
50+derive instance eqMonthRep :: Eq MonthRep
51+
3252instance showMonthRep :: Show MonthRep where
3353 show MonthNumeric = "numeric"
3454 show MonthTwoDigit = "2-digit"
@@ -38,6 +58,8 @@ instance showMonthRep :: Show MonthRep where
3858
3959data TimeZoneNameRep = TimeZoneNameShort | TimeZoneNameLong
4060
61+derive instance eqTimeZoneNameRep :: Eq TimeZoneNameRep
62+
4163instance showTimeZoneRep :: Show TimeZoneNameRep where
4264 show TimeZoneNameShort = "short"
4365 show TimeZoneNameLong = "long"
@@ -53,6 +75,8 @@ data FormatParts
5375 | DayPeriod String
5476 | Literal String
5577
78+derive instance eqFormatParts :: Eq FormatParts
79+
5680readFormatParts :: Foreign -> F FormatParts
5781readFormatParts val = do
5882 type_ <- val ! "type" >>= readString
@@ -86,3 +110,137 @@ newtype ResolvedOptions = ResolvedOptions
86110 }
87111
88112derive 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+28−24
@@ -9,10 +9,11 @@ import Data.DateTime (Date, DateTime(..), Month(..), canonicalDate)
99import Data.Either (Either(..), fromRight, isLeft)
1010import Data.Enum (toEnum)
1111import Data.Foldable (intercalate)
12−import Data.Foreign (renderForeignError)
12+import Data.Foreign (F, renderForeignError)
1313import 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), createDateTimeFormatter, formatJSDate, resolvedOptions, supportedLocalesOf)
15−import Data.Intl.DateTimeFormat.Generic (class FormatComponent, genericFormatComponent)
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)
1617import Data.JSDate (JSDate, fromDateTime)
1718import Data.Maybe (Maybe(..), isJust, isNothing)
1819import Data.Symbol (SProxy(..))
@@ -36,7 +37,7 @@ instance formatComponentEraYear :: FormatComponent EraYear where
3637newtype Era = Era StringRep
3738
3839instance formatComponentEra :: FormatComponent Era where
39− formatComponent (Era r) =
40+ formatComponent (Era r) = FormatComponentRecord
4041 { era: Just (show r)
4142 , weekday: Nothing
4243 , year: Nothing
@@ -52,11 +53,14 @@ main :: Tests
5253main = do
5354 let
5455
56+ unsafeFromF :: forall a. F a -> a
57+ unsafeFromF = unsafePartial fromRight <<< runExcept
58+
5559 locales :: LocalesOption
5660 locales = inj (SProxy :: SProxy "locale") "en-US"
5761
5862 fmtError =
59− createDateTimeFormatter (inj (SProxy :: SProxy "locale") "") opts
63+ createDateTimeFormat (inj (SProxy :: SProxy "locale") "") opts
6064 where
6165 opts :: DateTimeFormatOptions'
6266 opts =
@@ -69,8 +73,8 @@ main = do
6973 (inj (SProxy :: SProxy "hourMinute") (HourMinute {hour: TwoDigit, minute: TwoDigit}))
7074 )
7175
72− fmtHourMinute = unsafePartial $ fromRight $
73− createDateTimeFormatter locales opts
76+ fmtHourMinute = unsafeFromF $
77+ createDateTimeFormat locales opts
7478 where
7579 opts :: DateTimeFormatOptions'
7680 opts =
@@ -83,8 +87,8 @@ main = do
8387 (inj (SProxy :: SProxy "hourMinute") (HourMinute {hour: TwoDigit, minute: TwoDigit}))
8488 )
8589
86− fmtHourMinuteSecond = unsafePartial $ fromRight $
87− createDateTimeFormatter locales opts
90+ fmtHourMinuteSecond = unsafeFromF $
91+ createDateTimeFormat locales opts
8892 where
8993 opts :: DateTimeFormatOptions'
9094 opts =
@@ -97,8 +101,8 @@ main = do
97101 (inj (SProxy :: SProxy "hourMinuteSecond") (HourMinuteSecond {hour: Numeric, minute: Numeric, second: Numeric}))
98102 )
99103
100− fmtWeekdayYearMonthDayHourMinuteSecond = unsafePartial $ fromRight $
101− createDateTimeFormatter locales opts
104+ fmtWeekdayYearMonthDayHourMinuteSecond = unsafeFromF $
105+ createDateTimeFormat locales opts
102106 where
103107 opts :: DateTimeFormatOptions'
104108 opts =
@@ -123,8 +127,8 @@ main = do
123127 )
124128 )
125129
126− fmtWeekdayYearMonthDay = unsafePartial $ fromRight $
127− createDateTimeFormatter locales opts
130+ fmtWeekdayYearMonthDay = unsafeFromF $
131+ createDateTimeFormat locales opts
128132 where
129133 opts :: DateTimeFormatOptions'
130134 opts =
@@ -146,8 +150,8 @@ main = do
146150 )
147151 )
148152
149− fmtYearMonthDay = unsafePartial $ fromRight $
150− createDateTimeFormatter locales opts
153+ fmtYearMonthDay = unsafeFromF $
154+ createDateTimeFormat locales opts
151155 where
152156 opts :: DateTimeFormatOptions'
153157 opts =
@@ -168,8 +172,8 @@ main = do
168172 )
169173 )
170174
171− fmtYearMonth = unsafePartial $ fromRight $
172− createDateTimeFormatter locales opts
175+ fmtYearMonth = unsafeFromF $
176+ createDateTimeFormat locales opts
173177 where
174178 opts :: DateTimeFormatOptions'
175179 opts =
@@ -189,8 +193,8 @@ main = do
189193 )
190194 )
191195
192− fmtMonthDay = unsafePartial $ fromRight $
193− createDateTimeFormatter locales opts
196+ fmtMonthDay = unsafeFromF $
197+ createDateTimeFormat locales opts
194198 where
195199 opts :: DateTimeFormatOptions'
196200 opts =
@@ -210,8 +214,8 @@ main = do
210214 )
211215 )
212216
213− fmtEraYear = unsafePartial $ fromRight $
214− createDateTimeFormatter locales opts
217+ fmtEraYear = unsafeFromF $
218+ createDateTimeFormat locales opts
215219 where
216220 opts :: DateTimeFormatOptions EraYear
217221 opts =
@@ -231,8 +235,8 @@ main = do
231235 )
232236 )
233237
234− fmtEra = unsafePartial $ fromRight $
235− createDateTimeFormatter locales opts
238+ fmtEra = unsafeFromF $
239+ createDateTimeFormat locales opts
236240 where
237241 opts :: DateTimeFormatOptions Era
238242 opts =
@@ -277,7 +281,7 @@ main = do
277281 Nothing -> unsafeCrashWith "jsDate not parsed"
278282 Just d -> do
279283
280− assert' "fmtError expected to return error" $ isLeft fmtError
284+ assert' "fmtError expected to return error" $ isLeft (runExcept fmtError)
281285
282286 let fmtDate1 = formatJSDate fmtWeekdayYearMonthDayHourMinuteSecond d
283287 fmtDate1Expected = "Tue, January 2, 2018, 12:00:00 PM"