en_CA + fix Canadian Thanksgiving

Summary:
* `en_CA` locale
* In Canada, Thanksgiving Day is the second Monday of October.
* Black Friday is the same as the US.
* However Canada observes both DDMM and MMDD formats. Defer to later, falling back to US.

Reviewed By: blandinw

Differential Revision: D6058909

fbshipit-source-id: 3d4e05e
This commit is contained in:
Julien Odent 2017-10-16 09:43:53 -07:00 committed by Facebook Github Bot
parent fb1dcaa138
commit 1ab5f447d2
16 changed files with 2580 additions and 76 deletions

View File

@ -69,7 +69,8 @@ instance TextShow Lang where
-- | ISO 3166-1 alpha-2 Country code (includes regions and territories).
-- See https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
data Region
= CN
= CA
| CN
| GB
| HK
| MO
@ -100,6 +101,6 @@ makeLocale lang (Just region)
allLocales :: HashMap Lang (HashSet Region)
allLocales = HashMap.fromList
[ (EN, HashSet.fromList [GB, US])
[ (EN, HashSet.fromList [CA, GB, US])
, (ZH, HashSet.fromList [CN, HK, MO, TW])
]

File diff suppressed because it is too large Load Diff

View File

@ -29,6 +29,7 @@ import qualified Duckling.Ordinal.EN.Rules as Ordinal
import qualified Duckling.Quantity.EN.Rules as Quantity
import qualified Duckling.Temperature.EN.Rules as Temperature
import qualified Duckling.Time.EN.Rules as Time
import qualified Duckling.Time.EN.CA.Rules as TimeCA
import qualified Duckling.Time.EN.GB.Rules as TimeGB
import qualified Duckling.Time.EN.US.Rules as TimeUS
import qualified Duckling.TimeGrain.EN.Rules as TimeGrain
@ -38,10 +39,12 @@ defaultRules :: Some Dimension -> [Rule]
defaultRules dim@(This Time) =
[ TimeUS.ruleMMDD
, TimeUS.ruleMMDDYYYY
, TimeUS.ruleThanksgiving
] ++ langRules dim
defaultRules dim = langRules dim
localeRules :: Region -> Some Dimension -> [Rule]
localeRules CA (This Time) = TimeCA.rules
localeRules GB (This Time) = TimeGB.rules
localeRules US (This Time) = TimeUS.rules
localeRules _ _ = []

View File

@ -0,0 +1,60 @@
-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree. An additional grant
-- of patent rights can be found in the PATENTS file in the same directory.
{-# LANGUAGE OverloadedStrings #-}
module Duckling.Time.EN.CA.Corpus
( allExamples
) where
import Data.String
import Prelude
import Duckling.Testing.Types hiding (examples)
import Duckling.Time.Corpus
import Duckling.Time.Types hiding (Month)
import Duckling.TimeGrain.Types hiding (add)
allExamples :: [Example]
allExamples = concat
[ examples (datetime (2013, 2, 15, 0, 0, 0) Day)
[ "2/15"
, "on 2/15"
, "2 / 15"
, "2-15"
, "2 - 15"
]
, examples (datetime (1974, 10, 31, 0, 0, 0) Day)
[ "10/31/1974"
, "10/31/74"
, "10-31-74"
]
, examples (datetime (2013, 4, 25, 16, 0, 0) Minute)
[ "4/25 at 4:00pm"
]
, examples (datetime (2013, 10, 14, 0, 0, 0) Day)
[ "thanksgiving day"
, "thanksgiving"
, "thanksgiving 2013"
, "this thanksgiving"
, "next thanksgiving day"
]
, examples (datetime (2014, 10, 13, 0, 0, 0) Day)
[ "thanksgiving of next year"
, "thanksgiving 2014"
]
, examples (datetime (2012, 10, 8, 0, 0, 0) Day)
[ "last thanksgiving"
, "thanksgiving day 2012"
]
, examples (datetime (2016, 10, 10, 0, 0, 0) Day)
[ "thanksgiving 2016"
]
, examples (datetime (2017, 10, 9, 0, 0, 0) Day)
[ "thanksgiving 2017"
]
]

View File

@ -0,0 +1,69 @@
-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree. An additional grant
-- of patent rights can be found in the PATENTS file in the same directory.
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoRebindableSyntax #-}
{-# LANGUAGE OverloadedStrings #-}
module Duckling.Time.EN.CA.Rules
( rules
) where
import Data.Maybe
import Prelude
import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Regex.Types
import Duckling.Time.Helpers
import Duckling.Time.Types (TimeData (..))
import Duckling.Types
-- Although one can see both MMDD and DDMM in Canada,
-- there is no direct way to implement this today. Let's fallback to MMDD (US).
ruleMMDD :: Rule
ruleMMDD = Rule
{ name = "mm/dd"
, pattern = [regex "(0?[1-9]|1[0-2])\\s?[/-]\\s?(3[01]|[12]\\d|0?[1-9])"]
, prod = \tokens -> case tokens of
(Token RegexMatch (GroupMatch (mm:dd:_)):_) -> do
m <- parseInt mm
d <- parseInt dd
tt $ monthDay m d
_ -> Nothing
}
ruleMMDDYYYY :: Rule
ruleMMDDYYYY = Rule
{ name = "mm/dd/yyyy"
, pattern =
[regex "(0?[1-9]|1[0-2])[/-](3[01]|[12]\\d|0?[1-9])[-/](\\d{2,4})"]
, prod = \tokens -> case tokens of
(Token RegexMatch (GroupMatch (mm:dd:yy:_)):_) -> do
y <- parseInt yy
m <- parseInt mm
d <- parseInt dd
tt $ yearMonthDay y m d
_ -> Nothing
}
ruleThanksgiving :: Rule
ruleThanksgiving = Rule
{ name = "Thanksgiving Day"
, pattern =
[ regex "thanks?giving( day)?"
]
, prod = \_ -> tt $ nthDOWOfMonth 2 1 10 -- Second Monday of October
}
rules :: [Rule]
rules =
[ ruleMMDD
, ruleMMDDYYYY
, ruleThanksgiving
]

View File

@ -44,6 +44,27 @@ defaultCorpus = (testContext, allExamples ++ custom)
, examples (datetime (2013, 4, 25, 16, 0, 0) Minute)
[ "4/25 at 4:00pm"
]
, examples (datetime (2013, 11, 28, 0, 0, 0) Day)
[ "thanksgiving day"
, "thanksgiving"
, "thanksgiving 2013"
, "this thanksgiving"
, "next thanksgiving day"
]
, examples (datetime (2014, 11, 27, 0, 0, 0) Day)
[ "thanksgiving of next year"
, "thanksgiving 2014"
]
, examples (datetime (2012, 11, 22, 0, 0, 0) Day)
[ "last thanksgiving"
, "thanksgiving day 2012"
]
, examples (datetime (2016, 11, 24, 0, 0, 0) Day)
[ "thanksgiving 2016"
]
, examples (datetime (2017, 11, 23, 0, 0, 0) Day)
[ "thanksgiving 2017"
]
]
negativeCorpus :: NegativeCorpus
@ -613,27 +634,6 @@ allExamples = concat
, "next halloween"
, "Halloween 2013"
]
, examples (datetime (2013, 11, 28, 0, 0, 0) Day)
[ "thanksgiving day"
, "thanksgiving"
, "thanksgiving 2013"
, "this thanksgiving"
, "next thanksgiving day"
]
, examples (datetime (2014, 11, 27, 0, 0, 0) Day)
[ "thanksgiving of next year"
, "thanksgiving 2014"
]
, examples (datetime (2012, 11, 22, 0, 0, 0) Day)
[ "last thanksgiving"
, "thanksgiving day 2012"
]
, examples (datetime (2016, 11, 24, 0, 0, 0) Day)
[ "thanksgiving 2016"
]
, examples (datetime (2017, 11, 23, 0, 0, 0) Day)
[ "thanksgiving 2017"
]
, examples (datetime (2013, 11, 29, 0, 0, 0) Day)
[ "black friday"
, "black friday of this year"

View File

@ -36,4 +36,25 @@ allExamples = concat
, examples (datetime (2013, 4, 25, 16, 0, 0) Minute)
[ "25/4 at 4:00pm"
]
, examples (datetime (2013, 11, 28, 0, 0, 0) Day)
[ "thanksgiving day"
, "thanksgiving"
, "thanksgiving 2013"
, "this thanksgiving"
, "next thanksgiving day"
]
, examples (datetime (2014, 11, 27, 0, 0, 0) Day)
[ "thanksgiving of next year"
, "thanksgiving 2014"
]
, examples (datetime (2012, 11, 22, 0, 0, 0) Day)
[ "last thanksgiving"
, "thanksgiving day 2012"
]
, examples (datetime (2016, 11, 24, 0, 0, 0) Day)
[ "thanksgiving 2016"
]
, examples (datetime (2017, 11, 23, 0, 0, 0) Day)
[ "thanksgiving 2017"
]
]

View File

@ -53,8 +53,18 @@ ruleDDMMYYYY = Rule
_ -> Nothing
}
ruleThanksgiving :: Rule
ruleThanksgiving = Rule
{ name = "Thanksgiving Day"
, pattern =
[ regex "thanks?giving( day)?"
]
, prod = \_ -> tt $ nthDOWOfMonth 4 4 11 -- Fourth Thursday of November
}
rules :: [Rule]
rules =
[ ruleDDMM
, ruleDDMMYYYY
, ruleThanksgiving
]

View File

@ -1264,10 +1264,6 @@ moreUSHolidays =
, "mother'?s?'? day"
, 2, 7, 5
)
, ( "Thanksgiving Day" -- Fourth Thursday of November
, "thanks?giving( day)?"
, 4, 4, 11
)
, ( "Labor Day" -- First Monday of September
, "labor day"
, 1, 1, 9

View File

@ -36,4 +36,25 @@ allExamples = concat
, examples (datetime (2013, 4, 25, 16, 0, 0) Minute)
[ "4/25 at 4:00pm"
]
, examples (datetime (2013, 11, 28, 0, 0, 0) Day)
[ "thanksgiving day"
, "thanksgiving"
, "thanksgiving 2013"
, "this thanksgiving"
, "next thanksgiving day"
]
, examples (datetime (2014, 11, 27, 0, 0, 0) Day)
[ "thanksgiving of next year"
, "thanksgiving 2014"
]
, examples (datetime (2012, 11, 22, 0, 0, 0) Day)
[ "last thanksgiving"
, "thanksgiving day 2012"
]
, examples (datetime (2016, 11, 24, 0, 0, 0) Day)
[ "thanksgiving 2016"
]
, examples (datetime (2017, 11, 23, 0, 0, 0) Day)
[ "thanksgiving 2017"
]
]

View File

@ -14,6 +14,7 @@ module Duckling.Time.EN.US.Rules
( rules
, ruleMMDD
, ruleMMDDYYYY
, ruleThanksgiving
) where
import Data.Maybe
@ -52,8 +53,18 @@ ruleMMDDYYYY = Rule
_ -> Nothing
}
ruleThanksgiving :: Rule
ruleThanksgiving = Rule
{ name = "Thanksgiving Day"
, pattern =
[ regex "thanks?giving( day)?"
]
, prod = \_ -> tt $ nthDOWOfMonth 4 4 11 -- Fourth Thursday of November
}
rules :: [Rule]
rules =
[ ruleMMDD
, ruleMMDDYYYY
, ruleThanksgiving
]

View File

@ -82,6 +82,7 @@ library
, Duckling.Ranking.Classifiers.CS_XX
, Duckling.Ranking.Classifiers.DA_XX
, Duckling.Ranking.Classifiers.DE_XX
, Duckling.Ranking.Classifiers.EN_CA
, Duckling.Ranking.Classifiers.EN_GB
, Duckling.Ranking.Classifiers.EN_US
, Duckling.Ranking.Classifiers.EN_XX
@ -436,6 +437,8 @@ library
, Duckling.Time.DE.Rules
, Duckling.Time.EN.Corpus
, Duckling.Time.EN.Rules
, Duckling.Time.EN.CA.Corpus
, Duckling.Time.EN.CA.Rules
, Duckling.Time.EN.GB.Corpus
, Duckling.Time.EN.GB.Rules
, Duckling.Time.EN.US.Corpus

View File

@ -30,6 +30,7 @@ import Duckling.Testing.Types
import qualified Duckling.Time.DA.Corpus as DATime
import qualified Duckling.Time.DE.Corpus as DETime
import qualified Duckling.Time.EN.Corpus as ENTime
import qualified Duckling.Time.EN.CA.Corpus as EN_CATime
import qualified Duckling.Time.EN.GB.Corpus as EN_GBTime
import qualified Duckling.Time.EN.US.Corpus as EN_USTime
import qualified Duckling.Time.ES.Corpus as ESTime
@ -188,6 +189,7 @@ getCorpusForLang VI = VITime.corpus
getCorpusForLang ZH = ZHTime.corpus
getExamplesForLocale :: Lang -> Region -> [Example]
getExamplesForLocale EN CA = EN_CATime.allExamples
getExamplesForLocale EN GB = EN_GBTime.allExamples
getExamplesForLocale EN US = EN_USTime.allExamples
getExamplesForLocale ZH CN = ZH_CNTime.allExamples

View File

@ -1,24 +0,0 @@
-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree. An additional grant
-- of patent rights can be found in the PATENTS file in the same directory.
module Duckling.Time.EN.GB.Tests
( tests
) where
import Data.String
import Prelude
import Test.Tasty
import Duckling.Dimensions.Types
import Duckling.Time.EN.GB.Corpus
import Duckling.Testing.Asserts
tests :: TestTree
tests = testGroup "EN_GB Tests"
[ makeCorpusTest [This Time] corpus
]

View File

@ -29,6 +29,7 @@ import Duckling.Testing.Types hiding (examples)
import Duckling.Time.Corpus
import Duckling.Time.EN.Corpus
import Duckling.TimeGrain.Types (Grain(..))
import qualified Duckling.Time.EN.CA.Corpus as CA
import qualified Duckling.Time.EN.GB.Corpus as GB
import qualified Duckling.Time.EN.US.Corpus as US
@ -44,7 +45,11 @@ tests = testGroup "EN Tests"
localeTests :: TestTree
localeTests = testGroup "Locale Tests"
[ testGroup "EN_GB Tests"
[ testGroup "EN_CA Tests"
[ makeCorpusTest [This Time] $ withLocale corpus localeCA CA.allExamples
, makeNegativeCorpusTest [This Time] $ withLocale negativeCorpus localeCA []
]
, testGroup "EN_GB Tests"
[ makeCorpusTest [This Time] $ withLocale corpus localeGB GB.allExamples
, makeNegativeCorpusTest [This Time] $ withLocale negativeCorpus localeGB []
]
@ -54,6 +59,7 @@ localeTests = testGroup "Locale Tests"
]
]
where
localeCA = makeLocale EN $ Just CA
localeGB = makeLocale EN $ Just GB
localeUS = makeLocale EN $ Just US

View File

@ -1,24 +0,0 @@
-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree. An additional grant
-- of patent rights can be found in the PATENTS file in the same directory.
module Duckling.Time.EN.US.Tests
( tests
) where
import Data.String
import Prelude
import Test.Tasty
import Duckling.Dimensions.Types
import Duckling.Time.EN.US.Corpus
import Duckling.Testing.Asserts
tests :: TestTree
tests = testGroup "EN_US Tests"
[ makeCorpusTest [This Time] corpus
]