git.iko.soy/purescript-intl
on master help sign in
Merge branch 'master' of github.com:coot/purescript-intl
ba43f6dMarcin Szamotulski
.travis.yml+4−1
@@ -4,6 +4,9 @@ sudo: required
4node_js: stable
4node_js: stable
5env:
5env:
6 - PATH=$HOME/purescript:$PATH
6 - PATH=$HOME/purescript:$PATH
7+cache:
8+ - directories:
9+ - $HOME/purescript
7install:
10install:
8 - TAG=$(wget -q -O - https://github.com/purescript/purescript/releases/latest --server-response --max-redirect 0 2>&1 | sed -n -e 's/.*Location:.*tag\///p')
11 - TAG=$(wget -q -O - https://github.com/purescript/purescript/releases/latest --server-response --max-redirect 0 2>&1 | sed -n -e 's/.*Location:.*tag\///p')
9 - wget -O $HOME/purescript.tar.gz https://github.com/purescript/purescript/releases/download/$TAG/linux64.tar.gz
12 - wget -O $HOME/purescript.tar.gz https://github.com/purescript/purescript/releases/download/$TAG/linux64.tar.gz
@@ -16,7 +19,7 @@ script:
16 - bower install --production
19 - bower install --production
17 - npm run -s build
20 - npm run -s build
18 - bower install
21 - bower install
19− - LC_TIME="en_GB.UTF-8" npm -s test
22+ - npm -s test
20after_success:
23after_success:
21- >-
24- >-
22 test $TRAVIS_TAG &&
25 test $TRAVIS_TAG &&
src/Data/Intl/DateTimeFormat.js+10
@@ -20,6 +20,12 @@ exports.formatJSDate = function(formatter) {
20 };
20 };
21};
21};
22
22
23+exports.formatToPartsImpl = function(formatter) {
24+ return function(date) {
25+ return formatter.formatToParts(date);
26+ };
27+};
28+
23exports.supportedLocalesOfImpl = function(Left, Right, locales) {
29exports.supportedLocalesOfImpl = function(Left, Right, locales) {
24 try {
30 try {
25 return Right(Intl.DateTimeFormat.supportedLocalesOf(locales))
31 return Right(Intl.DateTimeFormat.supportedLocalesOf(locales))
@@ -27,3 +33,7 @@ exports.supportedLocalesOfImpl = function(Left, Right, locales) {
27 return Left(e.message)
33 return Left(e.message)
28 }
34 }
29}
35}
36+
37+exports.resolvedOptionsImpl = function(formatter) {
38+ return formatter.resolvedOptions();
39+};
src/Data/Intl/DateTimeFormat.purs+40−2
@@ -20,21 +20,26 @@ module Data.Intl.DateTimeFormat
20 , formatJSDate
20 , formatJSDate
21 , module Data.Intl.DateTimeFormat.Types
21 , module Data.Intl.DateTimeFormat.Types
22 , supportedLocalesOf
22 , supportedLocalesOf
23+ , formatToParts
24+ , resolvedOptions
23 ) where
25 ) where
24
26
25import Data.Intl.DateTimeFormat.Types
27import Data.Intl.DateTimeFormat.Types
26
28
27import Data.Either (Either(..))
29import Data.Either (Either(..))
30+import Data.Foreign (F, Foreign, isUndefined, readString)
31+import Data.Foreign.Index ((!))
28import Data.Function.Uncurried (Fn3, runFn3)
32import Data.Function.Uncurried (Fn3, runFn3)
29import Data.Generic.Rep (class Generic)
33import Data.Generic.Rep (class Generic)
30import Data.Intl.DateTimeFormat.Generic (class FormatComponent, defaultComponentRecord, formatComponent, genericFormatComponent)
34import Data.Intl.DateTimeFormat.Generic (class FormatComponent, defaultComponentRecord, formatComponent, genericFormatComponent)
31import Data.JSDate (JSDate)
35import Data.JSDate (JSDate)
32−import Data.Maybe (Maybe, fromMaybe, maybe)
36+import Data.Maybe (Maybe(..), fromMaybe, maybe)
33import Data.Newtype (class Newtype)
37import Data.Newtype (class Newtype)
34import Data.StrMap (union)
38import Data.StrMap (union)
35import Data.Symbol (SProxy(..))
39import Data.Symbol (SProxy(..))
40+import Data.Traversable (sequence)
36import Data.Variant (Variant, default, on)
41import Data.Variant (Variant, default, on)
37−import Prelude (class Eq, class Show, Unit, id, show, (#), ($))
42+import Prelude (class Eq, class Show, Unit, bind, id, pure, show, (#), ($), (<$>), (>>=))
38import Unsafe.Coerce (unsafeCoerce)
43import Unsafe.Coerce (unsafeCoerce)
39
44
40foreign import data LocalesOption' :: Type
45foreign import data LocalesOption' :: Type
@@ -291,6 +296,39 @@ createDateTimeFormatter ls opts = createDateTimeFormatterImpl (toLocale ls) (for
291foreign import formatJSDate :: DateTimeFormatter -> JSDate -> String
296foreign import formatJSDate :: DateTimeFormatter -> JSDate -> String
292
297
293foreign import supportedLocalesOfImpl :: Fn3 (String -> Either String (Array String)) (Array String -> Either String (Array String)) (Array String) (Either String (Array String))
298foreign import supportedLocalesOfImpl :: Fn3 (String -> Either String (Array String)) (Array String -> Either String (Array String)) (Array String) (Either String (Array String))
299+
300+foreign import formatToPartsImpl :: DateTimeFormatter -> JSDate -> Array Foreign
301+
302+formatToParts :: DateTimeFormatter -> JSDate -> F (Array FormatParts)
303+formatToParts formatter date = sequence $ readFormatParts <$> formatToPartsImpl formatter date
294
304
295supportedLocalesOf :: Array String -> Either String (Array String)
305supportedLocalesOf :: Array String -> Either String (Array String)
296supportedLocalesOf locales = runFn3 supportedLocalesOfImpl Left Right locales
306supportedLocalesOf locales = runFn3 supportedLocalesOfImpl Left Right locales
307+
308+foreign import resolvedOptionsImpl :: DateTimeFormatter -> Foreign
309+
310+resolvedOptions :: DateTimeFormatter -> F ResolvedOptions
311+resolvedOptions fmt = do
312+ locale <- obj ! "locale" >>= readString
313+ calendar <- obj ! "calendar" >>= readString
314+ numberingSystem <- obj ! "numberingSystem" >>= readString
315+ timeZone <- obj ! "timeZone" >>= readString
316+ era <- obj ! "era" >>= readMaybeString
317+ weekday <- obj ! "weekday" >>= readMaybeString
318+ year <- obj ! "year" >>= readMaybeString
319+ day <- obj ! "day" >>= readMaybeString
320+ hour <- obj ! "hour" >>= readMaybeString
321+ minute <- obj ! "minute" >>= readMaybeString
322+ second <- obj ! "second" >>= readMaybeString
323+ timeZoneName <- obj ! "timeZoneName" >>= readMaybeString
324+
325+ pure $ ResolvedOptions { locale, calendar, numberingSystem, timeZone, era, weekday, year, day, hour, minute, second, timeZoneName }
326+
327+ where
328+ obj = resolvedOptionsImpl fmt
329+
330+ readMaybeString :: Foreign -> F (Maybe String)
331+ readMaybeString f =
332+ if isUndefined f
333+ then pure Nothing
334+ else Just <$> readString f
src/Data/Intl/DateTimeFormat/Types.purs+58−2
@@ -1,6 +1,18 @@
1−module Data.Intl.DateTimeFormat.Types where
1+module Data.Intl.DateTimeFormat.Types
2+ ( StringRep(..)
3+ , NumericRep(..)
4+ , MonthRep(..)
5+ , TimeZoneNameRep(..)
6+ , FormatParts(..)
7+ , readFormatParts
8+ , ResolvedOptions(..)
9+ ) where
2
10
11+import Data.Foreign (F, Foreign, ForeignError(..), fail, readString)
12+import Data.Foreign.Index ((!))
13+import Data.Maybe (Maybe)
14+import Data.Newtype (class Newtype)
3−import Prelude (class Show)
15+import Prelude (class Show, bind, pure, ($), (<>), (>>=))
4
16
5data StringRep = Narrow | Short | Long
17data StringRep = Narrow | Short | Long
6
18
@@ -30,3 +42,47 @@ instance showTimeZoneRep :: Show TimeZoneNameRep where
30 show TimeZoneNameShort = "short"
42 show TimeZoneNameShort = "short"
31 show TimeZoneNameLong = "long"
43 show TimeZoneNameLong = "long"
32
44
45+data FormatParts
46+ = Era String
47+ | Year String
48+ | Month String
49+ | Weekday String
50+ | Day String
51+ | Hour String
52+ | Minute String
53+ | DayPeriod String
54+ | Literal String
55+
56+readFormatParts :: Foreign -> F FormatParts
57+readFormatParts val = do
58+ type_ <- val ! "type" >>= readString
59+ value <- val ! "value" >>= readString
60+ case type_ of
61+ "era" -> pure $ Era value
62+ "year" -> pure $ Year value
63+ "month" -> pure $ Month value
64+ "weekday" -> pure $ Weekday value
65+ "month" -> pure $ Month value
66+ "day" -> pure $ Day value
67+ "hour" -> pure $ Hour value
68+ "minute" -> pure $ Minute value
69+ "dayperiod" -> pure $ DayPeriod value
70+ "literal" -> pure $ Literal value
71+ _ -> fail $ ForeignError ("type " <> type_ <> " is not supported by purescript-intl")
72+
73+newtype ResolvedOptions = ResolvedOptions
74+ { locale :: String
75+ , numberingSystem :: String
76+ , calendar :: String
77+ , timeZone :: String
78+ , era :: Maybe String
79+ , weekday :: Maybe String
80+ , year :: Maybe String
81+ , day :: Maybe String
82+ , hour :: Maybe String
83+ , minute :: Maybe String
84+ , second :: Maybe String
85+ , timeZoneName :: Maybe String
86+ }
87+
88+derive instance newtypeResolvedOptions :: Newtype ResolvedOptions _
test/Test/Main.purs+21−2
@@ -4,14 +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)
7import Data.DateTime (Date, DateTime(..), Month(..), canonicalDate)
8import Data.DateTime (Date, DateTime(..), Month(..), canonicalDate)
8import Data.Either (Either(..), isLeft)
9import Data.Either (Either(..), isLeft)
9import Data.Enum (toEnum)
10import Data.Enum (toEnum)
11+import Data.Foldable (intercalate)
12+import Data.Foreign (renderForeignError)
10import Data.Generic.Rep (class Generic)
13import Data.Generic.Rep (class Generic)
11−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, supportedLocalesOf)
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)
12import Data.Intl.DateTimeFormat.Generic (class FormatComponent, genericFormatComponent)
15import Data.Intl.DateTimeFormat.Generic (class FormatComponent, genericFormatComponent)
13import Data.JSDate (JSDate, fromDateTime)
16import Data.JSDate (JSDate, fromDateTime)
14−import Data.Maybe (Maybe(..))
17+import Data.Maybe (Maybe(..), isJust, isNothing)
15import Data.Symbol (SProxy(..))
18import Data.Symbol (SProxy(..))
16import Data.Time (Time(..))
19import Data.Time (Time(..))
17import Data.Variant (inj)
20import Data.Variant (inj)
@@ -301,3 +304,19 @@ main = do
301
304
302 let err = supportedLocalesOf ["en_US"]
305 let err = supportedLocalesOf ["en_US"]
303 assert' ("supportedLocalesOf got: " <> show err) $ isLeft err
306 assert' ("supportedLocalesOf got: " <> show err) $ isLeft err
307+
308+ -- formatToParts is not supported in node
309+ -- let parts = runExcept $ formatToParts fmtHourMinute d
310+ -- assert' ("") $ isRight parts
311+
312+ case runExcept (resolvedOptions fmtHourMinuteSecond) of
313+ Left errs-> assert' ("resolvedOptions error: " <> (intercalate "; " $ renderForeignError <$> errs)) false
314+ Right (ResolvedOptions {locale, year, day, weekday, hour, minute, second}) -> do
315+ assert' ("resolvedOptions locale: got: " <> locale) $ (locale == "en-US") || (locale == "en")
316+ assert' ("resolvedOptions year: got Just") $ isNothing year
317+ assert' ("resolvedOptions day: got Just") $ isNothing day
318+ assert' ("resolvedOptions weekday: got Just") $ isNothing weekday
319+ assert' ("resolvedOptions hour: got Nothing") $ isJust hour
320+ assert' ("resolvedOptions minute: got Nothing") $ isJust minute
321+ assert' ("resolvedOptions second: got Nothing") $ isJust second
322+