git.iko.soy/purescript-intl
on master help sign in
6 files changed+192−37
since splitsnapshots
unifiedsplit
src/Data/Intl/DateTimeFormat.js−2 src/Data/Intl/DateTimeFormat.purs+94−7 src/Data/Intl/DateTimeFormat/Class.purs+8−3 src/Data/Intl/DateTimeFormat/Generic.purs+3−3 src/Data/Intl/DateTimeFormat/Types.purs+84−20 test/Test/Main.purs+3−2
src/Data/Intl/DateTimeFormat.js−2
@@ -1,7 +1,5 @@
11"use strict";
22
3−exports["undefined"] = undefined;
4−
53exports.dateTimeFormatImpl = function(locales) {
64 return function(options) {
75 return new Intl.DateTimeFormat(locales, options);
src/Data/Intl/DateTimeFormat.purs+94−7
@@ -1,4 +1,4 @@
1−module Data.Intl.DateTimeFormat
1+module Data.Intl.DateTimeFormat
22 ( LocalesOption
33 , LocaleMatcher(..)
44 , TimeZone(..)
@@ -22,15 +22,14 @@ import Data.Either (Either(..))
2222import Data.Foreign (F, Foreign, ForeignError(..), isUndefined, readString)
2323import Data.Foreign.Index ((!))
2424import Data.Function.Uncurried (Fn3, Fn4, runFn3, runFn4)
25−import Data.Generic.Rep (class Generic)
26−import Data.Intl.DateTimeFormat.Generic (class FormatComponent, defaultComponentRecord, formatComponent, genericFormatComponent)
25+import Data.Intl.DateTimeFormat.Class (class FormatComponent, FormatComponentRecord(FormatComponentRecord), formatComponent)
2726import Data.JSDate (JSDate)
2827import Data.Maybe (Maybe(..), fromMaybe, maybe)
29−import Data.Newtype (class Newtype)
28+import Data.Newtype (class Newtype, un)
3029import Data.StrMap (union)
3130import Data.Symbol (SProxy(..))
3231import Data.Traversable (sequence)
33−import Data.Variant (Variant, default, on)
32+import Data.Variant (Variant, case_, default, on)
3433import Prelude (class Eq, class Show, Unit, bind, id, pure, show, (#), ($), (<$>), (<<<), (>>=))
3534import Unsafe.Coerce (unsafeCoerce)
3635
@@ -121,7 +120,7 @@ formatDateTimeOptions (DateTimeFormatOptions opts comps) = merge opts' (compsCoe
121120 , hour12: fromMaybe (unsafeCoerce undefined) opts.hour12
122121 , formatMatcher: maybe undefinedString show opts.formatMatcher
123122 }
124− comps' = default (defaultComponentRecord)
123+ comps' = un FormatComponentRecord $ case_
125124 # on (SProxy :: SProxy "weekdayYearMonthDayHourMinuteSecond") formatComponent
126125 # on (SProxy :: SProxy "weekdayYearMonthDay") formatComponent
127126 # on (SProxy :: SProxy "yearMonthDay") formatComponent
@@ -197,6 +196,88 @@ foreign import createDateTimeFormatImpl
197196 DateTimeFormatOptions_
198197 (F DateTimeFormat)
199198
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+-- | ```
200281createDateTimeFormat
201282 :: forall a
202283 .(FormatComponent a)
@@ -210,6 +291,12 @@ createDateTimeFormat ls opts =
210291 (toLocale ls)
211292 (formatDateTimeOptions opts)
212293
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+-- | ```
213300foreign import formatJSDate :: DateTimeFormat -> JSDate -> String
214301
215302foreign import supportedLocalesOfImpl
@@ -218,7 +305,7 @@ foreign import supportedLocalesOfImpl
218305 (Array String -> Either String (Array String))
219306 (Array String)
220307 (Either String (Array String))
221−
308+
222309foreign import formatToPartsImpl :: DateTimeFormat -> JSDate -> Array Foreign
223310
224311formatToParts :: DateTimeFormat -> JSDate -> F (Array FormatParts)
src/Data/Intl/DateTimeFormat/Class.purs+8−3
@@ -1,9 +1,10 @@
11module Data.Intl.DateTimeFormat.Class where
22
33import Data.Maybe (Maybe(..))
4−import Prelude (Unit)
4+import Data.Newtype (class Newtype)
5+import Prelude (class Eq, Unit)
56
6−type FormatComponentRecord =
7+newtype FormatComponentRecord = FormatComponentRecord
78 { era :: Maybe String
89 , weekday :: Maybe String
910 , year :: Maybe String
@@ -15,8 +16,12 @@ type FormatComponentRecord =
1516 , timeZoneName :: Maybe String
1617 }
1718
19+derive instance newtypeFormatComponentRecord :: Newtype FormatComponentRecord _
20+
21+derive instance eqFormatComponentRecord :: Eq FormatComponentRecord
22+
1823defaultComponentRecord :: FormatComponentRecord
19−defaultComponentRecord =
24+defaultComponentRecord = FormatComponentRecord
2025 { era: Nothing
2126 , weekday: Nothing
2227 , year: Nothing
src/Data/Intl/DateTimeFormat/Generic.purs+3−3
@@ -7,7 +7,7 @@ module Data.Intl.DateTimeFormat.Generic
77 ) where
88
99import Data.Generic.Rep (class Generic, Constructor(Constructor), Field(..), NoConstructors, Product(..), Rec(..), from)
10−import Data.Intl.DateTimeFormat.Class (FormatComponentRecord)
10+import Data.Intl.DateTimeFormat.Class (FormatComponentRecord(..))
1111import Data.Intl.DateTimeFormat.Types (MonthRep, NumericRep, TimeZoneNameRep, StringRep)
1212import Data.Maybe (Maybe(..))
1313import Data.StrMap (StrMap, lookup, singleton, union)
@@ -20,7 +20,7 @@ class GenericFormatComponentFields a where
2020 genericFormatComponentFields :: a -> StrMap String
2121
2222instance genericFormatComponentNoConsturctors :: GenericFormatComponent NoConstructors where
23− genericFormatComponent' a =
23+ genericFormatComponent' a = FormatComponentRecord
2424 { era: Nothing
2525 , weekday: Nothing
2626 , year: Nothing
@@ -80,7 +80,7 @@ instance genericFormatComponentFieldsProduct
8080instance genericFormatComponentRec
8181 :: (GenericFormatComponentFields a)
8282 => GenericFormatComponent (Rec a) where
83− genericFormatComponent' (Rec a) =
83+ genericFormatComponent' (Rec a) = FormatComponentRecord
8484 { era: "era" `lookup` u
8585 , weekday: "weekday" `lookup` u
8686 , year: "year" `lookup` u
src/Data/Intl/DateTimeFormat/Types.purs+84−20
@@ -19,18 +19,19 @@ module Data.Intl.DateTimeFormat.Types
1919
2020import Data.Foreign (F, Foreign, ForeignError(..), fail, readString)
2121import Data.Foreign.Index ((!))
22−import Data.Generic (class Generic)
23−import Data.Intl.DateTimeFormat.Class (class FormatComponent)
24−import Data.Intl.DateTimeFormat.Generic (genericFormatComponent)
25−import Data.Maybe (Maybe)
26−import Data.Newtype (class Newtype)
27−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, ($), (<>), (>>=))
2826
2927foreign import data Undefined :: Type
28+
3029foreign import undefined :: Undefined
3130
3231data StringRep = Narrow | Short | Long
3332
33+derive instance eqStringRep :: Eq StringRep
34+
3435instance showStringRep :: Show StringRep where
3536 show Narrow = "narrow"
3637 show Short = "short"
@@ -38,12 +39,16 @@ instance showStringRep :: Show StringRep where
3839
3940data NumericRep = Numeric | TwoDigit
4041
42+derive instance eqNumericRep :: Eq NumericRep
43+
4144instance showNumericRep :: Show NumericRep where
4245 show Numeric = "numeric"
4346 show TwoDigit = "2-digit"
4447
4548data MonthRep = MonthNumeric | MonthTwoDigit | MonthNarrow | MonthShort | MonthLong
4649
50+derive instance eqMonthRep :: Eq MonthRep
51+
4752instance showMonthRep :: Show MonthRep where
4853 show MonthNumeric = "numeric"
4954 show MonthTwoDigit = "2-digit"
@@ -53,6 +58,8 @@ instance showMonthRep :: Show MonthRep where
5358
5459data TimeZoneNameRep = TimeZoneNameShort | TimeZoneNameLong
5560
61+derive instance eqTimeZoneNameRep :: Eq TimeZoneNameRep
62+
5663instance showTimeZoneRep :: Show TimeZoneNameRep where
5764 show TimeZoneNameShort = "short"
5865 show TimeZoneNameLong = "long"
@@ -68,6 +75,8 @@ data FormatParts
6875 | DayPeriod String
6976 | Literal String
7077
78+derive instance eqFormatParts :: Eq FormatParts
79+
7180readFormatParts :: Foreign -> F FormatParts
7281readFormatParts val = do
7382 type_ <- val ! "type" >>= readString
@@ -102,6 +111,8 @@ newtype ResolvedOptions = ResolvedOptions
102111
103112derive instance newtypeResolvedOptions :: Newtype ResolvedOptions _
104113
114+derive instance eqResolvedOptions :: Eq ResolvedOptions
115+
105116newtype WeekdayYearMonthDayHourMinuteSecond = WeekdayYearMonthDayHourMinuteSecond
106117 { weekday :: StringRep
107118 , year :: NumericRep
@@ -112,10 +123,21 @@ newtype WeekdayYearMonthDayHourMinuteSecond = WeekdayYearMonthDayHourMinuteSecon
112123 , second :: NumericRep
113124 }
114125
115−derive instance genericWeekdayYearMonthDayHourMinuteSecond :: Generic WeekdayYearMonthDayHourMinuteSecond _
126+derive instance newtypeWeekdayYearMonthDayHourMinuteSecond :: Newtype WeekdayYearMonthDayHourMinuteSecond _
127+
128+derive instance eqWeekdayYearMonthDayHourMinuteSecond :: Eq WeekdayYearMonthDayHourMinuteSecond
116129
117130instance formatComponentWeekdayYearMonthDayHourMinuteSecond :: FormatComponent WeekdayYearMonthDayHourMinuteSecond where
118− formatComponent = genericFormatComponent
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
119141
120142newtype WeekdayYearMonthDay = WeekdayYearMonthDay
121143 { weekday :: StringRep
@@ -124,10 +146,19 @@ newtype WeekdayYearMonthDay = WeekdayYearMonthDay
124146 , day :: NumericRep
125147 }
126148
127−derive instance genericWeekdayYearMonthDay :: Generic WeekdayYearMonthDay _
149+derive instance newtypeWeekdayYearMonthDay :: Newtype WeekdayYearMonthDay _
150+
151+derive instance eqWeekdayYearMonthDay :: Eq WeekdayYearMonthDay
128152
129153instance formatComponentWeekdayYearMonthDay :: FormatComponent WeekdayYearMonthDay where
130− formatComponent = genericFormatComponent
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+
131162
132163newtype YearMonthDay = YearMonthDay
133164 { year :: NumericRep
@@ -135,30 +166,50 @@ newtype YearMonthDay = YearMonthDay
135166 , day :: NumericRep
136167 }
137168
138−derive instance genericYearMonthDay :: Generic YearMonthDay _
169+derive instance newtypeYearMonthDay :: Newtype YearMonthDay _
170+
171+derive instance eqYearMonthDay :: Eq YearMonthDay
139172
140173instance formatComponentYearMonthDay :: FormatComponent YearMonthDay where
141− formatComponent = genericFormatComponent
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+
142181
143182newtype YearMonth = YearMonth
144183 { year :: NumericRep
145184 , month :: MonthRep
146185 }
147186
148−derive instance genericYearMonth :: Generic YearMonth _
187+derive instance newtypeYearMonth :: Newtype YearMonth _
188+
189+derive instance eqYearMonth :: Eq YearMonth
149190
150191instance formatComponentYearMonth :: FormatComponent YearMonth where
151− formatComponent = genericFormatComponent
192+ formatComponent (YearMonth { year, month }) = over FormatComponentRecord
193+ (\r -> r { year = Just (show year)
194+ , month = Just (show month)
195+ }
196+ ) defaultComponentRecord
152197
153198newtype MonthDay = MonthDay
154199 { month :: MonthRep
155200 , day :: NumericRep
156201 }
157202
158−derive instance genericMonthDay :: Generic MonthDay _
203+derive instance newtypeMonthDay :: Newtype MonthDay _
204+
205+derive instance eqMonthDay :: Eq MonthDay
159206
160207instance formatComponentMonthDay :: FormatComponent MonthDay where
161− formatComponent = genericFormatComponent
208+ formatComponent (MonthDay { month, day }) = over FormatComponentRecord
209+ (\r -> r { month = Just (show month)
210+ , day = Just (show day)
211+ }
212+ ) defaultComponentRecord
162213
163214newtype HourMinuteSecond = HourMinuteSecond
164215 { hour :: NumericRep
@@ -166,17 +217,30 @@ newtype HourMinuteSecond = HourMinuteSecond
166217 , second :: NumericRep
167218 }
168219
169−derive instance genericHourMinuteSecond :: Generic HourMinuteSecond _
220+derive instance newtypeHourMinuteSecond :: Newtype HourMinuteSecond _
221+
222+derive instance eqHourMinuteSecond :: Eq HourMinuteSecond
170223
171224instance formatComponentHourMinuteSecond :: FormatComponent HourMinuteSecond where
172− formatComponent = genericFormatComponent
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
173231
174232newtype HourMinute = HourMinute
175233 { hour :: NumericRep
176234 , minute :: NumericRep
177235 }
178236
179−derive instance genericHourMinute :: Generic HourMinute _
237+derive instance newtypeHourMinute :: Newtype HourMinute _
238+
239+derive instance eqHourMinute :: Eq HourMinute
180240
181241instance formatComponentHourMinute :: FormatComponent HourMinute where
182− formatComponent = genericFormatComponent
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+3−2
@@ -12,7 +12,8 @@ import Data.Foldable (intercalate)
1212import Data.Foreign (F, renderForeignError)
1313import Data.Generic.Rep (class Generic)
1414import 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.Generic (class FormatComponent, genericFormatComponent)
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