-- 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.


{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE NoRebindableSyntax #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Time.EN.Rules where

import Control.Applicative ((<|>))
import Control.Monad (guard)
import Data.Maybe
import Prelude
import qualified Data.Text as Text

import Duckling.Dimensions.Types
import Duckling.Duration.Helpers (duration, isGrain)
import Duckling.Duration.Types (DurationData (..))
import Duckling.Numeral.Helpers (isNatural, parseInt)
import Duckling.Numeral.Types (NumeralData (..))
import Duckling.Ordinal.Types (OrdinalData (..))
import Duckling.Regex.Types
import Duckling.Time.Computed
import Duckling.Time.Helpers
import Duckling.Time.HolidayHelpers
import Duckling.Time.Types (TimeData (..), TimeIntervalType (..))
import Duckling.Types
import qualified Duckling.Duration.Types as TDuration
import qualified Duckling.Numeral.Types as TNumeral
import qualified Duckling.Ordinal.Types as TOrdinal
import qualified Duckling.Time.Types as TTime
import qualified Duckling.TimeGrain.Types as TG

ruleIntersect :: Rule
ruleIntersect :: Rule
ruleIntersect = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"intersect"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrainFinerThan Grain
TG.Year
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ([Bool] -> Bool) -> (Token -> [Bool]) -> Predicate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Predicate] -> Token -> [Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Predicate
isNotLatent, Grain -> Predicate
isGrainOfTime Grain
TG.Year]
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td1:Token Dimension a
Time a
td2:[Token]
_)
        | Bool -> Bool
not (TimeData -> Bool
TTime.latent a
TimeData
td1) Bool -> Bool -> Bool
|| Bool -> Bool
not (TimeData -> Bool
TTime.latent a
TimeData
td2) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> (TimeData -> TimeData) -> TimeData -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
notLatent (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntersectOf :: Rule
ruleIntersectOf :: Rule
ruleIntersectOf = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"intersect by \",\", \"of\", \"from\", \"'s\""
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isNotLatent
    , String -> PatternItem
regex String
"of|from|for|'s|,"
    , Predicate -> PatternItem
Predicate Predicate
isNotLatent
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> (TimeData -> TimeData) -> TimeData -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
notLatent (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntersectYear :: Rule
ruleIntersectYear :: Rule
ruleIntersectYear = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"intersect by \",\", \"of\", \"from\" for year"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isNotLatent
    , String -> PatternItem
regex String
"of|from|,"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrainOfTime Grain
TG.Year
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> (TimeData -> TimeData) -> TimeData -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
notLatent (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleAbsorbOnDay :: Rule
ruleAbsorbOnDay :: Rule
ruleAbsorbOnDay = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"on <day>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"on"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrainOfTime Grain
TG.Day
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token
token:[Token]
_) -> Token -> Maybe Token
forall a. a -> Maybe a
Just Token
token
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleAbsorbOnADOW :: Rule
ruleAbsorbOnADOW :: Rule
ruleAbsorbOnADOW = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"on a <named-day>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"on a"
    , Predicate -> PatternItem
Predicate Predicate
isADayOfWeek
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token
token:[Token]
_) -> Token -> Maybe Token
forall a. a -> Maybe a
Just Token
token
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleAbsorbInMonthYear :: Rule
ruleAbsorbInMonthYear :: Rule
ruleAbsorbInMonthYear = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"in|during <named-month>|year"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"in|during"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ([Bool] -> Bool) -> (Token -> [Bool]) -> Predicate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Predicate] -> Token -> [Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Predicate
isAMonth, Grain -> Predicate
isGrainOfTime Grain
TG.Year]
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
notLatent a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleAbsorbCommaTOD :: Rule
ruleAbsorbCommaTOD :: Rule
ruleAbsorbCommaTOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"absorption of , after named day"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isADayOfWeek
    , String -> PatternItem
regex String
","
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:[Token]
_) -> Token -> Maybe Token
forall a. a -> Maybe a
Just Token
token
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleInstants :: [Rule]
ruleInstants :: [Rule]
ruleInstants = [(Text, Grain, Int, String)] -> [Rule]
mkRuleInstants
  [ (Text
"right now"    , Grain
TG.Second, Int
0  , String
"((just|right)\\s*)now|immediately")
  , (Text
"today"        , Grain
TG.Day   , Int
0  , String
"todays?|(at this time)"           )
  , (Text
"tomorrow"     , Grain
TG.Day   , Int
1  , String
"(tmrw?|tomm?or?rows?)"            )
  , (Text
"yesterday"    , Grain
TG.Day   , - Int
1, String
"yesterdays?"                      )
  ]

ruleNow :: Rule
ruleNow :: Rule
ruleNow = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"now"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"now|at\\sthe\\smoment|atm"
    ]
  , prod :: Production
prod = \[Token]
_ -> TimeData -> Maybe Token
tt TimeData
now
  }

ruleASAP :: Rule
ruleASAP :: Rule
ruleASAP = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"as soon as possible"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"asap|as\\ssoon\\sas\\spossible"
    ]
  , prod :: Production
prod = \[Token]
_ -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ IntervalDirection -> TimeData -> TimeData
withDirection IntervalDirection
TTime.After TimeData
now
  }

ruleNextDOW :: Rule
ruleNextDOW :: Rule
ruleNextDOW = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"this|next <day-of-week>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(this|next)"
    , Predicate -> PatternItem
Predicate Predicate
isADayOfWeek
    ]
  , prod :: Production
prod = \case
      (
        Token Dimension a
RegexMatch (GroupMatch (match:_)):
        Token Dimension a
Time a
dow:
        [Token]
_) -> do
          TimeData
td <- case Text -> Text
Text.toLower Text
match of
                  Text
"this" -> TimeData -> Maybe TimeData
forall a. a -> Maybe a
Just (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> Bool -> TimeData -> TimeData
predNth Int
0 Bool
True a
TimeData
dow
                  Text
"next" -> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
dow (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth Grain
TG.Week Int
1
                  Text
_ -> Maybe TimeData
forall a. Maybe a
Nothing
          TimeData -> Maybe Token
tt TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleThisTime :: Rule
ruleThisTime :: Rule
ruleThisTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"this <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"this|current|coming"
    , Predicate -> PatternItem
Predicate Predicate
isOkWithThisNext
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> Bool -> TimeData -> TimeData
predNth Int
0 Bool
False a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleNextTime :: Rule
ruleNextTime :: Rule
ruleNextTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"next <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"next"
    , Predicate -> PatternItem
Predicate Predicate
isOkWithThisNext
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> Bool -> TimeData -> TimeData
predNth Int
0 Bool
True a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleLastTime :: Rule
ruleLastTime :: Rule
ruleLastTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"last <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(this past|last|previous)"
    , Predicate -> PatternItem
Predicate Predicate
isOkWithThisNext
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> Bool -> TimeData -> TimeData
predNth (- Int
1) Bool
False a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleLastWeekendOfMonth :: Rule
ruleLastWeekendOfMonth :: Rule
ruleLastWeekendOfMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"last weekend of <named-month>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"last\\s(week(\\s|-)?end|wkend)\\s(of|in)"
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td2:[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData -> TimeData
predLastOf TimeData
weekend a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTimeBeforeLastAfterNext :: Rule
ruleTimeBeforeLastAfterNext :: Rule
ruleTimeBeforeLastAfterNext = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<time> before last|after next"
  , pattern :: Pattern
pattern =
    [ Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    , String -> PatternItem
regex String
"(before last|after next)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td:Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_) ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> Bool -> TimeData -> TimeData
predNth Int
1 (Text -> Text
Text.toLower Text
match Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"after next") a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleOrdinalDOWOfTime :: Rule
ruleOrdinalDOWOfTime :: Rule
ruleOrdinalDOWOfTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"first|second|third|fourth|fifth <day-of-week> of <time>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isOrdinalBetween Int
1 Int
5
    , Predicate -> PatternItem
Predicate Predicate
isADayOfWeek
    , String -> PatternItem
regex String
"(of|in)"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \case
      (
        Token
token:
        Token Dimension a
Time a
td1:
        Token
_:
        Token Dimension a
Time a
td2:
        [Token]
_) -> do
          Int
ord <- Token -> Maybe Int
getIntValue Token
token
          TimeData
td <- TimeData -> Maybe TimeData
forall a. a -> Maybe a
Just (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData -> TimeData -> TimeData
predNthAfter (Int
ordInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1) a
TimeData
td1 a
TimeData
td2
          TimeData -> Maybe Token
tt TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleLastDOWOfTime :: Rule
ruleLastDOWOfTime :: Rule
ruleLastDOWOfTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"last <day-of-week> of <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"last"
    , Predicate -> PatternItem
Predicate Predicate
isADayOfWeek
    , String -> PatternItem
regex String
"(of|in)"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \case
      (
        Token
_:
        Token Dimension a
Time a
td1:
        Token
_:
        Token Dimension a
Time a
td2:
        [Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData -> TimeData
predLastOf a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleLastCycleOfTime :: Rule
ruleLastCycleOfTime :: Rule
ruleLastCycleOfTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"last <cycle> of <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"last"
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    , String -> PatternItem
regex String
"of|in"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
TimeGrain a
grain:Token
_:Token Dimension a
Time a
td:[Token]
_) ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> TimeData -> TimeData
cycleLastOf a
Grain
grain a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleLastNight :: Rule
ruleLastNight :: Rule
ruleLastNight = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"last night"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(late )?last night"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_) ->
        let hours :: Int
hours = if Text -> Text
Text.toLower Text
match Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"late " then Int
3 else Int
6
            start :: TimeData
start = DurationData -> TimeData -> TimeData
durationBefore (Int -> Grain -> DurationData
DurationData Int
hours Grain
TG.Hour) TimeData
today
        in Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> (TimeData -> TimeData) -> TimeData -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
partOfDay (TimeData -> TimeData)
-> (TimeData -> TimeData) -> TimeData -> TimeData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
notLatent (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
today
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleNthTimeOfTime :: Rule
ruleNthTimeOfTime :: Rule
ruleNthTimeOfTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"nth <time> of <time>"
  , pattern :: Pattern
pattern =
    [ Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    , String -> PatternItem
regex String
"of|in"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Ordinal a
od:Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> (TimeData -> TimeData) -> TimeData -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
        Int -> Bool -> TimeData -> TimeData
predNth (OrdinalData -> Int
TOrdinal.value a
OrdinalData
od Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Bool
False (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td2 a
TimeData
td1
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTheNthTimeOfTime :: Rule
ruleTheNthTimeOfTime :: Rule
ruleTheNthTimeOfTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the nth <time> of <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    , String -> PatternItem
regex String
"of|in"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Ordinal a
od:Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> (TimeData -> TimeData) -> TimeData -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
         Int -> Bool -> TimeData -> TimeData
predNth (OrdinalData -> Int
TOrdinal.value a
OrdinalData
od Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) Bool
False (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td2 a
TimeData
td1
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleNthTimeAfterTime :: Rule
ruleNthTimeAfterTime :: Rule
ruleNthTimeAfterTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"nth <time> after <time>"
  , pattern :: Pattern
pattern =
    [ Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    , String -> PatternItem
regex String
"after"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Ordinal a
od:Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> TimeData -> TimeData -> TimeData
predNthAfter (OrdinalData -> Int
TOrdinal.value a
OrdinalData
od Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTheNthTimeAfterTime :: Rule
ruleTheNthTimeAfterTime :: Rule
ruleTheNthTimeAfterTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the nth <time> after <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    , String -> PatternItem
regex String
"after"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Ordinal a
od:Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> TimeData -> TimeData -> TimeData
predNthAfter (OrdinalData -> Int
TOrdinal.value a
OrdinalData
od Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleNDOWFromTime :: Rule
ruleNDOWFromTime :: Rule
ruleNDOWFromTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<integer> <day-of-week> from <time>"
  , pattern :: Pattern
pattern =
    [ Dimension NumeralData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension NumeralData
Numeral
    , Predicate -> PatternItem
Predicate Predicate
isADayOfWeek
    , String -> PatternItem
regex String
"from"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> TimeData -> TimeData -> TimeData
predNthAfter (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleYearLatent :: Rule
ruleYearLatent :: Rule
ruleYearLatent = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"year (latent)"
  , pattern :: Pattern
pattern =
      [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$
        [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ([Bool] -> Bool) -> (Token -> [Bool]) -> Predicate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Predicate] -> Token -> [Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Int -> Int -> Predicate
isIntegerBetween (- Int
10000) Int
0, Int -> Int -> Predicate
isIntegerBetween Int
25 Int
10000]
      ]
  , prod :: Production
prod = \case
      (Token
token:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
mkLatent (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
year Int
n
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleYearADBC :: Rule
ruleYearADBC :: Rule
ruleYearADBC = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<year> (bc|ad)"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween (-Int
10000) Int
10000
    , String -> PatternItem
regex String
"(a\\.?d\\.?|b\\.?c\\.?)"
    ]
  , prod :: Production
prod = \case
    (Token
token:Token Dimension a
RegexMatch (GroupMatch (ab:_)):[Token]
_) -> do
      Int
y <- Token -> Maybe Int
getIntValue Token
token
      TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
yearADBC (Int -> TimeData) -> Int -> TimeData
forall a b. (a -> b) -> a -> b
$ if Text -> Char
Text.head (Text -> Text
Text.toLower Text
ab) Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'b' then -Int
y else Int
y
    [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDOMLatent :: Rule
ruleDOMLatent :: Rule
ruleDOMLatent = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<day-of-month> (ordinal)"
  , pattern :: Pattern
pattern = [Predicate -> PatternItem
Predicate Predicate
isDOMOrdinal]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
mkLatent (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
dayOfMonth Int
n
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTheDOMNumeral :: Rule
ruleTheDOMNumeral :: Rule
ruleTheDOMNumeral = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the <day-of-month> (number)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Predicate -> PatternItem
Predicate Predicate
isDOMInteger
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token
token:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
mkLatent (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
dayOfMonth Int
n
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTheDOMOrdinal :: Rule
ruleTheDOMOrdinal :: Rule
ruleTheDOMOrdinal = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the <day-of-month> (ordinal)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Predicate -> PatternItem
Predicate Predicate
isDOMOrdinal
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:
       Token Dimension a
Ordinal OrdinalData{TOrdinal.value = v}:
       [Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
dayOfMonth Int
v
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleNamedDOMOrdinal :: Rule
ruleNamedDOMOrdinal :: Rule
ruleNamedDOMOrdinal = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<named-month>|<named-day> <day-of-month> (ordinal)"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ([Bool] -> Bool) -> (Token -> [Bool]) -> Predicate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Predicate] -> Token -> [Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Predicate
isAMonth, Predicate
isADayOfWeek]
    , Predicate -> PatternItem
Predicate Predicate
isDOMOrdinal
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td:Token
token:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleMonthDOMNumeral :: Rule
ruleMonthDOMNumeral :: Rule
ruleMonthDOMNumeral = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<named-month> <day-of-month> (non ordinal)"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isAMonth
    , Predicate -> PatternItem
Predicate Predicate
isDOMInteger
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td:Token
token:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTheDOMOfMonth :: Rule
ruleTheDOMOfMonth :: Rule
ruleTheDOMOfMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the <day-of-month> (ordinal or number) of <named-month>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , String -> PatternItem
regex String
"of|in"
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token
token:Token
_:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDOMOfMonth :: Rule
ruleDOMOfMonth :: Rule
ruleDOMOfMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<day-of-month> (ordinal or number) of <named-month>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , String -> PatternItem
regex String
"of|in"
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token
_:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDOMMonth :: Rule
ruleDOMMonth :: Rule
ruleDOMMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<day-of-month> (ordinal or number) <named-month>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDOMMonthYear :: Rule
ruleDOMMonthYear :: Rule
ruleDOMMonthYear = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<day-of-month>(ordinal or number)/<named-month>/year"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , String -> PatternItem
regex String
"[-/\\s]"
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    , String -> PatternItem
regex String
"[-/\\s]"
    , String -> PatternItem
regex String
"(\\d{2,4})"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:
       Token
_:
       Token Dimension a
Time a
td:
       Token
_:
       Token Dimension a
RegexMatch (GroupMatch (match:_)):
       [Token]
_) -> do
         Int
intVal <- Text -> Maybe Int
parseInt Text
match
         TimeData
dom <- TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token
         Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect TimeData
dom (Int -> TimeData
year Int
intVal)
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDOMOrdinalMonthYear :: Rule
ruleDOMOrdinalMonthYear :: Rule
ruleDOMOrdinalMonthYear = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<day-of-month>(ordinal) <named-month> year"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isDOMOrdinal
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    , String -> PatternItem
regex String
"(\\d{2,4})"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token Dimension a
Time a
td:Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_) -> do
        Int
intVal <- Text -> Maybe Int
parseInt Text
match
        TimeData
dom <- TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect TimeData
dom (Int -> TimeData
year Int
intVal)
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIdesOfMonth :: Rule
ruleIdesOfMonth :: Rule
ruleIdesOfMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the ides of <named-month>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the ides? of"
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time td :: a
td@TimeData {TTime.form = Just (TTime.Month m)}:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
          TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (Int -> TimeData
dayOfMonth (Int -> TimeData) -> Int -> TimeData
forall a b. (a -> b) -> a -> b
$ if Int -> [Int] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem Int
m [Int
3, Int
5, Int
7, Int
10] then Int
15 else Int
13)
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTODLatent :: Rule
ruleTODLatent :: Rule
ruleTODLatent = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"time-of-day (latent)"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween Int
0 Int
23
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
mkLatent (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> TimeData
hour (Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
13) Int
n
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleAtTOD :: Rule
ruleAtTOD :: Rule
ruleAtTOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"at <time-of-day>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"at|@"
    , Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
notLatent a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTODOClock :: Rule
ruleTODOClock :: Rule
ruleTODOClock = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<time-of-day> o'clock"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
    , String -> PatternItem
regex String
"o.?clock"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td:[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
notLatent a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

rulePODatTOD :: Rule
rulePODatTOD :: Rule
rulePODatTOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<part-of-day> at <time-of-day>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isAPartOfDay
    , String -> PatternItem
regex String
"at|@"
    , Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time TimeData{TTime.timePred = TTime.IntersectPredicate
        (TTime.TimeIntervalsPredicate
          _ TTime.TimeDatePredicate{TTime.tdHour = Just (False, start)} _) _}:Token
_:
        Token Dimension a
Time tod :: a
tod@TimeData{TTime.form = Just (TTime.TimeOfDay (Just hours) True)}:[Token]
_) ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> TimeData -> TimeData
timeOfDayAMPM (Int
start Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
12 Bool -> Bool -> Bool
|| Int
hours Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
12) a
TimeData
tod
      (Token Dimension a
Time TimeData{TTime.timePred = TTime.TimeIntervalsPredicate
        _ TTime.TimeDatePredicate{TTime.tdHour = Just (False, start)} _}:Token
_:
        Token Dimension a
Time tod :: a
tod@TimeData{TTime.form = Just (TTime.TimeOfDay (Just hours) True)}:[Token]
_) ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> TimeData -> TimeData
timeOfDayAMPM (Int
start Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
12 Bool -> Bool -> Bool
|| Int
hours Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
12) a
TimeData
tod
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing

  }

ruleHHMM :: Rule
ruleHHMM :: Rule
ruleHHMM = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"hh:mm"
  , pattern :: Pattern
pattern = [String -> PatternItem
regex String
"((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)"]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (hh:mm:_)):[Token]
_) -> do
        Int
h <- Text -> Maybe Int
parseInt Text
hh
        Int
m <- Text -> Maybe Int
parseInt Text
mm
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute (Int
h Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
0 Bool -> Bool -> Bool
&& Int
h Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
12) Int
h Int
m
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleHHhMM :: Rule
ruleHHhMM :: Rule
ruleHHhMM = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"hhhmm"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(?<!/)((?:[01]?\\d)|(?:2[0-3]))h(([0-5]\\d)|(?!\\d))"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
RegexMatch (GroupMatch (hh:mm:_)):[Token]
_) -> do
        Int
h <- Text -> Maybe Int
parseInt Text
hh
        Int
m <- Text -> Maybe Int
parseInt Text
mm Maybe Int -> Maybe Int -> Maybe Int
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
0
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute Bool
False Int
h Int
m
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleHHMMLatent :: Rule
ruleHHMMLatent :: Rule
ruleHHMMLatent = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"hhmm (latent)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"((?:[01]?\\d)|(?:2[0-3]))([0-5]\\d)(?!.\\d)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (hh:mm:_)):[Token]
_) -> do
        Int
h <- Text -> Maybe Int
parseInt Text
hh
        Int
m <- Text -> Maybe Int
parseInt Text
mm
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
mkLatent (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute (Int
h Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
12) Int
h Int
m
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleHHMMSS :: Rule
ruleHHMMSS :: Rule
ruleHHMMSS = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"hh:mm:ss"
  , pattern :: Pattern
pattern = [String -> PatternItem
regex String
"((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)[:.]([0-5]\\d)"]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (hh:mm:ss:_)):[Token]
_) -> do
        Int
h <- Text -> Maybe Int
parseInt Text
hh
        Int
m <- Text -> Maybe Int
parseInt Text
mm
        Int
s <- Text -> Maybe Int
parseInt Text
ss
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> Int -> TimeData
hourMinuteSecond (Int
h Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
12) Int
h Int
m Int
s
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleMilitaryAMPM :: Rule
ruleMilitaryAMPM :: Rule
ruleMilitaryAMPM = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"hhmm (military) am|pm"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"((?:1[012]|0?\\d))([0-5]\\d)"
    , String -> PatternItem
regex String
"([ap])\\.?m?\\.?"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (hh:mm:_)):
       Token Dimension a
RegexMatch (GroupMatch (ap:_)):
       [Token]
_) -> do
        Int
h <- Text -> Maybe Int
parseInt Text
hh
        Int
m <- Text -> Maybe Int
parseInt Text
mm
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> TimeData -> TimeData
timeOfDayAMPM (Text -> Text
Text.toLower Text
ap Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"a") (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute Bool
True Int
h Int
m
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleMilitarySpelledOutAMPM :: Rule
ruleMilitarySpelledOutAMPM :: Rule
ruleMilitarySpelledOutAMPM = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"military spelled out numbers am|pm"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween Int
10 Int
12
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween Int
1 Int
59
    , String -> PatternItem
regex String
"(in the )?([ap])(\\s|\\.)?m?\\.?"
    ]
    , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
        (Token
h:Token
m:Token Dimension a
RegexMatch (GroupMatch (_:ap:_)):[Token]
_) -> do
          Int
hh <- Token -> Maybe Int
getIntValue Token
h
          Int
mm <- Token -> Maybe Int
getIntValue Token
m
          TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> TimeData -> TimeData
timeOfDayAMPM (Text -> Text
Text.toLower Text
ap Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"a") (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute Bool
True Int
hh Int
mm
        [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleMilitarySpelledOutAMPM2 :: Rule
ruleMilitarySpelledOutAMPM2 :: Rule
ruleMilitarySpelledOutAMPM2 = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"six thirty six a.m."
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween Int
110 Int
999
    , String -> PatternItem
regex String
"(in the )?([ap])(\\s|\\.)?m?\\.?"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token Dimension a
RegexMatch (GroupMatch (_:ap:_)):[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        Int
m <- case Int -> Int -> Int
forall a. Integral a => a -> a -> a
mod Int
n Int
100 of
          Int
v | Int
v Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
60 -> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
v
          Int
_          -> Maybe Int
forall a. Maybe a
Nothing
        let h :: Int
h = Int -> Int -> Int
forall a. Integral a => a -> a -> a
quot Int
n Int
100
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> TimeData -> TimeData
timeOfDayAMPM (Text -> Text
Text.toLower Text
ap Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"a") (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute Bool
True Int
h Int
m
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTODAMPM :: Rule
ruleTODAMPM :: Rule
ruleTODAMPM = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<time-of-day> am|pm"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
    , String -> PatternItem
regex String
"(in the )?([ap])(\\s|\\.)?(m?)\\.?"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time td :: a
td@TimeData{TTime.latent = True}:
       Token Dimension a
RegexMatch (GroupMatch (_:ap:_:"":_)):
       [Token]
_) ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
mkLatent (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Bool -> TimeData -> TimeData
timeOfDayAMPM (Text -> Text
Text.toLower Text
ap Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"a") a
TimeData
td
      (Token Dimension a
Time td :: a
td@TimeData{TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:
       Token Dimension a
RegexMatch (GroupMatch (_:ap:_)):
       [Token]
_) | Int
hours Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
13 ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> TimeData -> TimeData
timeOfDayAMPM (Text -> Text
Text.toLower Text
ap Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"a") a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleHONumeral :: Rule
ruleHONumeral :: Rule
ruleHONumeral = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<hour-of-day> <integer>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isAnHourOfDay
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween Int
1 Int
59
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time TimeData{TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)
                          ,TTime.latent = isLatent}:
       Token
token:
       [Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        if Bool
isLatent
          then TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
mkLatent (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute Bool
is12H Int
hours Int
n
          else TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute Bool
is12H Int
hours Int
n
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleHONumeralAlt :: Rule
ruleHONumeralAlt :: Rule
ruleHONumeralAlt = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<hour-of-day> zero <integer>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isAnHourOfDay
    , String -> PatternItem
regex String
"(zero|o(h|u)?)"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween Int
1 Int
9
    ]
  , prod :: Production
prod = \case
      (
        Token Dimension a
Time TimeData{TTime.form = Just (TTime.TimeOfDay
                                              (Just hours) is12H)
                          , TTime.latent = isLatent}:
        Token
_:
        Token
token:
        [Token]
_) -> do
          Int
n <- Token -> Maybe Int
getIntValue Token
token
          if Bool
isLatent
            then TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
mkLatent (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute Bool
is12H Int
hours Int
n
            else TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute Bool
is12H Int
hours Int
n
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleHODHalf :: Rule
ruleHODHalf :: Rule
ruleHODHalf = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<hour-of-day> half"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isAnHourOfDay
    , String -> PatternItem
regex String
"half"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time TimeData{TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:
       [Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute Bool
is12H Int
hours Int
30
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleHODQuarter :: Rule
ruleHODQuarter :: Rule
ruleHODQuarter = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<hour-of-day> quarter"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isAnHourOfDay
    , String -> PatternItem
regex String
"(a|one)? ?quarter"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time TimeData{TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:
       [Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> Int -> TimeData
hourMinute Bool
is12H Int
hours Int
15
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleNumeralToHOD :: Rule
ruleNumeralToHOD :: Rule
ruleNumeralToHOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<integer> to|till|before <hour-of-day>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween Int
1 Int
59
    , String -> PatternItem
regex String
"to|till|before|of"
    , Predicate -> PatternItem
Predicate Predicate
isAnHourOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token
_:Token Dimension a
Time a
td:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> TimeData -> Maybe TimeData
minutesBefore Int
n a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleHalfToHOD :: Rule
ruleHalfToHOD :: Rule
ruleHalfToHOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"half to|till|before <hour-of-day>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"half (to|till|before|of)"
    , Predicate -> PatternItem
Predicate Predicate
isAnHourOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> TimeData -> Maybe TimeData
minutesBefore Int
30 a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleQuarterToHOD :: Rule
ruleQuarterToHOD :: Rule
ruleQuarterToHOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"quarter to|till|before <hour-of-day>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(a|one)? ?quarter (to|till|before|of)"
    , Predicate -> PatternItem
Predicate Predicate
isAnHourOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> TimeData -> Maybe TimeData
minutesBefore Int
15 a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleNumeralAfterHOD :: Rule
ruleNumeralAfterHOD :: Rule
ruleNumeralAfterHOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"integer after|past <hour-of-day>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween Int
1 Int
59
    , String -> PatternItem
regex String
"after|past"
    , Predicate -> PatternItem
Predicate Predicate
isAnHourOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token
_:Token Dimension a
Time a
td:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> TimeData -> Maybe TimeData
minutesAfter Int
n a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleHalfAfterHOD :: Rule
ruleHalfAfterHOD :: Rule
ruleHalfAfterHOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"half after|past <hour-of-day>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"half (after|past)"
    , Predicate -> PatternItem
Predicate Predicate
isAnHourOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> TimeData -> Maybe TimeData
minutesAfter Int
30 a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleQuarterAfterHOD :: Rule
ruleQuarterAfterHOD :: Rule
ruleQuarterAfterHOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"quarter after|past <hour-of-day>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(for )?((a|one) )?quarter (after|past)"
    , Predicate -> PatternItem
Predicate Predicate
isAnHourOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> TimeData -> Maybe TimeData
minutesAfter Int
15 a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleHalfHOD :: Rule
ruleHalfHOD :: Rule
ruleHalfHOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"half <integer> (UK style hour-of-day)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"half"
    , Predicate -> PatternItem
Predicate Predicate
isAnHourOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> TimeData -> Maybe TimeData
minutesAfter Int
30 a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleMMYYYY :: Rule
ruleMMYYYY :: Rule
ruleMMYYYY = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"mm/yyyy"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(0?[1-9]|1[0-2])[/-](\\d{4})"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
RegexMatch (GroupMatch (mm:yy:_)):[Token]
_) -> do
        Int
y <- Text -> Maybe Int
parseInt Text
yy
        Int
m <- Text -> Maybe Int
parseInt Text
mm
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> Int -> TimeData
yearMonth Int
y Int
m
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleYYYYMM :: Rule
ruleYYYYMM :: Rule
ruleYYYYMM = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"yyyy-mm"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(\\d{4})\\s*[/-]\\s*(1[0-2]|0?[1-9])"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
RegexMatch (GroupMatch (yy:mm:_)):[Token]
_) -> do
        Int
y <- Text -> Maybe Int
parseInt Text
yy
        Int
m <- Text -> Maybe Int
parseInt Text
mm
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> Int -> TimeData
yearMonth Int
y Int
m
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleYYYYMMDD :: Rule
ruleYYYYMMDD :: Rule
ruleYYYYMMDD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"yyyy-mm-dd"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
RegexMatch (GroupMatch (yy:mm:dd:_)):[Token]
_) -> do
        Int
y <- Text -> Maybe Int
parseInt Text
yy
        Int
m <- Text -> Maybe Int
parseInt Text
mm
        Int
d <- Text -> Maybe Int
parseInt Text
dd
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int -> TimeData
yearMonthDay Int
y Int
m Int
d
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleYYYYQQ :: Rule
ruleYYYYQQ :: Rule
ruleYYYYQQ = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"yyyyqq"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(\\d{2,4})q([1-4])"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
RegexMatch (GroupMatch (yy:qq:_)):[Token]
_) -> do
        Int
y <- Text -> Maybe Int
parseInt Text
yy
        Int
q <- Text -> Maybe Int
parseInt Text
qq
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True Grain
TG.Quarter (Int
q Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
year Int
y
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleNoonMidnightEOD :: Rule
ruleNoonMidnightEOD :: Rule
ruleNoonMidnightEOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"noon|midnight|EOD|end of day"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(noon|midni(ght|te)|(the )?(EOD|end of (the )?day))"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> TimeData
hour Bool
False (Int -> TimeData) -> Int -> TimeData
forall a b. (a -> b) -> a -> b
$
        if Text -> Text
Text.toLower Text
match Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"noon" then Int
12 else Int
0
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

rulePartOfDays :: Rule
rulePartOfDays :: Rule
rulePartOfDays = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"part of days"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(morning|after ?noo?n(ish)?|evening|night|(at )?lunch)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_) -> do
        let (TimeData
start, TimeData
end) = case Text -> Text
Text.toLower Text
match of
              Text
"morning"  -> (Bool -> Int -> TimeData
hour Bool
False Int
0, Bool -> Int -> TimeData
hour Bool
False Int
12)
              Text
"evening"  -> (Bool -> Int -> TimeData
hour Bool
False Int
18, Bool -> Int -> TimeData
hour Bool
False Int
0)
              Text
"night"    -> (Bool -> Int -> TimeData
hour Bool
False Int
18, Bool -> Int -> TimeData
hour Bool
False Int
0)
              Text
"lunch"    -> (Bool -> Int -> TimeData
hour Bool
False Int
12, Bool -> Int -> TimeData
hour Bool
False Int
14)
              Text
"at lunch" -> (Bool -> Int -> TimeData
hour Bool
False Int
12, Bool -> Int -> TimeData
hour Bool
False Int
14)
              Text
_          -> (Bool -> Int -> TimeData
hour Bool
False Int
12, Bool -> Int -> TimeData
hour Bool
False Int
19)
        TimeData
td <- TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
partOfDay (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
mkLatent TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleEarlyMorning :: Rule
ruleEarlyMorning :: Rule
ruleEarlyMorning = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"early morning"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"early ((in|hours of) the )?morning"
    ]
  , prod :: Production
prod = \[Token]
_ -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> (TimeData -> TimeData) -> TimeData -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
partOfDay (TimeData -> TimeData)
-> (TimeData -> TimeData) -> TimeData -> TimeData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
mkLatent (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
      TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open (Bool -> Int -> TimeData
hour Bool
False Int
0) (Bool -> Int -> TimeData
hour Bool
False Int
9)
  }

rulePODIn :: Rule
rulePODIn :: Rule
rulePODIn = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"in|during the <part-of-day>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(in|during)( the)?"
    , Predicate -> PatternItem
Predicate Predicate
isAPartOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
notLatent a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

rulePODThis :: Rule
rulePODThis :: Rule
rulePODThis = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"this <part-of-day>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"this"
    , Predicate -> PatternItem
Predicate Predicate
isAPartOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> (TimeData -> TimeData) -> TimeData -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
partOfDay (TimeData -> TimeData)
-> (TimeData -> TimeData) -> TimeData -> TimeData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
notLatent (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
        TimeData -> TimeData -> Maybe TimeData
intersect TimeData
today a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTonight :: Rule
ruleTonight :: Rule
ruleTonight = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"tonight"
  , pattern :: Pattern
pattern = [String -> PatternItem
regex String
"(late )?toni(ght|gth|te)s?"]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_) -> do
        let h :: Int
h = if Text -> Text
Text.toLower Text
match Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"late " then Int
21 else Int
18
        TimeData
evening <- TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open (Bool -> Int -> TimeData
hour Bool
False Int
h) (Bool -> Int -> TimeData
hour Bool
False Int
0)
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> (TimeData -> TimeData) -> TimeData -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
partOfDay (TimeData -> TimeData)
-> (TimeData -> TimeData) -> TimeData -> TimeData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
notLatent (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect TimeData
today TimeData
evening
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleAfterPartofday :: Rule
ruleAfterPartofday :: Rule
ruleAfterPartofday = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"after lunch/work/school"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"after[\\s-]?(lunch|work|school)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_) -> do
        (TimeData
start, TimeData
end) <- case Text -> Text
Text.toLower Text
match of
          Text
"lunch"  -> (TimeData, TimeData) -> Maybe (TimeData, TimeData)
forall a. a -> Maybe a
Just (Bool -> Int -> TimeData
hour Bool
False Int
13, Bool -> Int -> TimeData
hour Bool
False Int
17)
          Text
"work"   -> (TimeData, TimeData) -> Maybe (TimeData, TimeData)
forall a. a -> Maybe a
Just (Bool -> Int -> TimeData
hour Bool
False Int
17, Bool -> Int -> TimeData
hour Bool
False Int
21)
          Text
"school" -> (TimeData, TimeData) -> Maybe (TimeData, TimeData)
forall a. a -> Maybe a
Just (Bool -> Int -> TimeData
hour Bool
False Int
15, Bool -> Int -> TimeData
hour Bool
False Int
21)
          Text
_        -> Maybe (TimeData, TimeData)
forall a. Maybe a
Nothing
        TimeData
td <- TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> (TimeData -> TimeData) -> TimeData -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
partOfDay (TimeData -> TimeData)
-> (TimeData -> TimeData) -> TimeData -> TimeData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
notLatent (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect TimeData
today TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

-- Since part of days are latent, general time intersection is blocked
ruleTimePOD :: Rule
ruleTimePOD :: Rule
ruleTimePOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<time> <part-of-day>"
  , pattern :: Pattern
pattern =
    [ Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    , Predicate -> PatternItem
Predicate Predicate
isAPartOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td:Token Dimension a
Time a
pod:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
pod a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

rulePODofTime :: Rule
rulePODofTime :: Rule
rulePODofTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<part-of-day> of <time>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isAPartOfDay
    , String -> PatternItem
regex String
"of"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
pod:Token
_:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
pod a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleWeekend :: Rule
ruleWeekend :: Rule
ruleWeekend = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"week-end"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(week(\\s|-)?end|wkend)s?"
    ]
  , prod :: Production
prod = \[Token]
_ -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
mkOkForThisNext TimeData
weekend
  }

ruleWeek :: Rule
ruleWeek :: Rule
ruleWeek = Rule :: Text -> Pattern -> Production -> Rule
Rule
 { name :: Text
name = Text
"week"
 , pattern :: Pattern
pattern =
   [ String -> PatternItem
regex String
"(all|rest of the|the) week"
   ]
 , prod :: Production
prod = \case
     (Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_) ->
       let end :: TimeData
end = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True Grain
TG.Day (-Int
2) (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth Grain
TG.Week Int
1
           period :: Maybe TimeData
period = case Text -> Text
Text.toLower Text
match of
                      Text
"all" -> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
Closed (Grain -> Int -> TimeData
cycleNth Grain
TG.Week Int
0) TimeData
end
                      Text
"rest of the" -> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
Open TimeData
today TimeData
end
                      Text
"the" -> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
Open TimeData
today TimeData
end
                      Text
_ -> Maybe TimeData
forall a. Maybe a
Nothing
       in case Text -> Text
Text.toLower Text
match of
         Text
"the" -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> (TimeData -> TimeData) -> TimeData -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
mkLatent (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe TimeData
period
         Text
_ -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe TimeData
period
     [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
 }

ruleSeason :: Rule
ruleSeason :: Rule
ruleSeason = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"last|this|next <season>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(this|current|next|last|past|previous) seasons?"
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_) -> do
        Int
n <- case Text -> Text
Text.toLower Text
match of
               Text
"this" -> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
0
               Text
"current" -> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
0
               Text
"last" -> Int -> Maybe Int
forall a. a -> Maybe a
Just (-Int
1)
               Text
"past" -> Int -> Maybe Int
forall a. a -> Maybe a
Just (-Int
1)
               Text
"previous" -> Int -> Maybe Int
forall a. a -> Maybe a
Just (-Int
1)
               Text
"next" -> Int -> Maybe Int
forall a. a -> Maybe a
Just Int
1
               Text
_ -> Maybe Int
forall a. Maybe a
Nothing
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> Bool -> TimeData -> TimeData
predNth Int
n Bool
False TimeData
season
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleSeasons :: [Rule]
ruleSeasons :: [Rule]
ruleSeasons = [(Text, String, TimeData, TimeData)] -> [Rule]
mkRuleSeasons
  [ ( Text
"summer", String
"summer"     , Int -> Int -> TimeData
monthDay  Int
6 Int
21, Int -> Int -> TimeData
monthDay  Int
9 Int
23 )
  , ( Text
"fall"  , String
"fall|autumn", Int -> Int -> TimeData
monthDay  Int
9 Int
23, Int -> Int -> TimeData
monthDay Int
12 Int
21 )
  , ( Text
"winter", String
"winter"     , Int -> Int -> TimeData
monthDay Int
12 Int
21, Int -> Int -> TimeData
monthDay  Int
3 Int
20 )
  , ( Text
"spring", String
"spring"     , Int -> Int -> TimeData
monthDay  Int
3 Int
20, Int -> Int -> TimeData
monthDay  Int
6 Int
21 )
  ]

ruleTODPrecision :: Rule
ruleTODPrecision :: Rule
ruleTODPrecision = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<time-of-day> sharp|exactly"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
    , String -> PatternItem
regex String
"(sharp|exactly|-?ish|approximately)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td:[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
notLatent a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTODPOD :: Rule
ruleTODPOD :: Rule
ruleTODPOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<time-of-day> <part-of-day>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
    , Predicate -> PatternItem
Predicate Predicate
isAPartOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td:Token Dimension a
Time a
pod:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> (TimeData -> TimeData) -> TimeData -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TimeData -> TimeData
notLatent (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td a
TimeData
pod
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

rulePrecisionTOD :: Rule
rulePrecisionTOD :: Rule
rulePrecisionTOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"about|exactly <time-of-day>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(about|around|approximately|exactly)"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrainFinerThan Grain
TG.Year
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
notLatent a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalMonthDDDD :: Rule
ruleIntervalMonthDDDD :: Rule
ruleIntervalMonthDDDD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<month> dd-dd (interval)"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isAMonth
    , Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , String -> PatternItem
regex String
"\\-|to|th?ru|through|(un)?til(l)?"
    , Predicate -> PatternItem
Predicate Predicate
isDOMValue
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td:
       Token
token1:
       Token
_:
       Token
token2:
       [Token]
_) -> do
        TimeData
dom1 <- TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token1
        TimeData
dom2 <- TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token2
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed TimeData
dom1 TimeData
dom2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalDDDDMonth :: Rule
ruleIntervalDDDDMonth :: Rule
ruleIntervalDDDDMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"dd-dd <month> (interval)"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , String -> PatternItem
regex String
"\\-|to|th?ru|through|(un)?til(l)?"
    , Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token1:
       Token
_:
       Token
token2:
       Token Dimension a
Time a
td:
       [Token]
_) -> do
        TimeData
dom1 <- TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token1
        TimeData
dom2 <- TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token2
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed TimeData
dom1 TimeData
dom2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalFromMonthDDDD :: Rule
ruleIntervalFromMonthDDDD :: Rule
ruleIntervalFromMonthDDDD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"from <month> dd-dd (interval)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"from"
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    , Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , String -> PatternItem
regex String
"\\-|to|th?ru|through|(un)?til(l)?"
    , Predicate -> PatternItem
Predicate Predicate
isDOMValue
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:
       Token Dimension a
Time a
td:
       Token
token1:
       Token
_:
       Token
token2:
       [Token]
_) -> do
        TimeData
dom1 <- TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token1
        TimeData
dom2 <- TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token2
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed TimeData
dom1 TimeData
dom2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalFromDDDDMonth :: Rule
ruleIntervalFromDDDDMonth :: Rule
ruleIntervalFromDDDDMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"from the <day-of-month> (ordinal or number) to the <day-of-month> (ordinal or number) <named-month> (interval)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"from( the)?"
    , Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , String -> PatternItem
regex String
"\\-|to( the)?|th?ru|through|(un)?til(l)?"
    , Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:
       Token
token1:
       Token
_:
       Token
token2:
       Token Dimension a
Time a
td:
       [Token]
_) -> do
        TimeData
dom1 <- TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token1
        TimeData
dom2 <- TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token2
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed TimeData
dom1 TimeData
dom2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalFromDDDDOfMonth :: Rule
ruleIntervalFromDDDDOfMonth :: Rule
ruleIntervalFromDDDDOfMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"from the <day-of-month> (ordinal or number) to the <day-of-month> (ordinal or number) of <named-month> (interval)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"from( the)?"
    , Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , String -> PatternItem
regex String
"\\-|to( the)?|th?ru|through|(un)?til(l)?"
    , Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , String -> PatternItem
regex String
"of"
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:
       Token
token1:
       Token
_:
       Token
token2:
       Token
_:
       Token Dimension a
Time a
td:
       [Token]
_) -> do
        TimeData
dom1 <- TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token1
        TimeData
dom2 <- TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token2
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed TimeData
dom1 TimeData
dom2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

-- In order to support latent year ranges, e.g. "1960 - 1961", we impose
-- the following constraints:
--   1. Neither year can be negative.
--   2. The first year must be less than the second year.
--   3. The years must be within the interval [1000,10000].
-- (1): We could try to allow negative years, but years in natural language are
--      almost never written as negative, so it's unnecessary complication.
-- (2): Year ranges in natural language are written
--      <earlier year> - <later year>. No need to derive the ordering from
--      something which is not likely a year range.
-- (3): Four+ digits prevents phone numbers (e.g. "333-444-5555") from
--      registering false positives.
--      In everyday language, people are more likely to mention years closer
--      to the present than very far in the past or future (closer times are
--      more relevant).
--      Of course, this means we do not have the ability to parse something like
--      "300 - 600" as a year interval. But, prior to implementing this
--      rule, we already did not have that ability.
--
-- These guidelines are not perfect, but they work. They can be iterated on and
-- improved going forward.
ruleIntervalYearLatent :: Rule
ruleIntervalYearLatent :: Rule
ruleIntervalYearLatent = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<year> (latent) - <year> (latent) (interval)"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween Int
1000 Int
10000
    , String -> PatternItem
regex String
"\\-|to|th?ru|through|(un)?til(l)?"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween Int
1000 Int
10000
    ]
  , prod :: Production
prod = \case
      (Token
t1:Token
_:Token
t2:[Token]
_) -> do
        Int
y1 <- Token -> Maybe Int
getIntValue Token
t1
        Int
y2 <- Token -> Maybe Int
getIntValue Token
t2
        Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Int
y1 Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
y2)
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed (Int -> TimeData
year Int
y1) (Int -> TimeData
year Int
y2)
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

-- Blocked for :latent time.
ruleIntervalDash :: Rule
ruleIntervalDash :: Rule
ruleIntervalDash = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<datetime> - <datetime> (interval)"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isNotLatent
    , String -> PatternItem
regex String
"\\-|to|th?ru|through|(un)?til(l)?"
    , Predicate -> PatternItem
Predicate Predicate
isNotLatent
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalSlash :: Rule
ruleIntervalSlash :: Rule
ruleIntervalSlash = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<datetime>/<datetime> (interval)"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isNotLatent
    , String -> PatternItem
regex String
"/"
    , Predicate -> PatternItem
Predicate Predicate
isNotLatent
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) | TimeData -> TimeData -> Bool
sameGrain a
TimeData
td1 a
TimeData
td2 ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalFrom :: Rule
ruleIntervalFrom :: Rule
ruleIntervalFrom = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"from <datetime> - <datetime> (interval)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"from"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    , String -> PatternItem
regex String
"\\-|to|th?ru|through|(un)?til(l)?"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalBetween :: Rule
ruleIntervalBetween :: Rule
ruleIntervalBetween = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"between <time> and <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"between"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    , String -> PatternItem
regex String
"and"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

-- Specific for time-of-day, to help resolve ambiguities
ruleIntervalTODDash :: Rule
ruleIntervalTODDash :: Rule
ruleIntervalTODDash = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<time-of-day> - <time-of-day> (interval)"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and ([Bool] -> Bool) -> (Token -> [Bool]) -> Predicate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Predicate] -> Token -> [Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Predicate
isNotLatent, Predicate
isATimeOfDay]
    , String -> PatternItem
regex String
"\\-|:|to|th?ru|through|(un)?til(l)?"
    , Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
    ]
  , prod :: Production
prod = \case
      (Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalTODFrom :: Rule
ruleIntervalTODFrom :: Rule
ruleIntervalTODFrom = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"from <time-of-day> - <time-of-day> (interval)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(later than|from|(in[\\s-])?between)"
    , Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
    , String -> PatternItem
regex String
"((but )?before)|\\-|to|th?ru|through|(un)?til(l)?"
    , Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

-- We can't take generic TOD (e.g. "6:30am - 9pm").
-- Those are handled by other rules.
ruleIntervalTODAMPM :: Rule
ruleIntervalTODAMPM :: Rule
ruleIntervalTODAMPM = Rule :: Text -> Pattern -> Production -> Rule
Rule
 { name :: Text
name = Text
"hh(:mm) - <time-of-day> am|pm"
 , pattern :: Pattern
pattern =
   [ String -> PatternItem
regex String
"(?:from )?((?:[01]?\\d)|(?:2[0-3]))([:.]([0-5]\\d))?"
   , String -> PatternItem
regex String
"\\-|:|to|th?ru|through|(un)?til(l)?"
   , Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
   , String -> PatternItem
regex String
"(in the )?([ap])(\\s|\\.)?m?\\.?"
   ]
 , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
     (Token Dimension a
RegexMatch (GroupMatch (hh:_:mm:_)):
      Token
_:
      Token Dimension a
Time a
td2:
      Token Dimension a
RegexMatch (GroupMatch (_:ap:_)):
      [Token]
_) -> do
       Int
h <- Text -> Maybe Int
parseInt Text
hh
       let ampm :: Bool
ampm = Text -> Text
Text.toLower Text
ap Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"a"
           td1 :: TimeData
td1 = case Text -> Maybe Int
parseInt Text
mm of
             Just Int
m -> Bool -> Int -> Int -> TimeData
hourMinute Bool
True Int
h Int
m
             Maybe Int
Nothing -> Bool -> Int -> TimeData
hour Bool
True Int
h
       Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
         TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed (Bool -> TimeData -> TimeData
timeOfDayAMPM Bool
ampm TimeData
td1) (Bool -> TimeData -> TimeData
timeOfDayAMPM Bool
ampm a
TimeData
td2)
     [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
 }

ruleIntervalTODBetween :: Rule
ruleIntervalTODBetween :: Rule
ruleIntervalTODBetween = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"between <time-of-day> and <time-of-day> (interval)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"between"
    , Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
    , String -> PatternItem
regex String
"and"
    , Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
    ]
  , prod :: Production
prod = \case
      (Token
_:Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalBy :: Rule
ruleIntervalBy :: Rule
ruleIntervalBy = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"by <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"by"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \case
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
now a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalByTheEndOf :: Rule
ruleIntervalByTheEndOf :: Rule
ruleIntervalByTheEndOf = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"by the end of <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"by (the )?end of"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed TimeData
now a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalUntilTime :: Rule
ruleIntervalUntilTime :: Rule
ruleIntervalUntilTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"until <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(anytime |sometimes? )?(before|(un)?til(l)?|through|up to)"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ IntervalDirection -> TimeData -> TimeData
withDirection IntervalDirection
TTime.Before (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
notLatent a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalAfterFromSinceTime :: Rule
ruleIntervalAfterFromSinceTime :: Rule
ruleIntervalAfterFromSinceTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"from|since|after <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"from|since|(anytime |sometimes? )?after"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td:[Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ IntervalDirection -> TimeData -> TimeData
withDirection IntervalDirection
TTime.After (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ TimeData -> TimeData
notLatent a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDaysOfWeek :: [Rule]
ruleDaysOfWeek :: [Rule]
ruleDaysOfWeek = [(Text, String)] -> [Rule]
mkRuleDaysOfWeek
  [ ( Text
"Monday"   , String
"mondays?|mon\\.?"         )
  , ( Text
"Tuesday"  , String
"tuesdays?|tues?\\.?"      )
  , ( Text
"Wednesday", String
"wed?nesdays?|wed\\.?"     )
  , ( Text
"Thursday" , String
"thursdays?|thu(rs?)?\\.?" )
  , ( Text
"Friday"   , String
"fridays?|fri\\.?"         )
  , ( Text
"Saturday" , String
"saturdays?|sat\\.?"       )
  , ( Text
"Sunday"   , String
"sundays?|sun\\.?"         )
  ]

ruleMonths :: [Rule]
ruleMonths :: [Rule]
ruleMonths = [(Text, String, Bool)] -> [Rule]
mkRuleMonthsWithLatent
  [ ( Text
"January"  , String
"january|jan\\.?"    , Bool
False )
  , ( Text
"February" , String
"february|feb\\.?"   , Bool
False )
  , ( Text
"March"    , String
"march|mar\\.?"      , Bool
False )
  , ( Text
"April"    , String
"april|apr\\.?"      , Bool
False )
  , ( Text
"May"      , String
"may"                , Bool
True  )
  , ( Text
"June"     , String
"june|jun\\.?"       , Bool
False )
  , ( Text
"July"     , String
"july|jul\\.?"       , Bool
False )
  , ( Text
"August"   , String
"august|aug\\.?"     , Bool
False )
  , ( Text
"September", String
"september|sept?\\.?", Bool
False )
  , ( Text
"October"  , String
"october|oct\\.?"    , Bool
False )
  , ( Text
"November" , String
"november|nov\\.?"   , Bool
False )
  , ( Text
"December" , String
"december|dec\\.?"   , Bool
False )
  ]

rulePartOfMonth :: Rule
rulePartOfMonth :: Rule
rulePartOfMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"part of <named-month>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(early|mid|late)-?( of)?"
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):Token Dimension a
Time a
td:[Token]
_) -> do
        (Int
sd, Int
ed) <- case Text -> Text
Text.toLower Text
match of
          Text
"early" -> (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
1, Int
10)
          Text
"mid"   -> (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
11, Int
20)
          Text
"late"  -> (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
21, -Int
1)
          Text
_       -> Maybe (Int, Int)
forall a. Maybe a
Nothing
        TimeData
start <- TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
dayOfMonth Int
sd
        TimeData
end <- if Int
ed Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= -Int
1
          then TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
dayOfMonth Int
ed
          else TimeData -> Maybe TimeData
forall a. a -> Maybe a
Just (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Grain -> TimeData -> TimeData
cycleLastOf Grain
TG.Day a
TimeData
td
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleEndOrBeginningOfMonth :: Rule
ruleEndOrBeginningOfMonth :: Rule
ruleEndOrBeginningOfMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"at the beginning|end of <named-month>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(at the )?(beginning|end) of"
    , Predicate -> PatternItem
Predicate Predicate
isAMonth
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (_:match:_)):Token Dimension a
Time a
td:[Token]
_) -> do
        (Int
sd, Int
ed) <- case Text -> Text
Text.toLower Text
match of
          Text
"beginning" -> (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
1, Int
10)
          Text
"end"       -> (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
21, -Int
1)
          Text
_           -> Maybe (Int, Int)
forall a. Maybe a
Nothing
        TimeData
start <- TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
dayOfMonth Int
sd
        TimeData
end <- if Int
ed Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= -Int
1
          then TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
dayOfMonth Int
ed
          else TimeData -> Maybe TimeData
forall a. a -> Maybe a
Just (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Grain -> TimeData -> TimeData
cycleLastOf Grain
TG.Day a
TimeData
td
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleEndOfMonth :: Rule
ruleEndOfMonth :: Rule
ruleEndOfMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"end of month"
  , pattern :: Pattern
pattern = [ String -> PatternItem
regex String
"(by (the )?|(at )?the )?(EOM|end of (the )?month)" ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_)
        | (Just TimeData
start, Just TimeData
end) <- (Maybe TimeData, Maybe TimeData)
parsed ->
          Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end
        where
          cycleMonth :: Int -> TimeData
cycleMonth = Grain -> Int -> TimeData
cycleNth Grain
TG.Month
          parsed :: (Maybe TimeData, Maybe TimeData)
parsed = if Text
"by" Text -> Text -> Bool
`Text.isPrefixOf` Text -> Text
Text.toLower Text
match
            then
              ( TimeData -> Maybe TimeData
forall a. a -> Maybe a
Just TimeData
now
              , TimeData -> TimeData -> Maybe TimeData
intersect (Int -> TimeData
dayOfMonth Int
1) (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
cycleMonth Int
1)
            else
              ( TimeData -> TimeData -> Maybe TimeData
intersect (Int -> TimeData
dayOfMonth Int
21) (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
cycleMonth Int
0
              , TimeData -> Maybe TimeData
forall a. a -> Maybe a
Just (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Grain -> TimeData -> TimeData
cycleLastOf Grain
TG.Day (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
cycleMonth Int
0)
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleBeginningOfMonth :: Rule
ruleBeginningOfMonth :: Rule
ruleBeginningOfMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"beginning of month"
  , pattern :: Pattern
pattern = [ String -> PatternItem
regex String
"((at )?the )?(BOM|beginning of (the )?month)" ]
  , prod :: Production
prod = \[Token]
_ -> do
      TimeData
start <- TimeData -> TimeData -> Maybe TimeData
intersect (Int -> TimeData
dayOfMonth Int
1) (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth Grain
TG.Month Int
0
      TimeData
end <- TimeData -> TimeData -> Maybe TimeData
intersect (Int -> TimeData
dayOfMonth Int
10) (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth Grain
TG.Month Int
0
      Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end
  }

ruleEndOrBeginningOfYear :: Rule
ruleEndOrBeginningOfYear :: Rule
ruleEndOrBeginningOfYear = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"at the beginning|end of <year>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(at the )?(beginning|end) of"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrainOfTime Grain
TG.Year
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (_:match:_)):Token Dimension a
Time a
td:[Token]
_) -> do
        (Int
sd, Int
ed) <- case Text -> Text
Text.toLower Text
match of
          Text
"beginning" -> (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
1, Int
4)
          Text
"end"       -> (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
9, -Int
1)
          Text
_           -> Maybe (Int, Int)
forall a. Maybe a
Nothing
        TimeData
start <- TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
month Int
sd
        TimeData
end <- if Int
ed Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= -Int
1
          then TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Grain -> TimeData -> TimeData
cycleLastOf Grain
TG.Month (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
month Int
ed
          else Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Year Int
1 (TimeData -> TimeData) -> Maybe TimeData -> Maybe TimeData
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (Int -> TimeData
month Int
1)
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleEndOfYear :: Rule
ruleEndOfYear :: Rule
ruleEndOfYear = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"end of year"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(by (the )?|(at )?the )?(EOY|end of (the )?year)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):[Token]
_) -> do
        TimeData
start <- Maybe TimeData
std
        TimeData
end <- TimeData -> TimeData -> Maybe TimeData
intersect (Int -> TimeData
month Int
1) (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
cycleYear Int
1
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end
          where
            std :: Maybe TimeData
std = if Text
"by" Text -> Text -> Bool
`Text.isPrefixOf` Text -> Text
Text.toLower Text
match
              then TimeData -> Maybe TimeData
forall a. a -> Maybe a
Just TimeData
now
              else TimeData -> TimeData -> Maybe TimeData
intersect (Int -> TimeData
month Int
9) (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
cycleYear Int
0
            cycleYear :: Int -> TimeData
cycleYear = Grain -> Int -> TimeData
cycleNth Grain
TG.Year
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleBeginningOfYear :: Rule
ruleBeginningOfYear :: Rule
ruleBeginningOfYear = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"beginning of year"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"((at )?the )?(BOY|beginning of (the )?year)"
    ]
  , prod :: Production
prod = \[Token]
_ -> do
      TimeData
start <- TimeData -> TimeData -> Maybe TimeData
intersect (Int -> TimeData
month Int
1) (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth Grain
TG.Year Int
0
      TimeData
end <- TimeData -> TimeData -> Maybe TimeData
intersect (Int -> TimeData
month Int
4) (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth Grain
TG.Year Int
0
      Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end
  }

ruleEndOrBeginningOfWeek :: Rule
ruleEndOrBeginningOfWeek :: Rule
ruleEndOrBeginningOfWeek = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"at the beginning|end of <week>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(at the )?(beginning|end) of"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrainOfTime Grain
TG.Week
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (_:match1:_)):Token Dimension a
Time a
td:[Token]
_) -> do
        (Int
sd, Int
ed) <- case Text -> Text
Text.toLower Text
match1 of
          Text
"beginning" -> (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
1, Int
3)
          Text
"end"       -> (Int, Int) -> Maybe (Int, Int)
forall a. a -> Maybe a
Just (Int
5, Int
7)
          Text
_           -> Maybe (Int, Int)
forall a. Maybe a
Nothing
        TimeData
start <- TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
dayOfWeek Int
sd
        TimeData
end <- TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (TimeData -> Maybe TimeData) -> TimeData -> Maybe TimeData
forall a b. (a -> b) -> a -> b
$ Int -> TimeData
dayOfWeek Int
ed
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleClosest :: Rule
ruleClosest :: Rule
ruleClosest = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the closest <day> to <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the\\s+closest"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrainOfTime Grain
TG.Day
    , String -> PatternItem
regex String
"to"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \case
      (Token
_:Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> TimeData -> TimeData -> TimeData
predNthClosest Int
0 a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleNthClosest :: Rule
ruleNthClosest :: Rule
ruleNthClosest = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the <ordinal> closest <day> to <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , String -> PatternItem
regex String
"closest"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrainOfTime Grain
TG.Day
    , String -> PatternItem
regex String
"to"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \case
      (Token
_:Token
token:Token
_:Token Dimension a
Time a
td1:Token
_:Token Dimension a
Time a
td2:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> TimeData -> TimeData -> TimeData
predNthClosest (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) a
TimeData
td1 a
TimeData
td2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

rulePeriodicHolidays :: [Rule]
rulePeriodicHolidays :: [Rule]
rulePeriodicHolidays = [(Text, String, TimeData)] -> [Rule]
mkRuleHolidays
  -- Fixed dates, year over year
  [ ( Text
"Africa Day", String
"africa(n (freedom|liberation))? day", Int -> Int -> TimeData
monthDay Int
5 Int
25 )
  , ( Text
"Africa Industrialization Day", String
"africa industrialization day", Int -> Int -> TimeData
monthDay Int
11 Int
20 )
  , ( Text
"All Saints' Day", String
"all saints' day", Int -> Int -> TimeData
monthDay Int
11 Int
1 )
  , ( Text
"All Souls' Day", String
"all souls' day", Int -> Int -> TimeData
monthDay Int
11 Int
2 )
  , ( Text
"April Fools", String
"(april|all) fool'?s('? day)?", Int -> Int -> TimeData
monthDay Int
4 Int
1 )
  , ( Text
"Arabic Language Day", String
"arabic language day", Int -> Int -> TimeData
monthDay Int
12 Int
18 )
  , ( Text
"Assumption of Mary", String
"assumption of mary", Int -> Int -> TimeData
monthDay Int
8 Int
15 )
  , ( Text
"Boxing Day", String
"boxing day", Int -> Int -> TimeData
monthDay Int
12 Int
26 )
  , ( Text
"Chinese Language Day", String
"chinese language day", Int -> Int -> TimeData
monthDay Int
4 Int
20 )
  , ( Text
"Christmas", String
"(xmas|christmas)( day)?", Int -> Int -> TimeData
monthDay Int
12 Int
25 )
  , ( Text
"Christmas Eve", String
"(xmas|christmas)( day)?('s)? eve", Int -> Int -> TimeData
monthDay Int
12 Int
24 )
  , ( Text
"Day of Remembrance for all Victims of Chemical Warfare", String
"day of remembrance for all victims of chemical warfare", Int -> Int -> TimeData
monthDay Int
4 Int
29 )
  , ( Text
"Day of Remembrance of the Victims of the Rwanda Genocide", String
"day of remembrance of the victims of the rwanda genocide", Int -> Int -> TimeData
monthDay Int
4 Int
7 )
  , ( Text
"Day of the Seafarer", String
"day of the seafarer", Int -> Int -> TimeData
monthDay Int
6 Int
25 )
  , ( Text
"Earth Day", String
"earth day", Int -> Int -> TimeData
monthDay Int
4 Int
22 )
  , ( Text
"English Language Day", String
"english language day", Int -> Int -> TimeData
monthDay Int
4 Int
23 )
  , ( Text
"Epiphany", String
"Epiphany", Int -> Int -> TimeData
monthDay Int
1 Int
6 )
  , ( Text
"Feast of St Francis of Assisi", String
"feast of st\\.? francis of assisi", Int -> Int -> TimeData
monthDay Int
10 Int
4 )
  , ( Text
"Feast of the Immaculate Conception", String
"feast of the immaculate conception", Int -> Int -> TimeData
monthDay Int
12 Int
8 )
  , ( Text
"Global Day of Parents", String
"global day of parents", Int -> Int -> TimeData
monthDay Int
6 Int
1 )
  , ( Text
"Halloween", String
"hall?owe?en( day)?", Int -> Int -> TimeData
monthDay Int
10 Int
31 )
  , ( Text
"Human Rights Day", String
"human rights? day", Int -> Int -> TimeData
monthDay Int
12 Int
10 )
  , ( Text
"International Albinism Awareness Day", String
"international albinism awareness day", Int -> Int -> TimeData
monthDay Int
6 Int
13 )
  , ( Text
"International Anti-Corruption Day", String
"international anti(\\-|\\s)corruption day", Int -> Int -> TimeData
monthDay Int
12 Int
9 )
  , ( Text
"International Asteroid Day", String
"international asteroid day", Int -> Int -> TimeData
monthDay Int
6 Int
30 )
  , ( Text
"International Celebrate Bisexuality Day", String
"international celebrate bisexuality day", Int -> Int -> TimeData
monthDay Int
9 Int
23 )
  , ( Text
"International Chernobyl Disaster Remembrance Day", String
"international chernobyl disaster remembrance day", Int -> Int -> TimeData
monthDay Int
4 Int
26 )
  , ( Text
"International Civil Aviation Day", String
"international civil aviation day", Int -> Int -> TimeData
monthDay Int
12 Int
7 )
  , ( Text
"International Customs Day", String
"international customs day", Int -> Int -> TimeData
monthDay Int
1 Int
26 )
  , ( Text
"International Day Against Drug Abuse and Illicit Trafficking", String
"international day against drug abuse and illicit trafficking", Int -> Int -> TimeData
monthDay Int
6 Int
26 )
  , ( Text
"International Day against Nuclear Tests", String
"international day against nuclear tests", Int -> Int -> TimeData
monthDay Int
8 Int
29 )
  , ( Text
"International Day for Biological Diversity", String
"international day for biological diversity|world biodiversity day", Int -> Int -> TimeData
monthDay Int
5 Int
22 )
  , ( Text
"International Day for Monuments and Sites", String
"international day for monuments and sites", Int -> Int -> TimeData
monthDay Int
4 Int
18 )
  , ( Text
"International Day for Preventing the Exploitation of the Environment in War and Armed Conflict", String
"international day for preventing the exploitation of the environment in war and armed conflict", Int -> Int -> TimeData
monthDay Int
11 Int
6 )
  , ( Text
"International Day for South-South Cooperation", String
"international day for south(\\-|\\s)south cooperation", Int -> Int -> TimeData
monthDay Int
9 Int
12 )
  , ( Text
"International Day for Tolerance", String
"international day for tolerance", Int -> Int -> TimeData
monthDay Int
11 Int
16 )
  , ( Text
"International Day for the Abolition of Slavery", String
"international day for the abolition of slavery", Int -> Int -> TimeData
monthDay Int
12 Int
2 )
  , ( Text
"International Day for the Elimination of Racial Discrimination", String
"international day for the elimination of racial discrimination", Int -> Int -> TimeData
monthDay Int
3 Int
21 )
  , ( Text
"International Day for the Elimination of Sexual Violence in Conflict", String
"international day for the elimination of sexual violence in conflict", Int -> Int -> TimeData
monthDay Int
6 Int
19 )
  , ( Text
"International Day for the Elimination of Violence against Women", String
"international day for the elimination of violence against women", Int -> Int -> TimeData
monthDay Int
11 Int
25 )
  , ( Text
"International Day for the Eradication of Poverty", String
"international day for the eradication of poverty", Int -> Int -> TimeData
monthDay Int
10 Int
17 )
  , ( Text
"International Day for the Preservation of the Ozone Layer", String
"international day for the preservation of the ozone Layer", Int -> Int -> TimeData
monthDay Int
9 Int
16 )
  , ( Text
"International Day for the Remembrance of the Slave Trade and its Abolition", String
"international day for the remembrance of the slave trade and its abolition", Int -> Int -> TimeData
monthDay Int
8 Int
23 )
  , ( Text
"International Day for the Right to the Truth concerning Gross Human Rights Violations and for the Dignity of Victims", String
"international day for the right to the truth concerning gross human rights violations and for the dignity of victims", Int -> Int -> TimeData
monthDay Int
3 Int
24 )
  , ( Text
"International Day for the Total Elimination of Nuclear Weapons", String
"international day for the total elimination of nuclear weapons", Int -> Int -> TimeData
monthDay Int
9 Int
26 )
  , ( Text
"International Day in Support of Victims of Torture", String
"international day in support of victims of torture", Int -> Int -> TimeData
monthDay Int
6 Int
26 )
  , ( Text
"International Day of Charity", String
"international day of charity", Int -> Int -> TimeData
monthDay Int
9 Int
5 )
  , ( Text
"International Day of Commemoration in Memory of the Victims of the Holocaust", String
"international day of commemoration in memory of the victims of the holocaust", Int -> Int -> TimeData
monthDay Int
1 Int
27 )
  , ( Text
"International Day of Democracy", String
"international day of democracy", Int -> Int -> TimeData
monthDay Int
9 Int
15 )
  , ( Text
"International Day of Disabled Persons", String
"international day of disabled persons", Int -> Int -> TimeData
monthDay Int
12 Int
3 )
  , ( Text
"International Day of Families", String
"international day of families", Int -> Int -> TimeData
monthDay Int
5 Int
15 )
  , ( Text
"International Day of Family Remittances", String
"international day of family remittances", Int -> Int -> TimeData
monthDay Int
6 Int
16 )
  , ( Text
"International Day of Forests", String
"international day of forests", Int -> Int -> TimeData
monthDay Int
3 Int
21 )
  , ( Text
"International Day of Friendship", String
"international day of friendship", Int -> Int -> TimeData
monthDay Int
7 Int
30 )
  , ( Text
"International Day of Happiness", String
"international day of happiness", Int -> Int -> TimeData
monthDay Int
3 Int
20 )
  , ( Text
"International Day of Human Space Flight", String
"international day of human space flight", Int -> Int -> TimeData
monthDay Int
4 Int
12 )
  , ( Text
"International Day of Innocent Children Victims of Aggression", String
"international day of innocent children victims of aggression", Int -> Int -> TimeData
monthDay Int
6 Int
4 )
  , ( Text
"International Day of Non-Violence", String
"international day of non(\\-|\\s)violence", Int -> Int -> TimeData
monthDay Int
10 Int
2 )
  , ( Text
"International Day of Nowruz", String
"international day of nowruz", Int -> Int -> TimeData
monthDay Int
3 Int
21 )
  , ( Text
"International Day of Older Persons", String
"international day of older persons", Int -> Int -> TimeData
monthDay Int
10 Int
1 )
  , ( Text
"International Day of Peace", String
"international day of peace", Int -> Int -> TimeData
monthDay Int
9 Int
21 )
  , ( Text
"International Day of Persons with Disabilities", String
"international day of persons with disabilities", Int -> Int -> TimeData
monthDay Int
12 Int
3 )
  , ( Text
"International Day of Remembrance of Slavery Victims and the Transatlantic Slave Trade", String
"international day of remembrance of slavery victims and the transatlantic slave trade", Int -> Int -> TimeData
monthDay Int
3 Int
25 )
  , ( Text
"International Day of Rural Women", String
"international day of rural women", Int -> Int -> TimeData
monthDay Int
10 Int
15 )
  , ( Text
"International Day of Solidarity with Detained and Missing Staff Members", String
"international day of solidarity with detained and missing staff members", Int -> Int -> TimeData
monthDay Int
3 Int
25 )
  , ( Text
"International Day of Solidarity with the Palestinian People", String
"international day of solidarity with the palestinian people", Int -> Int -> TimeData
monthDay Int
11 Int
29 )
  , ( Text
"International Day of Sport for Development and Peace", String
"international day of sport for development and peace", Int -> Int -> TimeData
monthDay Int
4 Int
6 )
  , ( Text
"International Day of United Nations Peacekeepers", String
"international day of united nations peacekeepers", Int -> Int -> TimeData
monthDay Int
5 Int
29 )
  , ( Text
"International Day of Women and Girls in Science", String
"international day of women and girls in science", Int -> Int -> TimeData
monthDay Int
2 Int
11 )
  , ( Text
"International Day of Yoga", String
"international day of yoga", Int -> Int -> TimeData
monthDay Int
6 Int
21 )
  , ( Text
"International Day of Zero Tolerance for Female Genital Mutilation", String
"international day of zero tolerance for female genital mutilation", Int -> Int -> TimeData
monthDay Int
2 Int
6 )
  , ( Text
"International Day of the Girl Child", String
"international day of the girl child", Int -> Int -> TimeData
monthDay Int
10 Int
11 )
  , ( Text
"International Day of the Victims of Enforced Disappearances", String
"international day of the victims of enforced disappearances", Int -> Int -> TimeData
monthDay Int
8 Int
30 )
  , ( Text
"International Day of the World's Indigenous People", String
"international day of the world'?s indigenous people", Int -> Int -> TimeData
monthDay Int
8 Int
9 )
  , ( Text
"International Day to End Impunity for Crimes against Journalists", String
"international day to end impunity for crimes against journalists", Int -> Int -> TimeData
monthDay Int
11 Int
2 )
  , ( Text
"International Day to End Obstetric Fistula", String
"international day to end obstetric fistula", Int -> Int -> TimeData
monthDay Int
5 Int
23 )
  , ( Text
"International Day for Disaster Reduction", String
"iddr|international day for (natural )?disaster reduction", Int -> Int -> TimeData
monthDay Int
10 Int
13 )
  , ( Text
"International Human Solidarity Day", String
"international human solidarity day", Int -> Int -> TimeData
monthDay Int
12 Int
20 )
  , ( Text
"International Jazz Day", String
"international jazz day", Int -> Int -> TimeData
monthDay Int
4 Int
30 )
  , ( Text
"International Literacy Day", String
"international literacy day", Int -> Int -> TimeData
monthDay Int
9 Int
8 )
  , ( Text
"International Men's Day", String
"international men'?s day", Int -> Int -> TimeData
monthDay Int
11 Int
19 )
  , ( Text
"International Migrants Day", String
"international migrants day", Int -> Int -> TimeData
monthDay Int
12 Int
18 )
  , ( Text
"International Mother Language Day", String
"international mother language day", Int -> Int -> TimeData
monthDay Int
2 Int
21 )
  , ( Text
"International Mountain Day", String
"international mountain day", Int -> Int -> TimeData
monthDay Int
12 Int
11 )
  , ( Text
"International Nurses Day", String
"international nurses day", Int -> Int -> TimeData
monthDay Int
5 Int
12 )
  , ( Text
"International Overdose Awareness Day", String
"international overdose awareness day", Int -> Int -> TimeData
monthDay Int
8 Int
31 )
  , ( Text
"International Volunteer Day for Economic and Social Development", String
"international volunteer day for economic and social development", Int -> Int -> TimeData
monthDay Int
12 Int
5 )
  , ( Text
"International Widows' Day", String
"international widows'? day", Int -> Int -> TimeData
monthDay Int
6 Int
23 )
  , ( Text
"International Women's Day", String
"international women'?s day", Int -> Int -> TimeData
monthDay Int
3 Int
8 )
  , ( Text
"International Youth Day", String
"international youth day", Int -> Int -> TimeData
monthDay Int
8 Int
12 )
  , ( Text
"May Day", String
"may day", Int -> Int -> TimeData
monthDay Int
5 Int
1 )
  , ( Text
"Nelson Mandela Day", String
"nelson mandela day", Int -> Int -> TimeData
monthDay Int
7 Int
18 )
  , ( Text
"New Year's Day", String
"new year'?s?( day)?", Int -> Int -> TimeData
monthDay  Int
1  Int
1 )
  , ( Text
"New Year's Eve", String
"new year'?s? eve", Int -> Int -> TimeData
monthDay Int
12 Int
31 )
  , ( Text
"Orthodox Christmas Day", String
"orthodox christmas day", Int -> Int -> TimeData
monthDay Int
1 Int
7 )
  , ( Text
"Orthodox New Year", String
"orthodox new year", Int -> Int -> TimeData
monthDay Int
1 Int
14 )
  , ( Text
"Public Service Day", String
"public service day", Int -> Int -> TimeData
monthDay Int
6 Int
23 )
  , ( Text
"St. George's Day", String
"(saint|st\\.?) george'?s day|feast of saint george", Int -> Int -> TimeData
monthDay Int
4 Int
23 )
  , ( Text
"St Patrick's Day", String
"(saint|st\\.?) (patrick|paddy)'?s day", Int -> Int -> TimeData
monthDay Int
3 Int
17 )
  , ( Text
"St. Stephen's Day", String
"(saint|st\\.?) stephen'?s day", Int -> Int -> TimeData
monthDay Int
12 Int
26 )
  , ( Text
"Time of Remembrance and Reconciliation for Those Who Lost Their Lives during the Second World War", String
"time of remembrance and reconciliation for those who lost their lives during the second world war", Int -> Int -> TimeData
monthDay Int
5 Int
8 )
  , ( Text
"Ugadi", String
"y?ugadi|samvatsaradi|chaitra sukh?ladi", TimeData
ugadi)
  , ( Text
"United Nations Day", String
"united nations day", Int -> Int -> TimeData
monthDay Int
10 Int
24 )
  , ( Text
"United Nations' Mine Awareness Day", String
"united nations'? mine awareness day", Int -> Int -> TimeData
monthDay Int
4 Int
4 )
  , ( Text
"United Nations' World Health Day", String
"united nations'? world health day", Int -> Int -> TimeData
monthDay Int
4 Int
7 )
  , ( Text
"Universal Children's Day", String
"universal children'?s day", Int -> Int -> TimeData
monthDay Int
11 Int
20 )
  , ( Text
"Valentine's Day", String
"valentine'?s?( day)?", Int -> Int -> TimeData
monthDay Int
2 Int
14 )
  , ( Text
"World AIDS Day", String
"world aids day", Int -> Int -> TimeData
monthDay Int
12 Int
1 )
  , ( Text
"World Autism Awareness Day", String
"world autism awareness day", Int -> Int -> TimeData
monthDay Int
4 Int
2 )
  , ( Text
"World Autoimmune Arthritis Day", String
"world autoimmune arthritis day", Int -> Int -> TimeData
monthDay Int
5 Int
20 )
  , ( Text
"World Blood Donor Day", String
"world blood donor day", Int -> Int -> TimeData
monthDay Int
6 Int
14 )
  , ( Text
"World Book and Copyright Day", String
"world book and copyright day", Int -> Int -> TimeData
monthDay Int
4 Int
23 )
  , ( Text
"World Braille Day", String
"world braille day", Int -> Int -> TimeData
monthDay Int
1 Int
4 )
  , ( Text
"World Cancer Day", String
"world cancer day", Int -> Int -> TimeData
monthDay Int
2 Int
4 )
  , ( Text
"World Cities Day", String
"world cities day", Int -> Int -> TimeData
monthDay Int
10 Int
31 )
  , ( Text
"World CP Day", String
"world (cerebral palsy| cp) day", Int -> Int -> TimeData
monthDay Int
10 Int
6 )
  , ( Text
"World Day Against Child Labour", String
"world day against child labour", Int -> Int -> TimeData
monthDay Int
6 Int
12 )
  , ( Text
"World Day against Trafficking in Persons", String
"world day against trafficking in persons", Int -> Int -> TimeData
monthDay Int
7 Int
30 )
  , ( Text
"World Day for Audiovisual Heritage", String
"world day for audiovisual heritage", Int -> Int -> TimeData
monthDay Int
10 Int
27 )
  , ( Text
"World Day for Cultural Diversity for Dialogue and Development", String
"world day for cultural diversity for dialogue and development", Int -> Int -> TimeData
monthDay Int
5 Int
21 )
  , ( Text
"World Day for Safety and Health at Work", String
"world day for safety and health at work", Int -> Int -> TimeData
monthDay Int
4 Int
28 )
  , ( Text
"World Day for the Abolition of Slavery", String
"world day for the abolition of slavery", Int -> Int -> TimeData
monthDay Int
12 Int
2 )
  , ( Text
"World Day of Social Justice", String
"world day of social justice", Int -> Int -> TimeData
monthDay Int
2 Int
20 )
  , ( Text
"World Day of the Sick", String
"world day of the sick", Int -> Int -> TimeData
monthDay Int
2 Int
11 )
  , ( Text
"World Day to Combat Desertification and Drought", String
"world day to combat desertification and drought", Int -> Int -> TimeData
monthDay Int
6 Int
17 )
  , ( Text
"World Development Information Day", String
"world development information day", Int -> Int -> TimeData
monthDay Int
10 Int
24 )
  , ( Text
"World Diabetes Day", String
"world diabetes day", Int -> Int -> TimeData
monthDay Int
11 Int
14 )
  , ( Text
"World Down Syndrome Day", String
"world down syndrome day", Int -> Int -> TimeData
monthDay Int
3 Int
21 )
  , ( Text
"World Elder Abuse Awareness Day", String
"world elder abuse awareness day", Int -> Int -> TimeData
monthDay Int
6 Int
15 )
  , ( Text
"World Environment Day", String
"world environment day", Int -> Int -> TimeData
monthDay Int
6 Int
5 )
  , ( Text
"World Food Day", String
"world food day", Int -> Int -> TimeData
monthDay Int
10 Int
16 )
  , ( Text
"World Genocide Commemoration Day", String
"world genocide commemoration day", Int -> Int -> TimeData
monthDay Int
12 Int
9 )
  , ( Text
"World Heart Day", String
"world heart day", Int -> Int -> TimeData
monthDay Int
9 Int
29 )
  , ( Text
"World Hepatitis Day", String
"world hepatitis day", Int -> Int -> TimeData
monthDay Int
7 Int
28 )
  , ( Text
"World Humanitarian Day", String
"world humanitarian day", Int -> Int -> TimeData
monthDay Int
8 Int
19 )
  , ( Text
"World Information Society Day", String
"world information society day", Int -> Int -> TimeData
monthDay Int
5 Int
17 )
  , ( Text
"World Intellectual Property Day", String
"world intellectual property day", Int -> Int -> TimeData
monthDay Int
4 Int
26 )
  , ( Text
"World Malaria Day", String
"world malaria day", Int -> Int -> TimeData
monthDay Int
4 Int
25 )
  , ( Text
"World Mental Health Day", String
"world mental health day", Int -> Int -> TimeData
monthDay Int
10 Int
10 )
  , ( Text
"World Meteorological Day", String
"world meteorological day", Int -> Int -> TimeData
monthDay Int
3 Int
23 )
  , ( Text
"World No Tobacco Day", String
"world no tobacco day", Int -> Int -> TimeData
monthDay Int
5 Int
31 )
  , ( Text
"World Oceans Day", String
"world oceans day", Int -> Int -> TimeData
monthDay Int
6 Int
8 )
  , ( Text
"World Ovarian Cancer Day", String
"world ovarian cancer day", Int -> Int -> TimeData
monthDay Int
5 Int
8 )
  , ( Text
"World Pneumonia Day", String
"world pneumonia day", Int -> Int -> TimeData
monthDay Int
11 Int
12 )
  , ( Text
"World Poetry Day", String
"world poetry day", Int -> Int -> TimeData
monthDay Int
3 Int
21 )
  , ( Text
"World Population Day", String
"world population day", Int -> Int -> TimeData
monthDay Int
7 Int
11 )
  , ( Text
"World Post Day", String
"world post day", Int -> Int -> TimeData
monthDay Int
10 Int
9 )
  , ( Text
"World Prematurity Day", String
"world prematurity day", Int -> Int -> TimeData
monthDay Int
11 Int
17 )
  , ( Text
"World Press Freedom Day", String
"world press freedom day", Int -> Int -> TimeData
monthDay Int
5 Int
3 )
  , ( Text
"World Rabies Day", String
"world rabies day", Int -> Int -> TimeData
monthDay Int
9 Int
28 )
  , ( Text
"World Radio Day", String
"world radio day", Int -> Int -> TimeData
monthDay Int
2 Int
13 )
  , ( Text
"World Refugee Day", String
"world refugee day", Int -> Int -> TimeData
monthDay Int
6 Int
20 )
  , ( Text
"World Science Day for Peace and Development", String
"world science day for peace and development", Int -> Int -> TimeData
monthDay Int
11 Int
10 )
  , ( Text
"World Sexual Health Day", String
"world sexual health day", Int -> Int -> TimeData
monthDay Int
9 Int
4 )
  , ( Text
"World Soil Day", String
"world soil day", Int -> Int -> TimeData
monthDay Int
12 Int
5 )
  , ( Text
"World Stroke Day", String
"world stroke day", Int -> Int -> TimeData
monthDay Int
10 Int
29 )
  , ( Text
"World Suicide Prevention Day", String
"world suicide prevention day", Int -> Int -> TimeData
monthDay Int
9 Int
10 )
  , ( Text
"World Teachers' Day", String
"world teachers'? day", Int -> Int -> TimeData
monthDay Int
10 Int
5 )
  , ( Text
"World Television Day", String
"world television day", Int -> Int -> TimeData
monthDay Int
11 Int
21 )
  , ( Text
"World Toilet Day", String
"world toilet day", Int -> Int -> TimeData
monthDay Int
11 Int
19 )
  , ( Text
"World Tourism Day", String
"world tourism day", Int -> Int -> TimeData
monthDay Int
9 Int
27 )
  , ( Text
"World Tuberculosis Day", String
"world tuberculosis day", Int -> Int -> TimeData
monthDay Int
3 Int
24 )
  , ( Text
"World Tuna Day", String
"world tuna day", Int -> Int -> TimeData
monthDay Int
5 Int
2 )
  , ( Text
"World Vegan Day", String
"world vegan day", Int -> Int -> TimeData
monthDay Int
11 Int
1 )
  , ( Text
"World Vegetarian Day", String
"world vegetarian day", Int -> Int -> TimeData
monthDay Int
10 Int
1 )
  , ( Text
"World Water Day", String
"world water day", Int -> Int -> TimeData
monthDay Int
3 Int
22 )
  , ( Text
"World Wetlands Day", String
"world wetlands day", Int -> Int -> TimeData
monthDay Int
2 Int
2 )
  , ( Text
"World Wildlife Day", String
"world wildlife day", Int -> Int -> TimeData
monthDay Int
3 Int
3 )
  , ( Text
"World Youth Skills Day", String
"world youth skills day", Int -> Int -> TimeData
monthDay Int
7 Int
15 )
  , ( Text
"Zero Discrimination Day", String
"zero discrimination day", Int -> Int -> TimeData
monthDay Int
3 Int
1 )

  -- Fixed day/week/month, year over year
  , ( Text
"Commonwealth Day", String
"commonwealth day", Int -> Int -> Int -> TimeData
nthDOWOfMonth Int
2 Int
1 Int
3 )
  , ( Text
"Day of Remembrance for Road Traffic Victims"
    , String
"(world )?day of remembrance for road traffic victims"
    , Int -> Int -> Int -> TimeData
nthDOWOfMonth Int
3 Int
7 Int
11 )
  , ( Text
"International Day of Cooperatives"
    , String
"international day of co\\-?operatives", Int -> Int -> Int -> TimeData
nthDOWOfMonth Int
1 Int
6 Int
7 )
  , ( Text
"Martin Luther King's Day"
    , String
"(MLK|Martin Luther King('?s)?,?)( Jr\\.?| Junior)? day|(civil|idaho human) rights day"
    , Int -> Int -> Int -> TimeData
nthDOWOfMonth Int
3 Int
1 Int
1
    )

  -- The day after Thanksgiving (not always the fourth Friday of November)
  , ( Text
"Black Friday", String
"black frid?day"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
1 (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Int -> TimeData
nthDOWOfMonth Int
4 Int
4 Int
11
    )
  , ( Text
"World Habitat Day", String
"world habitat day", Int -> Int -> Int -> TimeData
nthDOWOfMonth Int
1 Int
1 Int
10 )
  , ( Text
"World Kidney Day", String
"world kidney day", Int -> Int -> Int -> TimeData
nthDOWOfMonth Int
2 Int
4 Int
3 )
  , ( Text
"World Leprosy Day", String
"world leprosy day"
    , TimeData -> TimeData -> TimeData
predLastOf (Int -> TimeData
dayOfWeek Int
7) (Int -> TimeData
month Int
1) )
  , ( Text
"World Maritime Day", String
"world maritime day"
    , TimeData -> TimeData -> TimeData
predLastOf (Int -> TimeData
dayOfWeek Int
4) (Int -> TimeData
month Int
9) )
  , ( Text
"World Migratory Bird Day", String
"world migratory bird day"
    , Int -> Int -> Int -> TimeData
nthDOWOfMonth Int
2 Int
6 Int
5 )
  , ( Text
"World Philosophy Day", String
"world philosophy day", Int -> Int -> Int -> TimeData
nthDOWOfMonth Int
3 Int
4 Int
11 )
  , ( Text
"World Religion Day", String
"world religion day", Int -> Int -> Int -> TimeData
nthDOWOfMonth Int
3 Int
7 Int
1 )
  , ( Text
"World Sight Day", String
"world sight day", Int -> Int -> Int -> TimeData
nthDOWOfMonth Int
2 Int
4 Int
10 )

  -- Other
  , ( Text
"Boss's Day", String
"boss'?s?( day)?"
    , Int -> TimeData -> TimeData -> TimeData
predNthClosest Int
0 TimeData
weekday (Int -> Int -> TimeData
monthDay Int
10 Int
16) )
  ]

ruleComputedHolidays :: [Rule]
ruleComputedHolidays :: [Rule]
ruleComputedHolidays = [(Text, String, TimeData)] -> [Rule]
mkRuleHolidays
  [ ( Text
"Ascension Day", String
"ascension\\s+(thurs)?day"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
39 TimeData
easterSunday )
  , ( Text
"Ash Wednesday", String
"ash\\s+wednesday|carnival"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
46) TimeData
easterSunday )
  , ( Text
"Ashura", String
"(day of )?ashura"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
9 TimeData
muharram )
  , ( Text
"Bhai Dooj", String
"bhai(ya)?\\s+d(u|oo)j|bhau\\-beej|bhai\\s+(tika|phonta)"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
4 TimeData
dhanteras )
  -- 6th day after Diwali
  , ( Text
"Chhath", String
"chhathi?|chhath (parv|puja)|dala (chhath|puja)|surya shashthi"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
8 TimeData
dhanteras )
  , ( Text
"Boghi", String
"boghi|bogi\\s+pandigai"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
1) TimeData
thaiPongal )
  , ( Text
"Chinese New Year", String
"chinese\\s+(lunar\\s+)?new\\s+year('?s(\\s+day)?)?"
    , TimeData
chineseNewYear )
  , ( Text
"Clean Monday"
    , String
"(orthodox\\s+)?(ash|clean|green|pure|shrove)\\s+monday|monday of lent"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
48) TimeData
orthodoxEaster )
  , ( Text
"Corpus Christi", String
"(the feast of )?corpus\\s+christi"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
60 TimeData
easterSunday )
  , ( Text
"Dhanteras", String
"dhanatrayodashi|dhanteras|dhanvantari\\s+trayodashi"
    , TimeData
dhanteras )
  , ( Text
"Diwali", String
"deepavali|diwali|lakshmi\\s+puja"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
2 TimeData
dhanteras )
  , ( Text
"Durga Ashtami", String
"(durga|maha)(\\s+a)?shtami"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
7 TimeData
navaratri )
  , ( Text
"Easter Monday", String
"easter\\s+mon(day)?"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
1 TimeData
easterSunday )
  , ( Text
"Easter Sunday", String
"easter(\\s+sun(day)?)?", TimeData
easterSunday )
  , ( Text
"Eid al-Adha", String
"bakr[\\-\\s]e?id|e?id [au]l\\-adha|sacrifice feast"
    , TimeData
eidalAdha )
  , ( Text
"Eid al-Fitr", String
"eid al\\-fitr", TimeData
eidalFitr )
  , ( Text
"Govardhan Puja", String
"govardhan\\s+puja|annak(u|oo)t"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
3 TimeData
dhanteras )
  , ( Text
"Good Friday", String
"(good|great|holy)\\s+fri(day)?"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
2) TimeData
easterSunday )
  , ( Text
"Guru Gobind Singh Jayanti"
    , String
"guru\\s+(gobind|govind)\\s+singh\\s+(birthday|jayanti)"
    , TimeData
guruGobindSinghJayanti )
  , ( Text
"Holi", String
"(rangwali )?holi|dhuleti|dhulandi|phagwah"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
39 TimeData
vasantPanchami )
  , ( Text
"Holika Dahan", String
"holika dahan|kamudu pyre|chhoti holi"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
38 TimeData
vasantPanchami )
  , ( Text
"Holy Saturday"
    , String
"(black|holy (and great )?|joyous)sat(urday)?|the great sabbath|easter eve"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
1) TimeData
easterSunday )
  , ( Text
"Islamic New Year", String
"(arabic|hijri|islamic) new year|amun jadid|muharram"
    , TimeData
muharram )
  , ( Text
"Isra and Mi'raj"
    , String
"isra and mi'raj|(the )?prophet'?s'? ascension|(the )?ascension to heaven|the night journey"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
26 TimeData
rajab
    )
  , ( Text
"Jumu'atul-Wida", String
"jumu'atul\\-widaa?'?|jamat[\\-\\s]ul[\\-\\s]vida"
    , Int -> TimeData -> TimeData -> TimeData
predNthAfter (-Int
1) (Int -> TimeData
dayOfWeek Int
5) TimeData
eidalFitr )
  , ( Text
"Kaanum Pongal", String
"(kaanum|kanni)\\s+pongal"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
2 TimeData
thaiPongal )
  , ( Text
"Lag BaOmer", String
"lag b[a']omer", TimeData
lagBaOmer )
  , ( Text
"Vaisakhi", String
"mesadi|[bv]aisakhi|vaisakhadi|vasakhi|vaishakhi", TimeData
vaisakhi)
  , ( Text
"Laylat al-Qadr"
    , String
"laylat al[\\-\\s][qk]adr|night of (destiny|measures|power|value)"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
26 TimeData
ramadan )
  , ( Text
"Lazarus Saturday", String
"lazarus\\s+saturday"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
8) TimeData
orthodoxEaster )
  , ( Text
"Maha Navami", String
"maha\\s+navami", Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
8 TimeData
navaratri )
  , ( Text
"Maha Saptami", String
"maha\\s+saptami", Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
6 TimeData
navaratri )
  , ( Text
"Mattu Pongal", String
"maa?ttu\\s+pongal"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
1 TimeData
thaiPongal )
  , ( Text
"Maundy Thursday"
    , String
"(covenant|(great and )?holy|maundy|sheer)\\s+thu(rsday)?|thu(rsday)? of mysteries"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
3) TimeData
easterSunday )
  , ( Text
"Mawlid"
    , String
"mawlid(\\s+al\\-nab(awi|i\\s+al\\-sharif))?|mevli[dt]|mulud|birth(day)? of (the )?prophet( muhammad)?|(the )?prophet's birthday"
    , TimeData
mawlid )
  , ( Text
"Naraka Chaturdashi"
    , String
"naraka? (nivaran )?chaturdashi|(kali|roop) chaudas|choti diwali"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
1 TimeData
dhanteras )
  , ( Text
"Orthodox Easter Monday", String
"orthodox\\s+easter\\s+mon(day)?"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
1 TimeData
orthodoxEaster )
  , ( Text
"Orthodox Easter Sunday", String
"orthodox\\s+easter(\\s+sun(day)?)?|pascha?"
    , TimeData
orthodoxEaster )
  , ( Text
"Orthodox Holy Saturday", String
"orthodox\\s+holy\\s+sat(urday)?|the great sabbath"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
1) TimeData
orthodoxEaster )
  , ( Text
"Orthodox Good Friday", String
"orthodox\\s+(great|good)(\\s+and\\s+holy)?\\s+friday"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
2) TimeData
orthodoxEaster )
  , ( Text
"Orthodox Palm Sunday", String
"orthodox\\s+(branch|palm|yew)\\s+sunday"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
7) TimeData
orthodoxEaster )
  , ( Text
"Palm Sunday", String
"(branch|palm|yew)\\s+sunday"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
7) TimeData
easterSunday )
  , ( Text
"Pentecost", String
"pentecost|white sunday|whitsunday"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
49 TimeData
easterSunday )
  , ( Text
"Purim", String
"purim", TimeData
purim )
  , ( Text
"Raksha Bandhan", String
"raksha(\\s+)?bandhan|rakhi", TimeData
rakshaBandhan )
  , ( Text
"Rama Navami", String
"rama\\s+navami", TimeData
ramaNavami)
  , ( Text
"Ganesh Chaturthi", String
"(ganesh|vinayaka)\\s+chaturthi", TimeData
ganeshChaturthi )
  , ( Text
"Ratha-Yatra", String
"ratha(\\-|\\s+)?yatra|rathjatra|chariot\\s+festival"
    , TimeData
rathaYatra )
  , ( Text
"Pargat Diwas", String
"pargat diwas|(maharishi )?valmiki jayanti", TimeData
pargatDiwas )
  , ( Text
"Mahavir Jayanti", String
"(mahavir|mahaveer) (jayanti|janma kalyanak)"
    , TimeData
mahavirJayanti )
  , ( Text
"Maha Shivaratri", String
"maha(\\s+)?shivaratri", TimeData
mahaShivaRatri)
  , ( Text
"Dayananda Saraswati Jayanti",String
"((maharishi|swami) )?(dayananda )?saraswati jayanti"
    , TimeData
saraswatiJayanti )
  , ( Text
"Karva Chauth", String
"karva\\s+chauth|karaka\\s+chaturthi"
    , TimeData
karvaChauth)
  , ( Text
"Krishna Janmashtami", String
"(krishna )?janmashtami|gokulashtami", TimeData
krishnaJanmashtami )
  , ( Text
"Shemini Atzeret", String
"shemini\\s+atzeret"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
21 TimeData
roshHashana )
  , ( Text
"Shrove Tuesday", String
"pancake (tues)?day|shrove tuesday|mardi gras"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
47) TimeData
easterSunday )
  , ( Text
"Shushan Purim", String
"shushan\\s+purim", Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
1 TimeData
purim )
  , ( Text
"Simchat Torah", String
"simc?hat\\s+torah"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
22 TimeData
roshHashana )
  , ( Text
"Thai Pongal"
    , String
"(thai )?pongal|pongal pandigai|(makara? |magha )?sankranth?i|maghi"
    , TimeData
thaiPongal )
  , ( Text
"Thiru Onam", String
"(thiru(v|\\s+))?onam", TimeData
thiruOnam )
  , ( Text
"Tisha B'Av", String
"tisha b'av", TimeData
tishaBAv )
  , ( Text
"Trinity Sunday", String
"trinity\\s+sunday"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
56 TimeData
easterSunday )
  , ( Text
"Vasant Panchami", String
"[bv]asant\\s+panchami", TimeData
vasantPanchami )
  , ( Text
"Vijayadashami", String
"dasara|duss(eh|he)ra|vijayadashami"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
9 TimeData
navaratri )
  -- 15th day of Shevat
  , ( Text
"Tu BiShvat", String
"tu b[i']shvat", TimeData
tuBishvat )
  -- day of the full moon in May in the Gregorian calendar
  , ( Text
"Vesak", String
"v(e|ai)sak(ha)?|buddha (day|purnima)", TimeData
vesak )
  , ( Text
"Yom Ha'atzmaut", String
"yom ha'?atzmaut", TimeData
yomHaatzmaut )
  , ( Text
"Yom HaShoah"
    , String
"yom hashoah|yom hazikaron lashoah ve-lag'vurah|holocaust (remembrance )?day"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
12 TimeData
passover )
  , ( Text
"Yom Kippur", String
"yom\\s+kippur", Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
9 TimeData
roshHashana )
  , ( Text
"Whit Monday", String
"(pentecost|whit)\\s+monday|monday of the holy spirit"
    , Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
50 TimeData
easterSunday )
  -- Rabindra Jayanti 25th day of the Bengali month of Boishakh
  , ( Text
"Rabindra Jayanti", String
"rabindra(nath)?\\s+jayanti", TimeData
rabindraJayanti )
  , (Text
"Guru Ravidass Jayanti", String
"guru\\s+ravidass?\\s+(birthday|jayanti)"
    , TimeData
ravidassJayanti )
  ]

ruleComputedHolidays' :: [Rule]
ruleComputedHolidays' :: [Rule]
ruleComputedHolidays' = [(Text, String, Maybe TimeData)] -> [Rule]
mkRuleHolidays'
  [ ( Text
"Global Youth Service Day", String
"global youth service day|gysd"
    , let start :: TimeData
start = TimeData
globalYouthServiceDay
          end :: TimeData
end = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
2 TimeData
globalYouthServiceDay
        in TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end )
  , ( Text
"Great Lent", String
"great\\s+(fast|lent)"
    , let start :: TimeData
start = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
48) TimeData
orthodoxEaster
          end :: TimeData
end = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
9) TimeData
orthodoxEaster
        in TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end )
  , ( Text
"Hanukkah", String
"c?hann?ukk?ah"
    , let start :: TimeData
start = TimeData
chanukah
          end :: TimeData
end = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
7 TimeData
chanukah
        in TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end )
  , ( Text
"Lent", String
"lent"
    , let start :: TimeData
start = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
46) TimeData
easterSunday
          end :: TimeData
end = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
1) TimeData
easterSunday
        in TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end )
  , ( Text
"Navaratri", String
"durga\\s+puja|durgotsava|nava?rath?ri"
    , let start :: TimeData
start = TimeData
navaratri
          end :: TimeData
end = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
9 TimeData
navaratri
        in TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end )
  , ( Text
"Passover", String
"passover|pesa[ck]?h"
    , let start :: TimeData
start = TimeData
passover
          end :: TimeData
end = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
8 TimeData
passover
        in TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end )
  , ( Text
"Ramadan", String
"rama[dt]h?an|ramzaa?n"
    , let start :: TimeData
start = TimeData
ramadan
          end :: TimeData
end = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day (-Int
1) TimeData
eidalFitr
        in TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end )
  , ( Text
"Rosh Hashanah", String
"rosh hashann?ah?|yom teruah"
    , let start :: TimeData
start = TimeData
roshHashana
          end :: TimeData
end = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
2 TimeData
roshHashana
        in TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end )
  , ( Text
"Shavuot", String
"feast of weeks|shavu'?oth?|shovuos"
    , let start :: TimeData
start = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
50 TimeData
passover
          end :: TimeData
end = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
52 TimeData
passover
        in TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end )
  , ( Text
"Sukkot", String
"feast of (booths|tabernacles|the ingathering)|su[ck]{2}o[st]"
    , let start :: TimeData
start = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
14 TimeData
roshHashana
          end :: TimeData
end = Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Day Int
22 TimeData
roshHashana
        in TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
start TimeData
end )
  -- Does not account for leap years, so every 365 days.
  , ( Text
"Parsi New Year", String
"parsi new year|jamshedi navroz"
    , Int -> (Integer, Int, Int) -> Maybe TimeData
predEveryNDaysFrom Int
365 (Integer
2020, Int
8, Int
16)
    )
  , ( Text
"Earth Hour", String
"earth hour"
    , Maybe TimeData
computeEarthHour )
  , ( Text
"King's Day", String
"king's day|koningsdag"
    , Maybe TimeData
computeKingsDay )
  ]

ruleCycleThisLastNext :: Rule
ruleCycleThisLastNext :: Rule
ruleCycleThisLastNext = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"this|last|next <cycle>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(this|current|coming|next|(the( following)?)|last|past|previous|upcoming)"
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    ]
  , prod :: Production
prod = \case
      (
        Token Dimension a
RegexMatch (GroupMatch (match:_)):
        Token Dimension a
TimeGrain a
grain:
        [Token]
_) ->
          case Text -> Text
Text.toLower Text
match of
            Text
"this"          -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
grain Int
0
            Text
"coming"        -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
grain Int
1
            Text
"current"       -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
grain Int
0
            Text
"last"          -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
grain (Int -> TimeData) -> Int -> TimeData
forall a b. (a -> b) -> a -> b
$ - Int
1
            Text
"past"          -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
grain (Int -> TimeData) -> Int -> TimeData
forall a b. (a -> b) -> a -> b
$ - Int
1
            Text
"previous"      -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
grain (Int -> TimeData) -> Int -> TimeData
forall a b. (a -> b) -> a -> b
$ - Int
1
            Text
"next"          -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
grain Int
1
            Text
"upcoming"      -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
grain Int
1
            Text
"the following" -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
grain Int
1
            Text
"the"           -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
grain Int
0
            Text
_ -> Maybe Token
forall a. Maybe a
Nothing
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDOMOfTimeMonth :: Rule
ruleDOMOfTimeMonth :: Rule
ruleDOMOfTimeMonth = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<day-of-month> (ordinal or number) of <month>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isDOMValue
    , String -> PatternItem
regex String
"of( the)?"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrainOfTime Grain
TG.Month
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token
_:Token Dimension a
Time a
td:[Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> Token -> Maybe TimeData
intersectDOM a
TimeData
td Token
token
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleTheAfterBeforeTime :: Rule
ruleCycleTheAfterBeforeTime :: Rule
ruleCycleTheAfterBeforeTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the <cycle> after|before <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    , String -> PatternItem
regex String
"(after|before)"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (  Token
_
       : Token Dimension a
TimeGrain a
grain
       : Token Dimension a
RegexMatch (GroupMatch (match:_))
       : Token Dimension a
Time a
td
       : [Token]
_) ->
        let n :: Int
n = if Text -> Text
Text.toLower Text
match Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"after" then Int
1 else - Int
1 in
          TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False a
Grain
grain Int
n a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleAfterBeforeTime :: Rule
ruleCycleAfterBeforeTime :: Rule
ruleCycleAfterBeforeTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<cycle> after|before <time>"
  , pattern :: Pattern
pattern =
    [ Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    , String -> PatternItem
regex String
"(after|before)"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
TimeGrain a
grain:
       Token Dimension a
RegexMatch (GroupMatch (match:_)):
       Token Dimension a
Time a
td:
       [Token]
_) ->
        let n :: Int
n = if Text -> Text
Text.toLower Text
match Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"after" then Int
1 else - Int
1 in
          TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False a
Grain
grain Int
n a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleOrdinalOfTime :: Rule
ruleCycleOrdinalOfTime :: Rule
ruleCycleOrdinalOfTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<ordinal> <cycle> of <time>"
  , pattern :: Pattern
pattern =
    [ Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    , String -> PatternItem
regex String
"of|in|from"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token Dimension a
TimeGrain a
grain:Token
_:Token Dimension a
Time a
td:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True a
Grain
grain (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleLastOrdinalOfTime :: Rule
ruleCycleLastOrdinalOfTime :: Rule
ruleCycleLastOrdinalOfTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<ordinal> last <cycle> of <time>"
  , pattern :: Pattern
pattern =
    [ Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , String -> PatternItem
regex String
"last"
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    , String -> PatternItem
regex String
"of|in|from"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token
_:Token Dimension a
TimeGrain a
grain:Token
_:Token Dimension a
Time a
td:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True a
Grain
grain (-Int
n) (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True (TimeData -> Grain
timeGrain a
TimeData
td) Int
1 a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleTheOrdinalOfTime :: Rule
ruleCycleTheOrdinalOfTime :: Rule
ruleCycleTheOrdinalOfTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the <ordinal> <cycle> of <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    , String -> PatternItem
regex String
"of|in|from"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token
token:Token Dimension a
TimeGrain a
grain:Token
_:Token Dimension a
Time a
td:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True a
Grain
grain (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleTheLastOrdinalOfTime :: Rule
ruleCycleTheLastOrdinalOfTime :: Rule
ruleCycleTheLastOrdinalOfTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the <ordinal> last <cycle> of <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , String -> PatternItem
regex String
"last"
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    , String -> PatternItem
regex String
"of|in|from"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token
token:Token
_:Token Dimension a
TimeGrain a
grain:Token
_:Token Dimension a
Time a
td:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True a
Grain
grain (-Int
n) (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True (TimeData -> Grain
timeGrain a
TimeData
td) Int
1 a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleTheOfTimeGrain :: Rule
ruleCycleTheOfTimeGrain :: Rule
ruleCycleTheOfTimeGrain = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the <cycle> of the <time grain>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    , String -> PatternItem
regex String
"of( the)?"
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
TimeGrain a
grain:Token
_:Token Dimension a
TimeGrain a
time:[Token]
_) ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True a
Grain
grain Int
0 (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
time Int
0
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleTheOfTime :: Rule
ruleCycleTheOfTime :: Rule
ruleCycleTheOfTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the <cycle> of <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    , String -> PatternItem
regex String
"of"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
TimeGrain a
grain:Token
_:Token Dimension a
Time a
td:[Token]
_) ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True a
Grain
grain Int
0 a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleOrdinalAfterTime :: Rule
ruleCycleOrdinalAfterTime :: Rule
ruleCycleOrdinalAfterTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<ordinal> <cycle> after <time>"
  , pattern :: Pattern
pattern =
    [ Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    , String -> PatternItem
regex String
"after"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token Dimension a
TimeGrain a
grain:Token
_:Token Dimension a
Time a
td:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True a
Grain
grain (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleTheOrdinalAfterTime :: Rule
ruleCycleTheOrdinalAfterTime :: Rule
ruleCycleTheOrdinalAfterTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<ordinal> <cycle> after <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    , String -> PatternItem
regex String
"after"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token
token:Token Dimension a
TimeGrain a
grain:Token
_:Token Dimension a
Time a
td:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True a
Grain
grain (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleOrdinalQuarter :: Rule
ruleCycleOrdinalQuarter :: Rule
ruleCycleOrdinalQuarter = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<ordinal> quarter"
  , pattern :: Pattern
pattern =
    [ Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrain Grain
TG.Quarter
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True Grain
TG.Quarter (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$
          Grain -> Int -> TimeData
cycleNth Grain
TG.Year Int
0
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleTheOrdinalQuarter :: Rule
ruleCycleTheOrdinalQuarter :: Rule
ruleCycleTheOrdinalQuarter = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"the <ordinal> quarter"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"the"
    , Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrain Grain
TG.Quarter
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token
token:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
True Grain
TG.Quarter (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$
          Grain -> Int -> TimeData
cycleNth Grain
TG.Year Int
0
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleCycleOrdinalQuarterYear :: Rule
ruleCycleOrdinalQuarterYear :: Rule
ruleCycleOrdinalQuarterYear = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<ordinal> quarter <year>"
  , pattern :: Pattern
pattern =
    [ Dimension OrdinalData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension OrdinalData
Ordinal
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrain Grain
TG.Quarter
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token
_:Token Dimension a
Time a
td:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData -> TimeData
cycleNthAfter Bool
False Grain
TG.Quarter (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDurationInWithinAfter :: Rule
ruleDurationInWithinAfter :: Rule
ruleDurationInWithinAfter = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"in|within|after <duration>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(in|within|after)"
    , Dimension DurationData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DurationData
Duration
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):
       Token Dimension a
Duration a
dd:
       [Token]
_) -> case Text -> Text
Text.toLower Text
match of
         Text
"within" -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Open TimeData
now (DurationData -> TimeData
inDuration a
DurationData
dd)
         Text
"after"  -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ IntervalDirection -> TimeData -> TimeData
withDirection IntervalDirection
TTime.After (TimeData -> TimeData) -> TimeData -> TimeData
forall a b. (a -> b) -> a -> b
$ DurationData -> TimeData
inDuration a
DurationData
dd
         Text
"in"     -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ DurationData -> TimeData
inDuration a
DurationData
dd
         Text
_        -> Maybe Token
forall a. Maybe a
Nothing
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDurationLastNext :: Rule
ruleDurationLastNext :: Rule
ruleDurationLastNext = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"last|past|next <duration>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"([lp]ast|next)"
    , Dimension DurationData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DurationData
Duration
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
RegexMatch (GroupMatch (match:_)):
       Token Dimension a
Duration DurationData{TDuration.grain, TDuration.value}:
       [Token]
_) -> case Text -> Text
Text.toLower Text
match of
         Text
"next" -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData
cycleN Bool
True Grain
grain Int
value
         Text
"last" -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData
cycleN Bool
True Grain
grain (- Int
value)
         Text
"past" -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Grain -> Int -> TimeData
cycleN Bool
True Grain
grain (- Int
value)
         Text
_      -> Maybe Token
forall a. Maybe a
Nothing
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleNDOWago :: Rule
ruleNDOWago :: Rule
ruleNDOWago = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<integer> <named-day> ago|back"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isNatural
    , Predicate -> PatternItem
Predicate Predicate
isADayOfWeek
    , String -> PatternItem
regex String
"ago|back"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Numeral NumeralData{TNumeral.value = v}:Token Dimension a
Time a
td:[Token]
_) ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Int -> Bool -> TimeData -> TimeData
predNth (- (Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
floor Double
v)) Bool
False a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDurationHenceAgo :: Rule
ruleDurationHenceAgo :: Rule
ruleDurationHenceAgo = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<duration> hence|ago"
  , pattern :: Pattern
pattern =
    [ Dimension DurationData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DurationData
Duration
    , String -> PatternItem
regex String
"(hence|ago)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Duration a
dd:
       Token Dimension a
RegexMatch (GroupMatch (match:_)):
       [Token]
_) -> case Text -> Text
Text.toLower Text
match of
        Text
"ago" -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ DurationData -> TimeData
durationAgo a
DurationData
dd
        Text
_     -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ DurationData -> TimeData
inDuration a
DurationData
dd
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDayDurationHenceAgo :: Rule
ruleDayDurationHenceAgo :: Rule
ruleDayDurationHenceAgo = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<day> <duration> hence|ago"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ([Bool] -> Bool) -> (Token -> [Bool]) -> Predicate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Predicate] -> Token -> [Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Grain -> Predicate
isGrainOfTime Grain
TG.Day, Grain -> Predicate
isGrainOfTime Grain
TG.Month]
    , Dimension DurationData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DurationData
Duration
    , String -> PatternItem
regex String
"(from now|hence|ago)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td:
       Token Dimension a
Duration a
dd:
       Token Dimension a
RegexMatch (GroupMatch (match:_)):
       [Token]
_) -> case Text -> Text
Text.toLower Text
match of
         Text
"ago" -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (DurationData -> TimeData
durationIntervalAgo a
DurationData
dd)
         Text
_     -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (DurationData -> TimeData
inDurationInterval a
DurationData
dd)
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDayInDuration :: Rule
ruleDayInDuration :: Rule
ruleDayInDuration = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<day> in <duration>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ([Bool] -> Bool) -> (Token -> [Bool]) -> Predicate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Predicate] -> Token -> [Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Grain -> Predicate
isGrainOfTime Grain
TG.Day, Grain -> Predicate
isGrainOfTime Grain
TG.Month]
    , String -> PatternItem
regex String
"in"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isDurationGreaterThan Grain
TG.Hour
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td:Token
_:Token Dimension a
Duration a
dd:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (DurationData -> TimeData
inDurationInterval a
DurationData
dd)
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleInDurationAtTime :: Rule
ruleInDurationAtTime :: Rule
ruleInDurationAtTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"in <duration> at <time-of-day>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"in"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isDurationGreaterThan Grain
TG.Hour
    , String -> PatternItem
regex String
"at"
    , Predicate -> PatternItem
Predicate Predicate
isATimeOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Duration a
dd:Token
_:Token Dimension a
Time a
td:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeData -> TimeData -> Maybe TimeData
intersect a
TimeData
td (DurationData -> TimeData
inDurationInterval a
DurationData
dd)
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleInNumeral :: Rule
ruleInNumeral :: Rule
ruleInNumeral = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"in <number> (implicit minutes)"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"in"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween Int
0 Int
60
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Numeral NumeralData{TNumeral.value = v}:[Token]
_) ->
        TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ DurationData -> TimeData
inDuration (DurationData -> TimeData) -> DurationData -> TimeData
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> DurationData
duration Grain
TG.Minute (Int -> DurationData) -> Int -> DurationData
forall a b. (a -> b) -> a -> b
$ Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
floor Double
v
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleDurationAfterBeforeTime :: Rule
ruleDurationAfterBeforeTime :: Rule
ruleDurationAfterBeforeTime = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<duration> after|before|from|past <time>"
  , pattern :: Pattern
pattern =
    [ Dimension DurationData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DurationData
Duration
    , String -> PatternItem
regex String
"(after|before|from|past)"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Duration a
dd:
       Token Dimension a
RegexMatch (GroupMatch (match:_)):
       Token Dimension a
Time a
td:
       [Token]
_) -> case Text -> Text
Text.toLower Text
match of
         Text
"before" -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ DurationData -> TimeData -> TimeData
durationBefore a
DurationData
dd a
TimeData
td
         Text
_        -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ DurationData -> TimeData -> TimeData
durationAfter a
DurationData
dd a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalForDurationFrom :: Rule
ruleIntervalForDurationFrom :: Rule
ruleIntervalForDurationFrom = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"for <duration> from <time>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"for"
    , Dimension DurationData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DurationData
Duration
    , String -> PatternItem
regex String
"(from|starting|beginning|after|starting from)"
    , Dimension TimeData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension TimeData
Time
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Duration a
dd:Token
_:Token Dimension a
Time a
td1:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed a
TimeData
td1 (DurationData -> TimeData -> TimeData
durationAfter a
DurationData
dd a
TimeData
td1)
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
}

ruleIntervalTimeForDuration :: Rule
ruleIntervalTimeForDuration :: Rule
ruleIntervalTimeForDuration = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<time> for <duration>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isNotLatent
    , String -> PatternItem
regex String
"for"
    , Dimension DurationData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DurationData
Duration
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td1:Token
_:Token Dimension a
Duration a
dd:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed a
TimeData
td1 (DurationData -> TimeData -> TimeData
durationAfter a
DurationData
dd a
TimeData
td1)
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
}

ruleIntervalFromTimeForDuration :: Rule
ruleIntervalFromTimeForDuration :: Rule
ruleIntervalFromTimeForDuration = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"from <time> for <duration>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(from|starting|beginning|after|starting from)"
    , Predicate -> PatternItem
Predicate Predicate
isNotLatent
    , String -> PatternItem
regex String
"for"
    , Dimension DurationData -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension DurationData
Duration
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
_:Token Dimension a
Time a
td1:Token
_:Token Dimension a
Duration a
dd:[Token]
_) ->
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed a
TimeData
td1 (DurationData -> TimeData -> TimeData
durationAfter a
DurationData
dd a
TimeData
td1)
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
}

timezoneName :: String
timezoneName :: String
timezoneName = String
"YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT"

ruleTimezone :: Rule
ruleTimezone :: Rule
ruleTimezone = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<time> timezone"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and ([Bool] -> Bool) -> (Token -> [Bool]) -> Predicate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Predicate] -> Token -> [Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Predicate
isNotLatent, Predicate
isATimeOfDay, Predicate
hasNoTimezone]
    , String -> PatternItem
regex (String -> PatternItem) -> String -> PatternItem
forall a b. (a -> b) -> a -> b
$ String
"\\b(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
timezoneName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")\\b"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td:
       Token Dimension a
RegexMatch (GroupMatch (tz:_)):
       [Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> TimeData -> Maybe TimeData
inTimezone (Text -> Text
Text.toUpper Text
tz) a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleTimezoneBracket :: Rule
ruleTimezoneBracket :: Rule
ruleTimezoneBracket = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<time> (timezone)"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and ([Bool] -> Bool) -> (Token -> [Bool]) -> Predicate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Predicate] -> Token -> [Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Predicate
isNotLatent, Predicate
isATimeOfDay, Predicate
hasNoTimezone]
    , String -> PatternItem
regex (String -> PatternItem) -> String -> PatternItem
forall a b. (a -> b) -> a -> b
$ String
"\\((" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
timezoneName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")\\)"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td:
       Token Dimension a
RegexMatch (GroupMatch (tz:_)):
       [Token]
_) -> Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> TimeData -> Maybe TimeData
inTimezone (Text -> Text
Text.toUpper Text
tz) a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleIntervalDashTimezone :: Rule
ruleIntervalDashTimezone :: Rule
ruleIntervalDashTimezone = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<datetime> - <datetime> (interval) timezone"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and ([Bool] -> Bool) -> (Token -> [Bool]) -> Predicate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Predicate] -> Token -> [Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Predicate
isATimeOfDay, Predicate
hasNoTimezone]
    , String -> PatternItem
regex String
"\\-|to|th?ru|through|(un)?til(l)?"
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
and ([Bool] -> Bool) -> (Token -> [Bool]) -> Predicate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Predicate] -> Token -> [Bool]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Predicate
isATimeOfDay, Predicate
hasNoTimezone]
    , String -> PatternItem
regex (String -> PatternItem) -> String -> PatternItem
forall a b. (a -> b) -> a -> b
$ String
"\\b(" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
timezoneName String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
")\\b"
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token Dimension a
Time a
td1:
       Token
_:
       Token Dimension a
Time a
td2:
       Token Dimension a
RegexMatch (GroupMatch (tz:_)):
       [Token]
_) -> do
        TimeData
tdz1 <- Text -> TimeData -> Maybe TimeData
inTimezone (Text -> Text
Text.toUpper Text
tz) a
TimeData
td1
        TimeData
tdz2 <- Text -> TimeData -> Maybe TimeData
inTimezone (Text -> Text
Text.toUpper Text
tz) a
TimeData
td2
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TimeIntervalType -> TimeData -> TimeData -> Maybe TimeData
interval TimeIntervalType
TTime.Closed TimeData
tdz1 TimeData
tdz2
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleMidDay :: Rule
ruleMidDay :: Rule
ruleMidDay = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"Mid-day"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"(the )?mid(\\s)?day"
    ]
  , prod :: Production
prod = \[Token]
_ -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Bool -> Int -> TimeData
hour Bool
False Int
12
  }

ruleUpcomingGrain :: Rule
ruleUpcomingGrain :: Rule
ruleUpcomingGrain = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"upcoming <integer> <cycle>"
  , pattern :: Pattern
pattern =
    [ String -> PatternItem
regex String
"upcoming"
    , Predicate -> PatternItem
Predicate Predicate
isNatural
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    ]
  , prod :: Production
prod = \case
      ( Token
_:
        Token Dimension a
Numeral NumeralData{ TNumeral.value = numOfTimeGrain }:
        Token Dimension a
TimeGrain a
grain:
        [Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
grain (Int -> TimeData) -> Int -> TimeData
forall a b. (a -> b) -> a -> b
$ Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
floor Double
numOfTimeGrain
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleUpcomingGrainAlt :: Rule
ruleUpcomingGrainAlt :: Rule
ruleUpcomingGrainAlt = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<integer> upcoming <cycle>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate Predicate
isNatural
    , String -> PatternItem
regex String
"upcoming"
    , Dimension Grain -> PatternItem
forall a. Typeable a => Dimension a -> PatternItem
dimension Dimension Grain
TimeGrain
    ]
  , prod :: Production
prod = \case
      ( Token Dimension a
Numeral NumeralData{ TNumeral.value = numOfTimeGrain }:
        Token
_:
        Token Dimension a
TimeGrain a
grain:
        [Token]
_) -> TimeData -> Maybe Token
tt (TimeData -> Maybe Token) -> TimeData -> Maybe Token
forall a b. (a -> b) -> a -> b
$ Grain -> Int -> TimeData
cycleNth a
Grain
grain (Int -> TimeData) -> Int -> TimeData
forall a b. (a -> b) -> a -> b
$ Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
floor Double
numOfTimeGrain
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

ruleMinutesToHOD :: Rule
ruleMinutesToHOD :: Rule
ruleMinutesToHOD = Rule :: Text -> Pattern -> Production -> Rule
Rule
  { name :: Text
name = Text
"<integer> minutes to|till|before <hour-of-day>"
  , pattern :: Pattern
pattern =
    [ Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Int -> Int -> Predicate
isIntegerBetween Int
1 Int
59
    , Predicate -> PatternItem
Predicate (Predicate -> PatternItem) -> Predicate -> PatternItem
forall a b. (a -> b) -> a -> b
$ Grain -> Predicate
isGrain Grain
TG.Minute
    , String -> PatternItem
regex String
"to|till|before|of"
    , Predicate -> PatternItem
Predicate Predicate
isAnHourOfDay
    ]
  , prod :: Production
prod = \[Token]
tokens -> case [Token]
tokens of
      (Token
token:Token
_:Token
_:Token Dimension a
Time a
td:[Token]
_) -> do
        Int
n <- Token -> Maybe Int
getIntValue Token
token
        Dimension TimeData -> TimeData -> Token
forall a.
(Resolve a, Eq a, Hashable a, Show a, NFData a) =>
Dimension a -> a -> Token
Token Dimension TimeData
Time (TimeData -> Token) -> Maybe TimeData -> Maybe Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> TimeData -> Maybe TimeData
minutesBefore Int
n a
TimeData
td
      [Token]
_ -> Maybe Token
forall a. Maybe a
Nothing
  }

rules :: [Rule]
rules :: [Rule]
rules =
  [ Rule
ruleIntersect
  , Rule
ruleIntersectOf
  , Rule
ruleIntersectYear
  , Rule
ruleAbsorbOnDay
  , Rule
ruleAbsorbOnADOW
  , Rule
ruleAbsorbInMonthYear
  , Rule
ruleAbsorbCommaTOD
  , Rule
ruleNextDOW
  , Rule
ruleNextTime
  , Rule
ruleThisTime
  , Rule
ruleLastTime
  , Rule
ruleTimeBeforeLastAfterNext
  , Rule
ruleOrdinalDOWOfTime
  , Rule
ruleLastDOWOfTime
  , Rule
ruleLastCycleOfTime
  , Rule
ruleLastNight
  , Rule
ruleLastWeekendOfMonth
  , Rule
ruleNthTimeOfTime
  , Rule
ruleTheNthTimeOfTime
  , Rule
ruleNthTimeAfterTime
  , Rule
ruleTheNthTimeAfterTime
  , Rule
ruleNDOWFromTime
  , Rule
ruleYearLatent
  , Rule
ruleYearADBC
  , Rule
ruleTheDOMNumeral
  , Rule
ruleTheDOMOrdinal
  , Rule
ruleDOMLatent
  , Rule
ruleNamedDOMOrdinal
  , Rule
ruleMonthDOMNumeral
  , Rule
ruleDOMMonth
  , Rule
ruleDOMOfMonth
  , Rule
ruleTheDOMOfMonth
  , Rule
ruleDOMOrdinalMonthYear
  , Rule
ruleDOMMonthYear
  , Rule
ruleIdesOfMonth
  , Rule
ruleTODLatent
  , Rule
ruleAtTOD
  , Rule
ruleTODOClock
  , Rule
rulePODatTOD
  , Rule
ruleHHMM
  , Rule
ruleHHhMM
  , Rule
ruleHHMMLatent
  , Rule
ruleHHMMSS
  , Rule
ruleMilitaryAMPM
  , Rule
ruleMilitarySpelledOutAMPM
  , Rule
ruleMilitarySpelledOutAMPM2
  , Rule
ruleTODAMPM
  , Rule
ruleHONumeral
  , Rule
ruleHONumeralAlt
  , Rule
ruleHODHalf
  , Rule
ruleHODQuarter
  , Rule
ruleNumeralToHOD
  , Rule
ruleHalfToHOD
  , Rule
ruleQuarterToHOD
  , Rule
ruleNumeralAfterHOD
  , Rule
ruleHalfAfterHOD
  , Rule
ruleQuarterAfterHOD
  , Rule
ruleHalfHOD
  , Rule
ruleYYYYQQ
  , Rule
ruleYYYYMM
  , Rule
ruleYYYYMMDD
  , Rule
ruleMMYYYY
  , Rule
ruleNoonMidnightEOD
  , Rule
rulePartOfDays
  , Rule
ruleEarlyMorning
  , Rule
rulePODIn
  , Rule
rulePODThis
  , Rule
ruleTonight
  , Rule
ruleAfterPartofday
  , Rule
ruleTimePOD
  , Rule
rulePODofTime
  , Rule
ruleWeekend
  , Rule
ruleWeek
  , Rule
ruleTODPrecision
  , Rule
ruleTODPOD
  , Rule
rulePrecisionTOD
  , Rule
ruleIntervalFromMonthDDDD
  , Rule
ruleIntervalFromDDDDMonth
  , Rule
ruleIntervalFromDDDDOfMonth
  , Rule
ruleIntervalMonthDDDD
  , Rule
ruleIntervalDDDDMonth
  , Rule
ruleIntervalYearLatent
  , Rule
ruleIntervalDash
  , Rule
ruleIntervalSlash
  , Rule
ruleIntervalFrom
  , Rule
ruleIntervalBetween
  , Rule
ruleIntervalTODDash
  , Rule
ruleIntervalTODFrom
  , Rule
ruleIntervalTODAMPM
  , Rule
ruleIntervalTODBetween
  , Rule
ruleIntervalBy
  , Rule
ruleIntervalByTheEndOf
  , Rule
ruleIntervalUntilTime
  , Rule
ruleIntervalAfterFromSinceTime
  , Rule
ruleCycleTheAfterBeforeTime
  , Rule
ruleCycleThisLastNext
  , Rule
ruleDOMOfTimeMonth
  , Rule
ruleCycleAfterBeforeTime
  , Rule
ruleCycleOrdinalOfTime
  , Rule
ruleCycleLastOrdinalOfTime
  , Rule
ruleCycleTheOrdinalOfTime
  , Rule
ruleCycleTheLastOrdinalOfTime
  , Rule
ruleCycleTheOfTimeGrain
  , Rule
ruleCycleTheOfTime
  , Rule
ruleCycleOrdinalAfterTime
  , Rule
ruleCycleTheOrdinalAfterTime
  , Rule
ruleCycleOrdinalQuarter
  , Rule
ruleCycleTheOrdinalQuarter
  , Rule
ruleCycleOrdinalQuarterYear
  , Rule
ruleDurationInWithinAfter
  , Rule
ruleDurationLastNext
  , Rule
ruleNDOWago
  , Rule
ruleDurationHenceAgo
  , Rule
ruleDayDurationHenceAgo
  , Rule
ruleDayInDuration
  , Rule
ruleInDurationAtTime
  , Rule
ruleDurationAfterBeforeTime
  , Rule
ruleIntervalForDurationFrom
  , Rule
ruleIntervalFromTimeForDuration
  , Rule
ruleIntervalTimeForDuration
  , Rule
ruleInNumeral
  , Rule
ruleTimezone
  , Rule
ruleTimezoneBracket
  , Rule
ruleIntervalDashTimezone
  , Rule
rulePartOfMonth
  , Rule
ruleEndOrBeginningOfMonth
  , Rule
ruleEndOrBeginningOfYear
  , Rule
ruleEndOrBeginningOfWeek
  , Rule
ruleNow
  , Rule
ruleASAP
  , Rule
ruleSeason
  , Rule
ruleEndOfMonth
  , Rule
ruleBeginningOfMonth
  , Rule
ruleEndOfYear
  , Rule
ruleBeginningOfYear
  , Rule
ruleClosest
  , Rule
ruleNthClosest
  , Rule
ruleMidDay
  , Rule
ruleUpcomingGrain
  , Rule
ruleUpcomingGrainAlt
  , Rule
ruleMinutesToHOD
  ]
  [Rule] -> [Rule] -> [Rule]
forall a. [a] -> [a] -> [a]
++ [Rule]
ruleInstants
  [Rule] -> [Rule] -> [Rule]
forall a. [a] -> [a] -> [a]
++ [Rule]
ruleDaysOfWeek
  [Rule] -> [Rule] -> [Rule]
forall a. [a] -> [a] -> [a]
++ [Rule]
ruleMonths
  [Rule] -> [Rule] -> [Rule]
forall a. [a] -> [a] -> [a]
++ [Rule]
ruleSeasons
  [Rule] -> [Rule] -> [Rule]
forall a. [a] -> [a] -> [a]
++ [Rule]
ruleComputedHolidays
  [Rule] -> [Rule] -> [Rule]
forall a. [a] -> [a] -> [a]
++ [Rule]
ruleComputedHolidays'
  [Rule] -> [Rule] -> [Rule]
forall a. [a] -> [a] -> [a]
++ [Rule]
rulePeriodicHolidays