@@ -1,22 +1,13 @@
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(..)
11− , HourMinuteSecond(..)
15 , DateTimeFormatOptions(..)
6 , DateTimeFormatOptions(..)
16 , DateTimeFormatOptions'
7 , DateTimeFormatOptions'
17 , DateTimeComponents(..)
8 , DateTimeComponents(..)
18− , DateTimeFormatter
9+ , DateTimeFormat
19− , createDateTimeFormatter
10+ , createDateTimeFormat
20 , formatJSDate
11 , formatJSDate
21 , module Data.Intl.DateTimeFormat.Types
12 , module Data.Intl.DateTimeFormat.Types
22 , supportedLocalesOf
13 , supportedLocalesOf
@@ -31,23 +22,18 @@ import Data.Either (Either(..))
31import Data.Foreign (F, Foreign, ForeignError(..), isUndefined, readString)
22import Data.Foreign (F, Foreign, ForeignError(..), isUndefined, readString)
32import Data.Foreign.Index ((!))
23import Data.Foreign.Index ((!))
33import Data.Function.Uncurried (Fn3, Fn4, runFn3, runFn4)
24import Data.Function.Uncurried (Fn3, Fn4, runFn3, runFn4)
34−import Data.Generic.Rep (class Generic)
35−import Data.Intl.DateTimeFormat.Generic (class FormatComponent, defaultComponentRecord, formatComponent, genericFormatComponent)
25+import Data.Intl.DateTimeFormat.Class (class FormatComponent, FormatComponentRecord(FormatComponentRecord), formatComponent)
36import Data.JSDate (JSDate)
26import Data.JSDate (JSDate)
37import Data.Maybe (Maybe(..), fromMaybe, maybe)
27import Data.Maybe (Maybe(..), fromMaybe, maybe)
38−import Data.Newtype (class Newtype)
28+import Data.Newtype (class Newtype, un)
39import Data.StrMap (union)
29import Data.StrMap (union)
40import Data.Symbol (SProxy(..))
30import Data.Symbol (SProxy(..))
41import Data.Traversable (sequence)
31import Data.Traversable (sequence)
42−import Data.Variant (Variant, default, on)
32+import Data.Variant (Variant, case_, default, on)
43import Prelude (class Eq, class Show, Unit, bind, id, pure, show, (#), ($), (<$>), (<<<), (>>=))
33import Prelude (class Eq, class Show, Unit, bind, id, pure, show, (#), ($), (<$>), (<<<), (>>=))
44import Unsafe.Coerce (unsafeCoerce)
34import Unsafe.Coerce (unsafeCoerce)
46foreign import data LocalesOption' :: Type
36foreign import data LocalesOption' :: Type
47−foreign import data DateTimeFormat :: Type
49−foreign import data Undefined :: Type
50−foreign import undefined :: Undefined
52foreign import dateTimeFormatImpl :: LocalesOption' -> DateTimeFormatOptions_ -> DateTimeFormat
38foreign import dateTimeFormatImpl :: LocalesOption' -> DateTimeFormatOptions_ -> DateTimeFormat
@@ -100,85 +86,6 @@ instance showFormatMatcher :: Show FormatMatcher where
100 show FMBasic = "basic"
86 show FMBasic = "basic"
101 show FMBestFit = "best fit"
87 show FMBestFit = "best fit"
103−newtype WeekdayYearMonthDayHourMinuteSecond = WeekdayYearMonthDayHourMinuteSecond
104− { weekday :: StringRep
105− , year :: NumericRep
108− , hour :: NumericRep
109− , minute :: NumericRep
110− , second :: NumericRep
113−derive instance genericWeekdayYearMonthDayHourMinuteSecond :: Generic WeekdayYearMonthDayHourMinuteSecond _
115−instance formatComponentWeekdayYearMonthDayHourMinuteSecond :: FormatComponent WeekdayYearMonthDayHourMinuteSecond where
116− formatComponent = genericFormatComponent
118−newtype WeekdayYearMonthDay = WeekdayYearMonthDay
119− { weekday :: StringRep
120− , year :: NumericRep
125−derive instance genericWeekdayYearMonthDay :: Generic WeekdayYearMonthDay _
127−instance formatComponentWeekdayYearMonthDay :: FormatComponent WeekdayYearMonthDay where
128− formatComponent = genericFormatComponent
130−newtype YearMonthDay = YearMonthDay
131− { year :: NumericRep
136−derive instance genericYearMonthDay :: Generic YearMonthDay _
138−instance formatComponentYearMonthDay :: FormatComponent YearMonthDay where
139− formatComponent = genericFormatComponent
141−newtype YearMonth = YearMonth
142− { year :: NumericRep
146−derive instance genericYearMonth :: Generic YearMonth _
148−instance formatComponentYearMonth :: FormatComponent YearMonth where
149− formatComponent = genericFormatComponent
151−newtype MonthDay = MonthDay
156−derive instance genericMonthDay :: Generic MonthDay _
158−instance formatComponentMonthDay :: FormatComponent MonthDay where
159− formatComponent = genericFormatComponent
161−newtype HourMinuteSecond = HourMinuteSecond
162− { hour :: NumericRep
163− , minute :: NumericRep
164− , second :: NumericRep
167−derive instance genericHourMinuteSecond :: Generic HourMinuteSecond _
169−instance formatComponentHourMinuteSecond :: FormatComponent HourMinuteSecond where
170− formatComponent = genericFormatComponent
172−newtype HourMinute = HourMinute
173− { hour :: NumericRep
174− , minute :: NumericRep
177−derive instance genericHourMinute :: Generic HourMinute _
179−instance formatComponentHourMinute :: FormatComponent HourMinute where
180− formatComponent = genericFormatComponent
182type DateTimeComponents a =
89type DateTimeComponents a =
184 ( weekdayYearMonthDayHourMinuteSecond :: WeekdayYearMonthDayHourMinuteSecond
91 ( weekdayYearMonthDayHourMinuteSecond :: WeekdayYearMonthDayHourMinuteSecond
@@ -213,7 +120,7 @@ formatDateTimeOptions (DateTimeFormatOptions opts comps) = merge opts' (compsCoe
213 , hour12: fromMaybe (unsafeCoerce undefined) opts.hour12
120 , hour12: fromMaybe (unsafeCoerce undefined) opts.hour12
214 , formatMatcher: maybe undefinedString show opts.formatMatcher
121 , formatMatcher: maybe undefinedString show opts.formatMatcher
216− comps' = default (defaultComponentRecord)
123+ comps' = un FormatComponentRecord $ case_
217 # on (SProxy :: SProxy "weekdayYearMonthDayHourMinuteSecond") formatComponent
124 # on (SProxy :: SProxy "weekdayYearMonthDayHourMinuteSecond") formatComponent
218 # on (SProxy :: SProxy "weekdayYearMonthDay") formatComponent
125 # on (SProxy :: SProxy "weekdayYearMonthDay") formatComponent
219 # on (SProxy :: SProxy "yearMonthDay") formatComponent
126 # on (SProxy :: SProxy "yearMonthDay") formatComponent
@@ -279,30 +186,118 @@ formatDateTimeOptions (DateTimeFormatOptions opts comps) = merge opts' (compsCoe
279 -> DateTimeFormatOptions_
186 -> DateTimeFormatOptions_
280 merge a b = unsafeCoerce $ union (unsafeCoerce a) (unsafeCoerce b)
187 merge a b = unsafeCoerce $ union (unsafeCoerce a) (unsafeCoerce b)
282−foreign import data DateTimeFormatter :: Type
189+foreign import data DateTimeFormat :: Type
284−foreign import createDateTimeFormatterImpl
191+foreign import createDateTimeFormatImpl
286 (forall a. String -> F a)
193 (forall a. String -> F a)
287 (forall a. a -> F a)
194 (forall a. a -> F a)
288 LocalesOption'
195 LocalesOption'
289 DateTimeFormatOptions_
196 DateTimeFormatOptions_
290− (F DateTimeFormatter)
197+ (F DateTimeFormat)
292−createDateTimeFormatter
199+-- | Examples
201+-- | import Data.Variant (inj)
203+-- | fmtHourMinute = F DateTimeFormat
204+-- | fmtHourMinute = createDateTimeFormat locale opts
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
213+-- | (inj (SProxy :: SProxy "hourMinute")
214+-- | (HourMinute {hour: TwoDigit, minute: TwoDigit}))
217+-- | fmtDate :: F DateTimeFormat
218+-- | fmtDate = createDateTimeFormat locale opts
220+-- | locale = inj (SProxy :: SProxy "locale") "en-GB"
221+-- | opts :: DateTimeFormatOptions'
223+-- | (DateTimeFormatOptions
224+-- | { localeMatcher: Nothing
225+-- | , timeZone: (Just (TimeZone "Europe/London"))
226+-- | , hour12: Just true
227+-- | , formatMatcher: Nothing
230+-- | (SProxy :: SProxy "weekdayYearMonthDayHourMinuteSecond")
231+-- | (WeekdayYearMonthDayHourMinuteSecond
232+-- | { weekday: Short
234+-- | , month: MonthLong
237+-- | , minute: Numeric
238+-- | , second: Numeric
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.
249+-- | newtype EraYear = EraYear
250+-- | { era :: StringRep
251+-- | , year :: NumericRep
254+-- | derive instance genericEraYear :: Generic EraYear _
256+-- | instance formatComponentEraYear :: FormatComponent EraYear where
257+-- | formatComponent = genericFormatComponent
259+-- | fmtEraYear :: F DateTimeFormat
260+-- | fmtEraYear = createDateTimeFormat locales opts
262+-- | locale = inj (SProxy :: SProxy "locale") "en-GB"
263+-- | opts :: DateTimeFormatOptions EraYear
265+-- | (DateTimeFormatOptions
266+-- | { localeMatcher: Nothing
267+-- | , timeZone: (Just (TimeZone "Europe/London"))
268+-- | , hour12: Just true
269+-- | , formatMatcher: Nothing
272+-- | (SProxy :: SProxy "custom")
293 :: forall a
282 :: forall a
294 .(FormatComponent a)
283 .(FormatComponent a)
295 => LocalesOption
284 => LocalesOption
296 -> DateTimeFormatOptions a
285 -> DateTimeFormatOptions a
297− -> F DateTimeFormatter
286+ -> F DateTimeFormat
298−createDateTimeFormatter ls opts =
287+createDateTimeFormat ls opts =
299− runFn4 createDateTimeFormatterImpl
288+ runFn4 createDateTimeFormatImpl
300 (throwError <<< pure <<< ForeignError)
289 (throwError <<< pure <<< ForeignError)
302 (toLocale ls)
291 (toLocale ls)
303 (formatDateTimeOptions opts)
292 (formatDateTimeOptions opts)
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"
305−foreign import formatJSDate :: DateTimeFormatter -> JSDate -> String
300+foreign import formatJSDate :: DateTimeFormat -> JSDate -> String
307foreign import supportedLocalesOfImpl
302foreign import supportedLocalesOfImpl
@@ -310,18 +305,18 @@ foreign import supportedLocalesOfImpl
310 (Array String -> Either String (Array String))
305 (Array String -> Either String (Array String))
311 (Array String)
306 (Array String)
312 (Either String (Array String))
307 (Either String (Array String))
314−foreign import formatToPartsImpl :: DateTimeFormatter -> JSDate -> Array Foreign
309+foreign import formatToPartsImpl :: DateTimeFormat -> JSDate -> Array Foreign
316−formatToParts :: DateTimeFormatter -> JSDate -> F (Array FormatParts)
311+formatToParts :: DateTimeFormat -> JSDate -> F (Array FormatParts)
317formatToParts formatter date = sequence $ readFormatParts <$> formatToPartsImpl formatter date
312formatToParts formatter date = sequence $ readFormatParts <$> formatToPartsImpl formatter date
319supportedLocalesOf :: Array String -> Either String (Array String)
314supportedLocalesOf :: Array String -> Either String (Array String)
320supportedLocalesOf locales = runFn3 supportedLocalesOfImpl Left Right locales
315supportedLocalesOf locales = runFn3 supportedLocalesOfImpl Left Right locales
322−foreign import resolvedOptionsImpl :: DateTimeFormatter -> Foreign
317+foreign import resolvedOptionsImpl :: DateTimeFormat -> Foreign
324−resolvedOptions :: DateTimeFormatter -> F ResolvedOptions
319+resolvedOptions :: DateTimeFormat -> F ResolvedOptions
325resolvedOptions fmt = do
320resolvedOptions fmt = do
326 locale <- obj ! "locale" >>= readString
321 locale <- obj ! "locale" >>= readString
327 calendar <- obj ! "calendar" >>= readString
322 calendar <- obj ! "calendar" >>= readString