duckling/Duckling/Time/DE/Rules.hs
Sebastian Mika 39cb76024b Smaller improvements to DE about/before/after
Summary:
* In DE `frühestens` and `spätestens` act implicitly as `nach` and `vor` (after and before) on times and may also appear after the time

* The rule `ruleTimeofdayTimeofdayInterval` does match `9Uhr-10` but not the
way more common expression `9-10Uhr`; added the same rule with the
second time as non-latent; actually I am not sure whether the original
rule makes sense at all

* Simple extension of `intersect by ,` to THE formal way in DE to express
a date (i.e. `Freitag, der 13.03.2013`)

General remark: I used UTF-8 characters albeit I saw that the other rules and examples use escaped hex encoding for e.g. German umlaute. If there is any reason to do that (it is not very readable), I will of course change that.
Closes https://github.com/facebookincubator/duckling/pull/19

Reviewed By: niteria

Differential Revision: D5070052

Pulled By: patapizza

fbshipit-source-id: 990ad08
2017-05-17 10:19:44 -07:00

2064 lines
49 KiB
Haskell

-- Copyright (c) 2016-present, Facebook, Inc.
-- All rights reserved.
--
-- This source code is licensed under the BSD-style license found in the
-- LICENSE file in the root directory of this source tree. An additional grant
-- of patent rights can be found in the PATENTS file in the same directory.
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoRebindableSyntax #-}
{-# LANGUAGE OverloadedStrings #-}
module Duckling.Time.DE.Rules
( rules ) where
import Control.Monad (liftM2)
import qualified Data.Text as Text
import Prelude
import Duckling.Dimensions.Types
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Types (OrdinalData (..))
import qualified Duckling.Ordinal.Types as TOrdinal
import Duckling.Regex.Types
import Duckling.Time.Helpers
import Duckling.Time.Types (TimeData (..))
import qualified Duckling.Time.Types as TTime
import qualified Duckling.TimeGrain.Types as TG
import Duckling.Types
ruleNamedday :: Rule
ruleNamedday = Rule
{ name = "named-day"
, pattern =
[ regex "montags?|mo\\.?"
]
, prod = \_ -> tt $ dayOfWeek 1
}
ruleNamedmonth12 :: Rule
ruleNamedmonth12 = Rule
{ name = "named-month"
, pattern =
[ regex "dezember|dez\\.?"
]
, prod = \_ -> tt $ month 12
}
ruleRelativeMinutesTotillbeforeIntegerHourofday :: Rule
ruleRelativeMinutesTotillbeforeIntegerHourofday = Rule
{ name = "relative minutes to|till|before <integer> (hour-of-day)"
, pattern =
[ Predicate $ isIntegerBetween 1 59
, regex "vor"
, Predicate isAnHourOfDay
]
, prod = \tokens -> case tokens of
(token:_:Token Time td:_) -> do
n <- getIntValue token
t <- minutesBefore n td
Just $ Token Time t
_ -> Nothing
}
ruleQuarterTotillbeforeIntegerHourofday :: Rule
ruleQuarterTotillbeforeIntegerHourofday = Rule
{ name = "quarter to|till|before <integer> (hour-of-day)"
, pattern =
[regex "vie?rtel vor"
, Predicate isAnHourOfDay
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) -> do
t <- minutesBefore 15 td
Just $ Token Time t
_ -> Nothing
}
ruleHalfTotillbeforeIntegerHourofday :: Rule
ruleHalfTotillbeforeIntegerHourofday = Rule
{ name = "half to|till|before <integer> (hour-of-day)"
, pattern =
[ regex "halbe? vor"
, Predicate isAnHourOfDay
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) -> do
t <- minutesBefore 30 td
Just $ Token Time t
_ -> Nothing
}
ruleNamedday2 :: Rule
ruleNamedday2 = Rule
{ name = "named-day"
, pattern =
[ regex "die?nstags?|di\\.?"
]
, prod = \_ -> tt $ dayOfWeek 2
}
ruleValentinesDay :: Rule
ruleValentinesDay = Rule
{ name = "valentine's day"
, pattern =
[ regex "valentin'?stag"
]
, prod = \_ -> tt $ monthDay 2 14
}
ruleTheOrdinalCycleOfTime :: Rule
ruleTheOrdinalCycleOfTime = Rule
{ name = "the <ordinal> <cycle> of <time>"
, pattern =
[ regex "der|die|das"
, dimension Ordinal
, dimension TimeGrain
, regex "im|in|von"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->
tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td
_ -> Nothing
}
ruleNthTimeOfTime2 :: Rule
ruleNthTimeOfTime2 = Rule
{ name = "nth <time> of <time>"
, pattern =
[ regex "der|die|das"
, dimension Ordinal
, dimension Time
, regex "im"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:
Token Ordinal (OrdinalData {TOrdinal.value = v}):
Token Time td1:
_:
Token Time td2:
_) -> Token Time . predNth (v - 1) False <$> intersect td2 td1
_ -> Nothing
}
ruleNewYearsDay :: Rule
ruleNewYearsDay = Rule
{ name = "new year's day"
, pattern =
[ regex "neujahr(s?tag)?"
]
, prod = \_ -> tt $ monthDay 1 1
}
ruleLastTime :: Rule
ruleLastTime = Rule
{ name = "last <time>"
, pattern =
[ regex "letzten?|letztes"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) ->
tt $ predNth (-1) False td
_ -> Nothing
}
ruleNamedday6 :: Rule
ruleNamedday6 = Rule
{ name = "named-day"
, pattern =
[ regex "samstags?|sa\\.?"
]
, prod = \_ -> tt $ dayOfWeek 6
}
ruleDatetimeDatetimeInterval :: Rule
ruleDatetimeDatetimeInterval = Rule
{ name = "<datetime> - <datetime> (interval)"
, pattern =
[ Predicate isNotLatent
, regex "\\-|bis"
, Predicate isNotLatent
]
, prod = \tokens -> case tokens of
(Token Time td1:_:Token Time td2:_) ->
Token Time <$> interval TTime.Closed td1 td2
_ -> Nothing
}
ruleNamedmonth7 :: Rule
ruleNamedmonth7 = Rule
{ name = "named-month"
, pattern =
[ regex "juli|jul\\.?"
]
, prod = \_ -> tt $ month 7
}
ruleEvening :: Rule
ruleEvening = Rule
{ name = "evening"
, pattern =
[ regex "abends?"
]
, prod = \_ ->
let from = hour False 18
to = hour False 0
in Token Time . mkLatent . partOfDay <$>
interval TTime.Open from to
}
ruleTheDayofmonthNonOrdinal :: Rule
ruleTheDayofmonthNonOrdinal = Rule
{ name = "the <day-of-month> (non ordinal)"
, pattern =
[ regex "der"
, Predicate $ isIntegerBetween 1 31
]
, prod = \tokens -> case tokens of
(_:token:_) -> do
v <- getIntValue token
tt $ dayOfMonth v
_ -> Nothing
}
ruleInDuration :: Rule
ruleInDuration = Rule
{ name = "in <duration>"
, pattern =
[ regex "in"
, dimension Duration
]
, prod = \tokens -> case tokens of
(_:Token Duration dd:_) ->
tt $ inDuration dd
_ -> Nothing
}
ruleNow :: Rule
ruleNow = Rule
{ name = "now"
, pattern =
[ regex "(genau)? ?jetzt|diesen moment|in diesem moment|gerade eben"
]
, prod = \_ -> tt $ cycleNth TG.Second 0
}
ruleLastCycleOfTime :: Rule
ruleLastCycleOfTime = Rule
{ name = "last <cycle> of <time>"
, pattern =
[ regex "letzte(r|n|s)?"
, dimension TimeGrain
, regex "um|im"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token TimeGrain grain:_:Token Time td:_) ->
tt $ cycleLastOf grain td
_ -> Nothing
}
ruleFromDatetimeDatetimeInterval :: Rule
ruleFromDatetimeDatetimeInterval = Rule
{ name = "from <datetime> - <datetime> (interval)"
, pattern =
[ regex "vo[nm]"
, dimension Time
, regex "\\-|bis"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Time td1:_:Token Time td2:_) ->
Token Time <$> interval TTime.Closed td1 td2
_ -> Nothing
}
ruleRelativeMinutesAfterpastIntegerHourofday :: Rule
ruleRelativeMinutesAfterpastIntegerHourofday = Rule
{ name = "relative minutes after|past <integer> (hour-of-day)"
, pattern =
[ Predicate $ isIntegerBetween 1 59
, regex "nach"
, Predicate isAnHourOfDay
]
, prod = \tokens -> case tokens of
(token:
_:
Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:
_) -> do
n <- getIntValue token
tt $ hourMinute is12H hours n
_ -> Nothing
}
ruleQuarterAfterpastIntegerHourofday :: Rule
ruleQuarterAfterpastIntegerHourofday = Rule
{ name = "quarter after|past <integer> (hour-of-day)"
, pattern =
[ regex "vie?rtel nach"
, Predicate isAnHourOfDay
]
, prod = \tokens -> case tokens of
(_:
Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:
_) -> tt $ hourMinute is12H hours 15
_ -> Nothing
}
ruleHalfAfterpastIntegerHourofday :: Rule
ruleHalfAfterpastIntegerHourofday = Rule
{ name = "half after|past <integer> (hour-of-day)"
, pattern =
[ regex "halbe? nach"
, Predicate isAnHourOfDay
]
, prod = \tokens -> case tokens of
(_:
Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:
_) -> tt $ hourMinute is12H hours 30
_ -> Nothing
}
ruleMonthDdddInterval :: Rule
ruleMonthDdddInterval = Rule
{ name = "<month> dd-dd (interval)"
, pattern =
[ regex "([012]?\\d|30|31)(ter|\\.)?"
, regex "\\-|bis"
, regex "([012]?\\d|30|31)(ter|\\.)?"
, Predicate isAMonth
]
, prod = \tokens -> case tokens of
(Token RegexMatch (GroupMatch (m1:_)):
_:
Token RegexMatch (GroupMatch (m2:_)):
Token Time td:
_) -> do
v1 <- parseInt m1
v2 <- parseInt m2
from <- intersect (dayOfMonth v1) td
to <- intersect (dayOfMonth v2) td
Token Time <$> interval TTime.Closed from to
_ -> Nothing
}
ruleNamedday4 :: Rule
ruleNamedday4 = Rule
{ name = "named-day"
, pattern =
[ regex "donn?erstags?|do\\.?"
]
, prod = \_ -> tt $ dayOfWeek 4
}
ruleAfterTomorrow :: Rule
ruleAfterTomorrow = Rule
{ name = "after tomorrow"
, pattern =
[ regex "(\x00fc)bermorgen"
]
, prod = \_ -> tt $ cycleNth TG.Day 2
}
ruleTheCycleAfterTime :: Rule
ruleTheCycleAfterTime = Rule
{ name = "the <cycle> after <time>"
, pattern =
[ regex "der"
, dimension TimeGrain
, regex "nach"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token TimeGrain grain:_:Token Time td:_) ->
tt $ cycleNthAfter False grain 1 td
_ -> Nothing
}
ruleTheCycleBeforeTime :: Rule
ruleTheCycleBeforeTime = Rule
{ name = "the <cycle> before <time>"
, pattern =
[ regex "der"
, dimension TimeGrain
, regex "vor"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token TimeGrain grain:_:Token Time td:_) ->
tt $ cycleNthAfter False grain (-1) td
_ -> Nothing
}
ruleSeason4 :: Rule
ruleSeason4 = Rule
{ name = "season"
, pattern =
[ regex "fr(\x00fc)hling|fr(\x00fc)hjahr"
]
, prod = \_ ->
let from = monthDay 3 20
to = monthDay 6 21
in Token Time <$> interval TTime.Open from to
}
ruleYearLatent2 :: Rule
ruleYearLatent2 = Rule
{ name = "year (latent)"
, pattern =
[ Predicate $ isIntegerBetween 2101 10000
]
, prod = \tokens -> case tokens of
(token:_) -> do
v <- getIntValue token
tt . mkLatent $ year v
_ -> Nothing
}
ruleTimeAfterNext :: Rule
ruleTimeAfterNext = Rule
{ name = "<time> after next"
, pattern =
[ dimension Time
, regex "nach dem n(\x00e4)chsten"
]
, prod = \tokens -> case tokens of
(Token Time td:_) ->
tt $ predNth 1 True td
_ -> Nothing
}
ruleTheIdesOfNamedmonth :: Rule
ruleTheIdesOfNamedmonth = Rule
{ name = "the ides of <named-month>"
, pattern =
[ regex "die iden (des?)"
, Predicate isAMonth
]
, prod = \tokens -> case tokens of
(_:Token Time td@TimeData {TTime.form = Just (TTime.Month m)}:_) ->
Token Time <$>
intersect (dayOfMonth $ if elem m [3, 5, 7, 10] then 15 else 13) td
_ -> Nothing
}
ruleNoon :: Rule
ruleNoon = Rule
{ name = "noon"
, pattern =
[ regex "mittags?|zw(\x00f6)lf (uhr)?"
]
, prod = \_ -> tt $ hour False 12
}
ruleToday :: Rule
ruleToday = Rule
{ name = "today"
, pattern =
[ regex "heute|(um diese zeit|zu dieser zeit|um diesen zeitpunkt|zu diesem zeitpunkt)"
]
, prod = \_ -> tt $ cycleNth TG.Day 0
}
ruleThisnextDayofweek :: Rule
ruleThisnextDayofweek = Rule
{ name = "this|next <day-of-week>"
, pattern =
[ regex "diese(n|r)|kommenden|n(\x00e4)chsten"
, Predicate isADayOfWeek
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) ->
tt $ predNth 0 True td
_ -> Nothing
}
ruleBetweenTimeofdayAndTimeofdayInterval :: Rule
ruleBetweenTimeofdayAndTimeofdayInterval = Rule
{ name = "between <time-of-day> and <time-of-day> (interval)"
, pattern =
[ regex "zwischen"
, Predicate isATimeOfDay
, regex "und"
, Predicate isATimeOfDay
]
, prod = \tokens -> case tokens of
(_:Token Time td1:_:Token Time td2:_) ->
Token Time <$> interval TTime.Closed td1 td2
_ -> Nothing
}
ruleNextCycle :: Rule
ruleNextCycle = Rule
{ name = "next <cycle>"
, pattern =
[ regex "n(\x00e4)chste(r|n|s)?|kommende(r|n|s)?"
, dimension TimeGrain
]
, prod = \tokens -> case tokens of
(_:Token TimeGrain grain:_) ->
tt $ cycleNth grain 1
_ -> Nothing
}
ruleNamedmonth :: Rule
ruleNamedmonth = Rule
{ name = "named-month"
, pattern =
[ regex "januar|jan\\.?"
]
, prod = \_ -> tt $ month 1
}
ruleTimeofdayApproximately :: Rule
ruleTimeofdayApproximately = Rule
{ name = "<time-of-day> approximately"
, pattern =
[ Predicate isATimeOfDay
, regex "(um )?zirka|ungef(\x00e4)hr|etwa"
]
, prod = \tokens -> case tokens of
(Token Time td:_) -> tt $ notLatent td
_ -> Nothing
}
ruleOnDate :: Rule
ruleOnDate = Rule
{ name = "on <date>"
, pattern =
[ regex "am"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:x:_) -> Just x
_ -> Nothing
}
ruleNamedmonth3 :: Rule
ruleNamedmonth3 = Rule
{ name = "named-month"
, pattern =
[ regex "m(\x00e4)rz|m(\x00e4)r\\.?"
]
, prod = \_ -> tt $ month 3
}
ruleDurationFromNow :: Rule
ruleDurationFromNow = Rule
{ name = "<duration> from now"
, pattern =
[ dimension Duration
, regex "ab (heute|jetzt)"
]
, prod = \tokens -> case tokens of
(Token Duration dd:_) ->
tt $ inDuration dd
_ -> Nothing
}
ruleLunch :: Rule
ruleLunch = Rule
{ name = "lunch"
, pattern =
[ regex "(am |zu )?mittags?"
]
, prod = \_ ->
let from = hour False 12
to = hour False 14
in Token Time . mkLatent . partOfDay <$>
interval TTime.Open from to
}
ruleLastCycle :: Rule
ruleLastCycle = Rule
{ name = "last <cycle>"
, pattern =
[ regex "letzte(r|n|s)?|vergangene(r|n|s)?"
, dimension TimeGrain
]
, prod = \tokens -> case tokens of
(_:Token TimeGrain grain:_) ->
tt . cycleNth grain $ - 1
_ -> Nothing
}
ruleAfternoon :: Rule
ruleAfternoon = Rule
{ name = "afternoon"
, pattern =
[ regex "nach ?mittags?"
]
, prod = \_ ->
let from = hour False 12
to = hour False 19
in Token Time . mkLatent . partOfDay <$>
interval TTime.Open from to
}
ruleNamedmonth4 :: Rule
ruleNamedmonth4 = Rule
{ name = "named-month"
, pattern =
[ regex "april|apr\\.?"
]
, prod = \_ -> tt $ month 4
}
ruleTimeBeforeLast :: Rule
ruleTimeBeforeLast = Rule
{ name = "<time> before last"
, pattern =
[ regex "vorletzten?|vor ?letztes?"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) ->
tt $ predNth (-2) False td
_ -> Nothing
}
ruleNamedmonthDayofmonthOrdinal :: Rule
ruleNamedmonthDayofmonthOrdinal = Rule
{ name = "<named-month> <day-of-month> (ordinal)"
, pattern =
[ Predicate isAMonth
, Predicate isDOMOrdinal
]
, prod = \tokens -> case tokens of
(Token Time td:token:_) -> Token Time <$> intersectDOM td token
_ -> Nothing
}
ruleChristmasEve :: Rule
ruleChristmasEve = Rule
{ name = "christmas eve"
, pattern =
[ regex "heilig(er)? abend"
]
, prod = \_ -> tt $ monthDay 12 24
}
ruleInduringThePartofday :: Rule
ruleInduringThePartofday = Rule
{ name = "in|during the <part-of-day>"
, pattern =
[ regex "(in|an|am|w(\x00e4)h?rend)( der| dem| des)?"
, Predicate isAPartOfDay
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) ->
tt $ notLatent td
_ -> Nothing
}
ruleHourofdayIntegerAsRelativeMinutes :: Rule
ruleHourofdayIntegerAsRelativeMinutes = Rule
{ name = "<hour-of-day> <integer> (as relative minutes)"
, pattern =
[ Predicate isAnHourOfDay
, Predicate $ isIntegerBetween 1 59
]
, prod = \tokens -> case tokens of
(Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:
token:
_) -> do
n <- getIntValue token
tt $ hourMinute is12H hours n
_ -> Nothing
}
ruleHourofdayQuarter :: Rule
ruleHourofdayQuarter = Rule
{ name = "<hour-of-day> <quarter> (as relative minutes)"
, pattern =
[ Predicate isAnHourOfDay
, regex "vie?rtel"
]
, prod = \tokens -> case tokens of
(Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->
tt $ hourMinute is12H hours 15
_ -> Nothing
}
ruleHourofdayHalf :: Rule
ruleHourofdayHalf = Rule
{ name = "<hour-of-day> <half> (as relative minutes)"
, pattern =
[ Predicate isAnHourOfDay
, regex "halbe?"
]
, prod = \tokens -> case tokens of
(Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->
tt $ hourMinute is12H hours 30
_ -> Nothing
}
ruleNamedday5 :: Rule
ruleNamedday5 = Rule
{ name = "named-day"
, pattern =
[ regex "freitags?|fr\\.?"
]
, prod = \_ -> tt $ dayOfWeek 5
}
ruleDayofmonthordinalNamedmonth :: Rule
ruleDayofmonthordinalNamedmonth = Rule
{ name = "<day-of-month>(ordinal) <named-month>"
, pattern =
[ Predicate isDOMOrdinal
, Predicate isAMonth
]
, prod = \tokens -> case tokens of
(token:Token Time td:_) -> Token Time <$> intersectDOM td token
_ -> Nothing
}
ruleIntersectBy :: Rule
ruleIntersectBy = Rule
{ name = "intersect by ','"
, pattern =
[ Predicate isNotLatent
, regex ",( den|r)?"
, Predicate isNotLatent
]
, prod = \tokens -> case tokens of
(Token Time td1:_:Token Time td2:_) ->
Token Time <$> intersect td1 td2
_ -> Nothing
}
ruleNthTimeAfterTime :: Rule
ruleNthTimeAfterTime = Rule
{ name = "nth <time> after <time>"
, pattern =
[ dimension Ordinal
, dimension Time
, regex "nach"
, dimension Time
]
, prod = \tokens -> case tokens of
(Token Ordinal (OrdinalData {TOrdinal.value = v}):
Token Time td1:
_:
Token Time td2:
_) -> tt $ predNthAfter (v - 1) td1 td2
_ -> Nothing
}
ruleMmdd :: Rule
ruleMmdd = Rule
{ name = "mm/dd"
, pattern =
[ regex "([012]?[1-9]|10|20|30|31)\\.(0?[1-9]|10|11|12)\\."
]
, prod = \tokens -> case tokens of
(Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do
d <- parseInt m1
m <- parseInt m2
tt $ monthDay m d
_ -> Nothing
}
ruleAfterDuration :: Rule
ruleAfterDuration = Rule
{ name = "after <duration>"
, pattern =
[ regex "nach"
, dimension Duration
]
, prod = \tokens -> case tokens of
(_:Token Duration dd:_) ->
tt $ inDuration dd
_ -> Nothing
}
ruleTimeofdayLatent :: Rule
ruleTimeofdayLatent = Rule
{ name = "time-of-day (latent)"
, pattern =
[ Predicate $ isIntegerBetween 0 23
]
, prod = \tokens -> case tokens of
(token:_) -> do
n <- getIntValue token
tt . mkLatent $ hour (n < 12) n
_ -> Nothing
}
ruleFromTimeofdayTimeofdayInterval :: Rule
ruleFromTimeofdayTimeofdayInterval = Rule
{ name = "from <time-of-day> - <time-of-day> (interval)"
, pattern =
[ regex "(von|nach|ab|fr(\x00fc)hestens (um)?)"
, Predicate isATimeOfDay
, regex "((noch|aber|jedoch)? vor)|\\-|bis"
, Predicate isATimeOfDay
]
, prod = \tokens -> case tokens of
(_:Token Time td1:_:Token Time td2:_) ->
Token Time <$> interval TTime.Closed td1 td2
_ -> Nothing
}
ruleNamedmonth2 :: Rule
ruleNamedmonth2 = Rule
{ name = "named-month"
, pattern =
[ regex "februar|feb\\.?"
]
, prod = \_ -> tt $ month 2
}
ruleExactlyTimeofday :: Rule
ruleExactlyTimeofday = Rule
{ name = "exactly <time-of-day>"
, pattern =
[ regex "genau|exakt|p(\x00fc)nktlich|punkt( um)?"
, Predicate isATimeOfDay
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) -> tt $ notLatent td
_ -> Nothing
}
ruleSeason3 :: Rule
ruleSeason3 = Rule
{ name = "season"
, pattern =
[ regex "winter"
]
, prod = \_ ->
let from = monthDay 12 21
to = monthDay 3 20
in Token Time <$> interval TTime.Open from to
}
ruleSeason :: Rule
ruleSeason = Rule
{ name = "season"
, pattern =
[ regex "sommer"
]
, prod = \_ ->
let from = monthDay 6 21
to = monthDay 9 23
in Token Time <$> interval TTime.Open from to
}
ruleSchweizerBundesfeiertag :: Rule
ruleSchweizerBundesfeiertag = Rule
{ name = "Schweizer Bundesfeiertag"
, pattern =
[ regex "schweiz(er)? (bundes)?feiertag|bundes feiertag"
]
, prod = \_ -> tt $ monthDay 8 1
}
ruleBetweenDatetimeAndDatetimeInterval :: Rule
ruleBetweenDatetimeAndDatetimeInterval = Rule
{ name = "between <datetime> and <datetime> (interval)"
, pattern =
[ regex "zwischen"
, dimension Time
, regex "und"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Time td1:_:Token Time td2:_) ->
Token Time <$> interval TTime.Closed td1 td2
_ -> Nothing
}
ruleNewYearsEve :: Rule
ruleNewYearsEve = Rule
{ name = "new year's eve"
, pattern =
[ regex "silvester"
]
, prod = \_ -> tt $ monthDay 12 31
}
ruleDurationAgo :: Rule
ruleDurationAgo = Rule
{ name = "<duration> ago"
, pattern =
[ regex "vor"
, dimension Duration
]
, prod = \tokens -> case tokens of
(_:Token Duration dd:_) ->
tt $ durationAgo dd
_ -> Nothing
}
ruleByTheEndOfTime :: Rule
ruleByTheEndOfTime = Rule
{ name = "by the end of <time>"
, pattern =
[ regex "bis (zum)? ende (von)?|(noch)? vor"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) -> Token Time <$>
interval TTime.Closed td (cycleNth TG.Second 0)
_ -> Nothing
}
ruleAfterWork :: Rule
ruleAfterWork = Rule
{ name = "after work"
, pattern =
[ regex "nach (der)? arbeit|(am)? feier ?abend"
]
, prod = \_ -> do
let td1 = cycleNth TG.Day 0
td2 <- interval TTime.Open (hour False 17) (hour False 21)
Token Time . partOfDay <$> intersect td1 td2
}
ruleBeforeYesterday :: Rule
ruleBeforeYesterday = Rule
{ name = "before yesterday"
, pattern =
[ regex "vorgestern"
]
, prod = \_ -> tt . cycleNth TG.Day $ - 2
}
ruleLastNCycle :: Rule
ruleLastNCycle = Rule
{ name = "last n <cycle>"
, pattern =
[ regex "letzten?|vergangenen?"
, Predicate $ isIntegerBetween 1 9999
, dimension TimeGrain
]
, prod = \tokens -> case tokens of
(_:token:Token TimeGrain grain:_) -> do
n <- getIntValue token
tt $ cycleN True grain (- n)
_ -> Nothing
}
ruleTimeofdaySharp :: Rule
ruleTimeofdaySharp = Rule
{ name = "<time-of-day> sharp"
, pattern =
[ Predicate isATimeOfDay
, regex "genau|exakt|p(\x00fc)nktlich|punkt( um)?"
]
, prod = \tokens -> case tokens of
(Token Time td:_) -> tt $ notLatent td
_ -> Nothing
}
ruleAllerheiligen :: Rule
ruleAllerheiligen = Rule
{ name = "Allerheiligen"
, pattern =
[ regex "allerheiligen?|aller heiligen?"
]
, prod = \_ -> tt $ monthDay 11 1
}
ruleWithinDuration :: Rule
ruleWithinDuration = Rule
{ name = "within <duration>"
, pattern =
[ regex "binnen|innerhalb( von)?"
, dimension Duration
]
, prod = \tokens -> case tokens of
(_:Token Duration dd:_) -> Token Time <$>
interval TTime.Open (cycleNth TG.Second 0) (inDuration dd)
_ -> Nothing
}
ruleMidnighteodendOfDay :: Rule
ruleMidnighteodendOfDay = Rule
{ name = "midnight|EOD|end of day"
, pattern =
[ regex "mitternacht|EOD|tagesende|ende (des)? tag(es)?"
]
, prod = \_ -> tt $ hour False 0
}
ruleDayofmonthNonOrdinalNamedmonth :: Rule
ruleDayofmonthNonOrdinalNamedmonth = Rule
{ name = "<day-of-month> (non ordinal) <named-month>"
, pattern =
[ Predicate isDOMInteger
, Predicate isAMonth
]
, prod = \tokens -> case tokens of
(token:Token Time td:_) -> Token Time <$> intersectDOM td token
_ -> Nothing
}
ruleIntersect :: Rule
ruleIntersect = Rule
{ name = "intersect"
, pattern =
[ Predicate isNotLatent
, Predicate isNotLatent
]
, prod = \tokens -> case tokens of
(Token Time td1:Token Time td2:_) ->
Token Time <$> intersect td1 td2
_ -> Nothing
}
ruleAboutTimeofday :: Rule
ruleAboutTimeofday = Rule
{ name = "about <time-of-day>"
, pattern =
[ regex "(um )?zirka|ca\\.?|ungef(\x00e4)hr|etwa|gegen"
, Predicate isATimeOfDay
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) -> tt $ notLatent td
_ -> Nothing
}
ruleUntilTimeofday :: Rule
ruleUntilTimeofday = Rule
{ name = "until <time-of-day>"
, pattern =
[ regex "vor|bis( zu[rm]?)?|sp(\x00e4)testens?"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) -> tt $ withDirection TTime.Before td
_ -> Nothing
}
ruleUntilTimeofdayPostfix :: Rule
ruleUntilTimeofdayPostfix = Rule
{ name = "<time-of-day> until"
, pattern =
[ dimension Time
, regex "sp(\x00e4)testens"
]
, prod = \tokens -> case tokens of
(Token Time td:_:_) -> tt $ withDirection TTime.Before td
_ -> Nothing
}
ruleSterreichischerNationalfeiertag :: Rule
ruleSterreichischerNationalfeiertag = Rule
{ name = "Österreichischer Nationalfeiertag"
, pattern =
[ regex "((\x00f6)sterreichischer?)? nationalfeiertag|national feiertag"
]
, prod = \_ -> tt $ monthDay 10 26
}
ruleAtTimeofday :: Rule
ruleAtTimeofday = Rule
{ name = "at <time-of-day>"
, pattern =
[ regex "um|@"
, Predicate isATimeOfDay
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) -> tt $ notLatent td
_ -> Nothing
}
ruleNamedmonth6 :: Rule
ruleNamedmonth6 = Rule
{ name = "named-month"
, pattern =
[ regex "juni|jun\\.?"
]
, prod = \_ -> tt $ month 6
}
ruleNthTimeOfTime :: Rule
ruleNthTimeOfTime = Rule
{ name = "nth <time> of <time>"
, pattern =
[ dimension Ordinal
, dimension Time
, regex "im"
, dimension Time
]
, prod = \tokens -> case tokens of
(Token Ordinal (OrdinalData {TOrdinal.value = v}):
Token Time td1:
_:
Token Time td2:
_) -> Token Time . predNth (v - 1) False <$> intersect td2 td1
_ -> Nothing
}
ruleNamedmonth8 :: Rule
ruleNamedmonth8 = Rule
{ name = "named-month"
, pattern =
[ regex "august|aug\\.?"
]
, prod = \_ -> tt $ month 8
}
ruleTimePartofday :: Rule
ruleTimePartofday = Rule
{ name = "<time> <part-of-day>"
, pattern =
[ dimension Time
, Predicate isAPartOfDay
]
, prod = \tokens -> case tokens of
(Token Time td1:Token Time td2:_) ->
Token Time <$> intersect td1 td2
_ -> Nothing
}
ruleWeekend :: Rule
ruleWeekend = Rule
{ name = "week-end"
, pattern =
[ regex "wochen ?ende?"
]
, prod = \_ -> do
from <- intersect (dayOfWeek 5) (hour False 18)
to <- intersect (dayOfWeek 1) (hour False 0)
Token Time <$> interval TTime.Open from to
}
ruleTagDerDeutschenEinheit :: Rule
ruleTagDerDeutschenEinheit = Rule
{ name = "Tag der Deutschen Einheit"
, pattern =
[ regex "tag (der)? deutsc?hen? einheit"
]
, prod = \_ -> tt $ monthDay 10 3
}
ruleEomendOfMonth :: Rule
ruleEomendOfMonth = Rule
{ name = "EOM|End of month"
, pattern =
[ regex "(das )?ende des monats?"
]
, prod = \_ -> tt $ cycleNth TG.Month 1
}
ruleNthTimeAfterTime2 :: Rule
ruleNthTimeAfterTime2 = Rule
{ name = "nth <time> after <time>"
, pattern =
[ regex "der|das"
, dimension Ordinal
, dimension Time
, regex "nach"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:
Token Ordinal (OrdinalData {TOrdinal.value = v}):
Token Time td1:
_:
Token Time td2:
_) -> tt $ predNthAfter (v - 1) td1 td2
_ -> Nothing
}
ruleNextTime :: Rule
ruleNextTime = Rule
{ name = "next <time>"
, pattern =
[ regex "(n(\x00e4)chste|kommende)[ns]?"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) ->
tt $ predNth 0 True td
_ -> Nothing
}
ruleOrdinalQuarterYear :: Rule
ruleOrdinalQuarterYear = Rule
{ name = "<ordinal> quarter <year>"
, pattern =
[ dimension Ordinal
, Predicate $ isGrain TG.Quarter
, dimension Time
]
, prod = \tokens -> case tokens of
(Token Ordinal od:_:Token Time td:_) ->
tt $ cycleNthAfter False TG.Quarter (TOrdinal.value od - 1) td
_ -> Nothing
}
ruleYyyymmdd :: Rule
ruleYyyymmdd = Rule
{ name = "yyyy-mm-dd"
, pattern =
[ regex "(\\d{2,4})-(0?[1-9]|10|11|12)-([012]?[1-9]|10|20|30|31)"
]
, prod = \tokens -> case tokens of
(Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do
y <- parseInt m1
m <- parseInt m2
d <- parseInt m3
tt $ yearMonthDay y m d
_ -> Nothing
}
ruleTheOrdinalCycleAfterTime :: Rule
ruleTheOrdinalCycleAfterTime = Rule
{ name = "the <ordinal> <cycle> after <time>"
, pattern =
[ regex "the"
, dimension Ordinal
, dimension TimeGrain
, regex "nach"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->
tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td
_ -> Nothing
}
ruleIntersectByOfFromS :: Rule
ruleIntersectByOfFromS = Rule
{ name = "intersect by 'of', 'from', 's"
, pattern =
[ Predicate isNotLatent
, regex "von|der|im"
, Predicate isNotLatent
]
, prod = \tokens -> case tokens of
(Token Time td1:_:Token Time td2:_) ->
Token Time <$> intersect td1 td2
_ -> Nothing
}
ruleNextNCycle :: Rule
ruleNextNCycle = Rule
{ name = "next n <cycle>"
, pattern =
[ regex "n(\x00e4)chsten?|kommenden?"
, Predicate $ isIntegerBetween 1 9999
, dimension TimeGrain
]
, prod = \tokens -> case tokens of
(_:token:Token TimeGrain grain:_) -> do
v <- getIntValue token
tt $ cycleN True grain v
_ -> Nothing
}
ruleADuration :: Rule
ruleADuration = Rule
{ name = "a <duration>"
, pattern =
[ regex "(in )?eine?(r|n)?"
, dimension Duration
]
, prod = \tokens -> case tokens of
(_:Token Duration dd:_) ->
tt $ inDuration dd
_ -> Nothing
}
ruleMorning :: Rule
ruleMorning = Rule
{ name = "morning"
, pattern =
[ regex "morgens|(in der )?fr(\x00fc)h|vor ?mittags?|am morgen"
]
, prod = \_ ->
let from = hour False 3
to = hour False 12
in Token Time . mkLatent . partOfDay <$>
interval TTime.Open from to
}
ruleThisPartofday :: Rule
ruleThisPartofday = Rule
{ name = "this <part-of-day>"
, pattern =
[ regex "diesen?|dieses|heute"
, Predicate isAPartOfDay
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) -> Token Time . partOfDay <$>
intersect (cycleNth TG.Day 0) td
_ -> Nothing
}
ruleThisCycle :: Rule
ruleThisCycle = Rule
{ name = "this <cycle>"
, pattern =
[ regex "diese(r|n|s)?|kommende(r|n|s)?"
, dimension TimeGrain
]
, prod = \tokens -> case tokens of
(_:Token TimeGrain grain:_) ->
tt $ cycleNth grain 0
_ -> Nothing
}
ruleThisTime :: Rule
ruleThisTime = Rule
{ name = "this <time>"
, pattern =
[ regex "diese(n|r|s)?|(im )?laufenden"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) ->
tt $ predNth 0 False td
_ -> Nothing
}
ruleDurationHence :: Rule
ruleDurationHence = Rule
{ name = "<duration> hence"
, pattern =
[ dimension Duration
, regex "hence"
]
, prod = \tokens -> case tokens of
(Token Duration dd:_) ->
tt $ inDuration dd
_ -> Nothing
}
ruleDayofmonthNonOrdinalOfNamedmonth :: Rule
ruleDayofmonthNonOrdinalOfNamedmonth = Rule
{ name = "<day-of-month> (non ordinal) of <named-month>"
, pattern =
[ Predicate isDOMInteger
, regex "vom|von"
, Predicate isAMonth
]
, prod = \tokens -> case tokens of
(token:_:Token Time td:_) -> Token Time <$> intersectDOM td token
_ -> Nothing
}
ruleNikolaus :: Rule
ruleNikolaus = Rule
{ name = "Nikolaus"
, pattern =
[ regex "nikolaus(tag)?|nikolaus tag|nikolo"
]
, prod = \_ -> tt $ monthDay 12 6
}
ruleAfterLunch :: Rule
ruleAfterLunch = Rule
{ name = "after lunch"
, pattern =
[ regex "nach dem mittagessen|nachmittags?"
]
, prod = \_ -> do
let td1 = cycleNth TG.Day 0
td2 <- interval TTime.Open (hour False 13) (hour False 17)
Token Time . partOfDay <$> intersect td1 td2
}
ruleOnANamedday :: Rule
ruleOnANamedday = Rule
{ name = "on a named-day"
, pattern =
[ regex "an einem"
, Predicate isADayOfWeek
]
, prod = \tokens -> case tokens of
(_:x:_) -> Just x
_ -> Nothing
}
ruleYearLatent :: Rule
ruleYearLatent = Rule
{ name = "year (latent)"
, pattern =
[ Predicate $
liftM2 (||) (isIntegerBetween (- 10000) 0) (isIntegerBetween 25 999)
]
, prod = \tokens -> case tokens of
(token:_) -> do
y <- getIntValue token
tt . mkLatent $ year y
_ -> Nothing
}
ruleYesterday :: Rule
ruleYesterday = Rule
{ name = "yesterday"
, pattern =
[ regex "gestern"
]
, prod = \_ -> tt . cycleNth TG.Day $ - 1
}
ruleSeason2 :: Rule
ruleSeason2 = Rule
{ name = "season"
, pattern =
[ regex "herbst"
]
, prod = \_ ->
let from = monthDay 9 23
to = monthDay 12 21
in Token Time <$> interval TTime.Open from to
}
ruleAfterTimeofday :: Rule
ruleAfterTimeofday = Rule
{ name = "after <time-of-day>"
, pattern =
[ regex "nach|ab|fr(\x00fc)he?stens"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) -> tt $ withDirection TTime.After td
_ -> Nothing
}
ruleAfterTimeofdayPostfix :: Rule
ruleAfterTimeofdayPostfix = Rule
{ name = "<time-of-day> after "
, pattern =
[ dimension Time
, regex "frühe?stens"
]
, prod = \tokens -> case tokens of
(Token Time td:_:_) -> tt $ withDirection TTime.After td
_ -> Nothing
}
ruleChristmas :: Rule
ruleChristmas = Rule
{ name = "christmas"
, pattern =
[ regex "weih?nacht(en|stag)?"
]
, prod = \_ -> tt $ monthDay 12 25
}
ruleNight :: Rule
ruleNight = Rule
{ name = "night"
, pattern =
[ regex "nachts?"
]
, prod = \_ ->
let from = hour False 0
to = hour False 4
in Token Time . mkLatent . partOfDay <$>
interval TTime.Open from to
}
ruleDayofmonthOrdinal :: Rule
ruleDayofmonthOrdinal = Rule
{ name = "<day-of-month> (ordinal)"
, pattern =
[ Predicate isDOMOrdinal
]
, prod = \tokens -> case tokens of
(Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->
tt $ dayOfMonth v
_ -> Nothing
}
ruleTimeofdayAmpm :: Rule
ruleTimeofdayAmpm = Rule
{ name = "<time-of-day> am|pm"
, pattern =
[ Predicate isATimeOfDay
, regex "([ap])\\.?m\\.?(?:[\\s'\"-_{}\\[\\]()]|$)"
]
, prod = \tokens -> case tokens of
(Token Time td:Token RegexMatch (GroupMatch (ap:_)):_) ->
tt . timeOfDayAMPM td $ Text.toLower ap == "a"
_ -> Nothing
}
ruleHalfIntegerGermanStyleHourofday :: Rule
ruleHalfIntegerGermanStyleHourofday = Rule
{ name = "half <integer> (german style hour-of-day)"
, pattern =
[ regex "halb"
, Predicate isAnHourOfDay
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) -> do
t <- minutesBefore 30 td
Just $ Token Time t
_ -> Nothing
}
ruleOrdinalCycleAfterTime :: Rule
ruleOrdinalCycleAfterTime = Rule
{ name = "<ordinal> <cycle> after <time>"
, pattern =
[ dimension Ordinal
, dimension TimeGrain
, regex "nach"
, dimension Time
]
, prod = \tokens -> case tokens of
(Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->
tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td
_ -> Nothing
}
ruleOrdinalCycleOfTime :: Rule
ruleOrdinalCycleOfTime = Rule
{ name = "<ordinal> <cycle> of <time>"
, pattern =
[ dimension Ordinal
, dimension TimeGrain
, regex "im|in|von"
, dimension Time
]
, prod = \tokens -> case tokens of
(Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->
tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td
_ -> Nothing
}
ruleAfterNextTime :: Rule
ruleAfterNextTime = Rule
{ name = "after next <time>"
, pattern =
[ regex "(\x00fc)ber ?n(\x00e4)chste[ns]?"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Time td:_) ->
tt $ predNth 1 True td
_ -> Nothing
}
ruleNamedmonth5 :: Rule
ruleNamedmonth5 = Rule
{ name = "named-month"
, pattern =
[ regex "mai"
]
, prod = \_ -> tt $ month 5
}
ruleNamedday7 :: Rule
ruleNamedday7 = Rule
{ name = "named-day"
, pattern =
[ regex "sonntags?|so\\.?"
]
, prod = \_ -> tt $ dayOfWeek 7
}
ruleHhmm :: Rule
ruleHhmm = Rule
{ name = "hh:mm"
, pattern =
[ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)(?:uhr|h)?"
]
, prod = \tokens -> case tokens of
(Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do
h <- parseInt m1
m <- parseInt m2
tt $ hourMinute False h m
_ -> Nothing
}
ruleTonight :: Rule
ruleTonight = Rule
{ name = "tonight"
, pattern =
[ regex "heute? (am)? abends?"
]
, prod = \_ -> do
let td1 = cycleNth TG.Day 0
td2 <- interval TTime.Open (hour False 18) (hour False 0)
Token Time . partOfDay <$> intersect td1 td2
}
ruleYear :: Rule
ruleYear = Rule
{ name = "year"
, pattern =
[ Predicate $ isIntegerBetween 1000 2100
]
, prod = \tokens -> case tokens of
(token:_) -> do
y <- getIntValue token
tt $ year y
_ -> Nothing
}
ruleNamedmonth10 :: Rule
ruleNamedmonth10 = Rule
{ name = "named-month"
, pattern =
[ regex "oktober|okt\\.?"
]
, prod = \_ -> tt $ month 10
}
ruleHalloweenDay :: Rule
ruleHalloweenDay = Rule
{ name = "halloween day"
, pattern =
[ regex "hall?owe?en?"
]
, prod = \_ -> tt $ monthDay 10 31
}
ruleNamedmonthDayofmonthNonOrdinal :: Rule
ruleNamedmonthDayofmonthNonOrdinal = Rule
{ name = "<named-month> <day-of-month> (non ordinal)"
, pattern =
[ Predicate isAMonth
, Predicate isDOMInteger
]
, prod = \tokens -> case tokens of
(Token Time td:token:_) -> Token Time <$> intersectDOM td token
_ -> Nothing
}
ruleHhmmMilitary :: Rule
ruleHhmmMilitary = Rule
{ name = "hhmm (military)"
, pattern =
[ regex "((?:[01]?\\d)|(?:2[0-3]))([0-5]\\d)"
]
, prod = \tokens -> case tokens of
(Token RegexMatch (GroupMatch (h:m:_)):_) -> do
hh <- parseInt h
mm <- parseInt m
tt . mkLatent $ hourMinute False hh mm
_ -> Nothing
}
ruleAbsorptionOfAfterNamedDay :: Rule
ruleAbsorptionOfAfterNamedDay = Rule
{ name = "absorption of , after named day"
, pattern =
[ Predicate isADayOfWeek
, regex ","
]
, prod = \tokens -> case tokens of
(x:_) -> Just x
_ -> Nothing
}
ruleLastDayofweekOfTime :: Rule
ruleLastDayofweekOfTime = Rule
{ name = "last <day-of-week> of <time>"
, pattern =
[ regex "letzte(r|n|s)?"
, Predicate isADayOfWeek
, regex "um|im"
, dimension Time
]
, prod = \tokens -> case tokens of
(_:Token Time td1:_:Token Time td2:_) ->
tt $ predLastOf td1 td2
_ -> Nothing
}
ruleFathersDay :: Rule
ruleFathersDay = Rule
{ name = "Father's Day"
, pattern =
[ regex "vatt?ertag|vatt?er (tag)?"
]
, prod = \_ -> tt $ nthDOWOfMonth 2 7 6
}
ruleHhmmMilitaryAmpm :: Rule
ruleHhmmMilitaryAmpm = Rule
{ name = "hhmm (military) am|pm"
, pattern =
[ regex "((?:1[012]|0?\\d))([0-5]\\d)"
, regex "([ap])\\.?m\\.?(?:[\\s'\"-_{}\\[\\]()]|$)"
]
, prod = \tokens -> case tokens of
(Token RegexMatch (GroupMatch (hh:mm:_)):Token RegexMatch (GroupMatch (ap:_)):_) -> do
h <- parseInt hh
m <- parseInt mm
tt . timeOfDayAMPM (hourMinute True h m) $
Text.toLower ap == "a"
_ -> Nothing
}
ruleTimeofdayTimeofdayInterval :: Rule
ruleTimeofdayTimeofdayInterval = Rule
{ name = "<time-of-day> - <time-of-day> (interval)"
, pattern =
[ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent
, regex "\\-|bis"
, Predicate isATimeOfDay
]
, prod = \tokens -> case tokens of
(Token Time td1:_:Token Time td2:_) ->
Token Time <$> interval TTime.Closed td1 td2
_ -> Nothing
}
ruleTimeofdayTimeofdayInterval2 :: Rule
ruleTimeofdayTimeofdayInterval2 = Rule
{ name = "<time-of-day> - <time-of-day> (interval)"
, pattern =
[ Predicate isATimeOfDay
, regex "\\-|bis"
, Predicate $ liftM2 (&&) isATimeOfDay isNotLatent
]
, prod = \tokens -> case tokens of
(Token Time td1:_:Token Time td2:_) ->
Token Time <$> interval TTime.Closed td1 td2
_ -> Nothing
}
ruleNamedmonth11 :: Rule
ruleNamedmonth11 = Rule
{ name = "named-month"
, pattern =
[ regex "november|nov\\.?"
]
, prod = \_ -> tt $ month 11
}
ruleDurationAfterTime :: Rule
ruleDurationAfterTime = Rule
{ name = "<duration> after <time>"
, pattern =
[ dimension Duration
, regex "nach"
, dimension Time
]
, prod = \tokens -> case tokens of
(Token Duration dd:_:Token Time td:_) ->
tt $ durationAfter dd td
_ -> Nothing
}
ruleOrdinalQuarter :: Rule
ruleOrdinalQuarter = Rule
{ name = "<ordinal> quarter"
, pattern =
[ dimension Ordinal
, Predicate $ isGrain TG.Quarter
]
, prod = \tokens -> case tokens of
(Token Ordinal (OrdinalData {TOrdinal.value = v}):_) -> tt .
cycleNthAfter False TG.Quarter (v - 1) $ cycleNth TG.Year 0
_ -> Nothing
}
ruleNamedday3 :: Rule
ruleNamedday3 = Rule
{ name = "named-day"
, pattern =
[ regex "mittwochs?|mi\\.?"
]
, prod = \_ -> tt $ dayOfWeek 3
}
ruleTheDayofmonthOrdinal :: Rule
ruleTheDayofmonthOrdinal = Rule
{ name = "the <day-of-month> (ordinal)"
, pattern =
[ regex "der"
, Predicate isDOMOrdinal
]
, prod = \tokens -> case tokens of
(_:Token Ordinal (OrdinalData {TOrdinal.value = v}):_) ->
tt $ dayOfMonth v
_ -> Nothing
}
ruleDurationBeforeTime :: Rule
ruleDurationBeforeTime = Rule
{ name = "<duration> before <time>"
, pattern =
[ dimension Duration
, regex "vor"
, dimension Time
]
, prod = \tokens -> case tokens of
(Token Duration dd:_:Token Time td:_) ->
tt $ durationBefore dd td
_ -> Nothing
}
rulePartofdayOfTime :: Rule
rulePartofdayOfTime = Rule
{ name = "<part-of-day> of <time>"
, pattern =
[ Predicate isAPartOfDay
, regex "des|von|vom|am"
, dimension Time
]
, prod = \tokens -> case tokens of
(Token Time td1:_:Token Time td2:_) ->
Token Time <$> intersect td1 td2
_ -> Nothing
}
ruleMmddyyyy :: Rule
ruleMmddyyyy = Rule
{ name = "mm/dd/yyyy"
, pattern =
[ regex "([012]?[1-9]|10|20|30|31)\\.(0?[1-9]|10|11|12)\\.(\\d{2,4})"
]
, prod = \tokens -> case tokens of
(Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do
y <- parseInt m3
m <- parseInt m2
d <- parseInt m1
tt $ yearMonthDay y m d
_ -> Nothing
}
ruleEoyendOfYear :: Rule
ruleEoyendOfYear = Rule
{ name = "EOY|End of year"
, pattern =
[ regex "(das )?(EOY|jahr(es)? ?ende|ende (des )?jahr(es)?)"
]
, prod = \_ -> tt $ cycleNth TG.Year 1
}
ruleTomorrow :: Rule
ruleTomorrow = Rule
{ name = "tomorrow"
, pattern =
[ regex "morgen"
]
, prod = \_ -> tt $ cycleNth TG.Day 1
}
ruleMothersDay :: Rule
ruleMothersDay = Rule
{ name = "Mother's Day"
, pattern =
[ regex "mutt?ertag|mutt?er (tag)?"
]
, prod = \_ -> tt $ nthDOWOfMonth 1 7 5
}
ruleTimeofdayOclock :: Rule
ruleTimeofdayOclock = Rule
{ name = "<time-of-day> o'clock"
, pattern =
[ Predicate isATimeOfDay
, regex "uhr|h(?:[\\s'\"-_{}\\[\\]()]|$)"
]
, prod = \tokens -> case tokens of
(Token Time td:_) ->
tt $ notLatent td
_ -> Nothing
}
ruleNamedmonth9 :: Rule
ruleNamedmonth9 = Rule
{ name = "named-month"
, pattern =
[ regex "september|sept?\\.?"
]
, prod = \_ -> tt $ month 9
}
ruleDayofmonthordinalNamedmonthYear :: Rule
ruleDayofmonthordinalNamedmonthYear = Rule
{ name = "<day-of-month>(ordinal) <named-month> year"
, pattern =
[ Predicate isDOMOrdinal
, Predicate isAMonth
, regex "(\\d{2,4})"
]
, prod = \tokens -> case tokens of
(token:
Token Time td:
Token RegexMatch (GroupMatch (match:_)):
_) -> do
n <- parseInt match
dom <- intersectDOM td token
Token Time <$> intersect dom (year n)
_ -> Nothing
}
ruleTimezone :: Rule
ruleTimezone = Rule
{ name = "<time> timezone"
, pattern =
[ Predicate $ liftM2 (&&) isATimeOfDay isNotLatent
, regex "\\b(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)\\b"
]
, prod = \tokens -> case tokens of
(Token Time td:
Token RegexMatch (GroupMatch (tz:_)):
_) -> Token Time <$> inTimezone tz td
_ -> Nothing
}
rules :: [Rule]
rules =
[ ruleADuration
, ruleAboutTimeofday
, ruleAbsorptionOfAfterNamedDay
, ruleAfterDuration
, ruleAfterLunch
, ruleAfterNextTime
, ruleAfterTimeofday
, ruleAfterTimeofdayPostfix
, ruleAfterTomorrow
, ruleAfterWork
, ruleAfternoon
, ruleAllerheiligen
, ruleAtTimeofday
, ruleBeforeYesterday
, ruleBetweenDatetimeAndDatetimeInterval
, ruleBetweenTimeofdayAndTimeofdayInterval
, ruleByTheEndOfTime
, ruleChristmas
, ruleChristmasEve
, ruleDatetimeDatetimeInterval
, ruleDayofmonthNonOrdinalNamedmonth
, ruleDayofmonthNonOrdinalOfNamedmonth
, ruleDayofmonthOrdinal
, ruleDayofmonthordinalNamedmonth
, ruleDayofmonthordinalNamedmonthYear
, ruleDurationAfterTime
, ruleDurationAgo
, ruleDurationBeforeTime
, ruleDurationFromNow
, ruleDurationHence
, ruleEomendOfMonth
, ruleEoyendOfYear
, ruleEvening
, ruleExactlyTimeofday
, ruleFathersDay
, ruleFromDatetimeDatetimeInterval
, ruleFromTimeofdayTimeofdayInterval
, ruleHalfIntegerGermanStyleHourofday
, ruleHalloweenDay
, ruleHhmm
, ruleHhmmMilitary
, ruleHhmmMilitaryAmpm
, ruleHourofdayIntegerAsRelativeMinutes
, ruleInDuration
, ruleInduringThePartofday
, ruleIntersect
, ruleIntersectBy
, ruleIntersectByOfFromS
, ruleLastCycle
, ruleLastCycleOfTime
, ruleLastDayofweekOfTime
, ruleLastNCycle
, ruleLastTime
, ruleLunch
, ruleMidnighteodendOfDay
, ruleMmdd
, ruleMmddyyyy
, ruleMonthDdddInterval
, ruleMorning
, ruleMothersDay
, ruleNamedday
, ruleNamedday2
, ruleNamedday3
, ruleNamedday4
, ruleNamedday5
, ruleNamedday6
, ruleNamedday7
, ruleNamedmonth
, ruleNamedmonth10
, ruleNamedmonth11
, ruleNamedmonth12
, ruleNamedmonth2
, ruleNamedmonth3
, ruleNamedmonth4
, ruleNamedmonth5
, ruleNamedmonth6
, ruleNamedmonth7
, ruleNamedmonth8
, ruleNamedmonth9
, ruleNamedmonthDayofmonthNonOrdinal
, ruleNamedmonthDayofmonthOrdinal
, ruleNewYearsDay
, ruleNewYearsEve
, ruleNextCycle
, ruleNextNCycle
, ruleNextTime
, ruleNight
, ruleNikolaus
, ruleNoon
, ruleNow
, ruleNthTimeAfterTime
, ruleNthTimeAfterTime2
, ruleNthTimeOfTime
, ruleNthTimeOfTime2
, ruleOnANamedday
, ruleOnDate
, ruleOrdinalCycleAfterTime
, ruleOrdinalCycleOfTime
, ruleOrdinalQuarter
, ruleOrdinalQuarterYear
, rulePartofdayOfTime
, ruleRelativeMinutesAfterpastIntegerHourofday
, ruleRelativeMinutesTotillbeforeIntegerHourofday
, ruleSchweizerBundesfeiertag
, ruleSeason
, ruleSeason2
, ruleSeason3
, ruleSeason4
, ruleSterreichischerNationalfeiertag
, ruleTagDerDeutschenEinheit
, ruleTheCycleAfterTime
, ruleTheCycleBeforeTime
, ruleTheDayofmonthNonOrdinal
, ruleTheDayofmonthOrdinal
, ruleTheIdesOfNamedmonth
, ruleTheOrdinalCycleAfterTime
, ruleTheOrdinalCycleOfTime
, ruleThisCycle
, ruleThisPartofday
, ruleThisTime
, ruleThisnextDayofweek
, ruleTimeAfterNext
, ruleTimeBeforeLast
, ruleTimePartofday
, ruleTimeofdayAmpm
, ruleTimeofdayApproximately
, ruleTimeofdayLatent
, ruleTimeofdayOclock
, ruleTimeofdaySharp
, ruleTimeofdayTimeofdayInterval
, ruleTimeofdayTimeofdayInterval2
, ruleToday
, ruleTomorrow
, ruleTonight
, ruleUntilTimeofday
, ruleUntilTimeofdayPostfix
, ruleValentinesDay
, ruleWeekend
, ruleWithinDuration
, ruleYear
, ruleYearLatent
, ruleYearLatent2
, ruleYesterday
, ruleYyyymmdd
, ruleQuarterTotillbeforeIntegerHourofday
, ruleHalfTotillbeforeIntegerHourofday
, ruleQuarterAfterpastIntegerHourofday
, ruleHalfAfterpastIntegerHourofday
, ruleHourofdayQuarter
, ruleHourofdayHalf
, ruleTimezone
]