mirror of
https://github.com/facebook/duckling.git
synced 2025-01-08 15:00:59 +03:00
75af12524f
Summary: closes https://github.com/facebook/duckling/issues/331 Pull Request resolved: https://github.com/facebook/duckling/pull/332 Reviewed By: girifb Differential Revision: D26283481 Pulled By: chessai fbshipit-source-id: 054c6467a69896ff3ebbd1f9bc0734aadf1b6dbe
1939 lines
55 KiB
Haskell
1939 lines
55 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.
|
|
|
|
|
|
{-# LANGUAGE GADTs #-}
|
|
{-# LANGUAGE LambdaCase #-}
|
|
{-# LANGUAGE NoRebindableSyntax #-}
|
|
{-# LANGUAGE OverloadedStrings #-}
|
|
|
|
module Duckling.Time.DE.Rules
|
|
( rules
|
|
) where
|
|
|
|
import Prelude
|
|
import qualified Data.Text as Text
|
|
|
|
import Duckling.Dimensions.Types
|
|
import Duckling.Duration.Helpers (isGrain)
|
|
import Duckling.Numeral.Helpers (parseInt)
|
|
import Duckling.Ordinal.Types (OrdinalData(..))
|
|
import Duckling.Regex.Types (GroupMatch(..))
|
|
import Duckling.Time.Computed
|
|
import Duckling.Time.Helpers
|
|
import Duckling.Time.HolidayHelpers
|
|
import Duckling.Time.Types (TimeData(..))
|
|
import Duckling.Types
|
|
import qualified Duckling.Ordinal.Types as TOrdinal
|
|
import qualified Duckling.Time.Types as TTime
|
|
import qualified Duckling.TimeGrain.Types as TG
|
|
|
|
ruleInstants :: [Rule]
|
|
ruleInstants = mkRuleInstants
|
|
[ ( "now" , TG.Second, 0,
|
|
"(genau)? ?jetzt|diesen moment|in diesem moment|gerade eben" )
|
|
, ( "today" , TG.Day , 0,
|
|
"heute|(um diese zeit|zu dieser zeit|um diesen zeitpunkt|zu diesem zeitpunkt)" )
|
|
, ( "tomorrow" , TG.Day , 1, "morgen" )
|
|
, ( "yesterday" , TG.Day , -1, "gestern" )
|
|
, ( "after tomorrow" , TG.Day , 2, "(ü)bermorgen" )
|
|
, ( "before yesterday", TG.Day , -2, "vorgestern" )
|
|
, ( "3 days ago" , TG.Day , -3, "vorvorgestern" )
|
|
, ( "EOM|End of month", TG.Month , 1, "(das )?ende des monats?" )
|
|
, ( "EOY|End of year" , TG.Year , 1,
|
|
"(das )?(EOY|jahr(es)? ?ende|ende (des )?jahr(es)?)" )
|
|
]
|
|
|
|
ruleDaysOfWeek :: [Rule]
|
|
ruleDaysOfWeek = mkRuleDaysOfWeek
|
|
[ ( "Montag" , "montags?|mo\\.?" )
|
|
, ( "Dienstag" , "die?nstags?|di\\.?" )
|
|
, ( "Mittwoch" , "mittwochs?|mi\\.?" )
|
|
, ( "Donnerstag", "donn?erstag|do\\.?" )
|
|
, ( "Freitag" , "freitags?|fr\\.?" )
|
|
, ( "Samstag" , "samstags?|sonnabends?|sa\\.?" )
|
|
, ( "Sonntag" , "sonntags?|so\\." )
|
|
]
|
|
|
|
ruleMonths :: [Rule]
|
|
ruleMonths = mkRuleMonths
|
|
[ ( "Januar" , "januar|jan\\.?" )
|
|
, ( "Februar" , "februar|feb\\.?" )
|
|
, ( "Marz" , "m(ä)rz|m(ä)r\\.?" )
|
|
, ( "April" , "april|apr\\.?" )
|
|
, ( "Mai" , "mai\\.?" )
|
|
, ( "Juni" , "juni|jun\\.?" )
|
|
, ( "Juli" , "juli|jul\\.?" )
|
|
, ( "August" , "august|aug\\.?" )
|
|
, ( "September", "september|sept?\\.?" )
|
|
, ( "Oktober" , "oktober|okt\\.?" )
|
|
, ( "November" , "november|nov\\.?" )
|
|
, ( "Dezember" , "dezember|dez\\.?" )
|
|
]
|
|
|
|
ruleSeasons :: [Rule]
|
|
ruleSeasons = mkRuleSeasons
|
|
[ ( "sommer" , "sommer" , monthDay 6 21, monthDay 9 23 )
|
|
, ( "herbst" , "herbst" , monthDay 9 23, monthDay 12 21 )
|
|
, ( "winter" , "winter" , monthDay 12 21, monthDay 3 20 )
|
|
, ( "fruhling", "fr(ü)h(ling|jahr)", monthDay 3 20, monthDay 6 21 )
|
|
]
|
|
|
|
ruleHolidays :: [Rule]
|
|
ruleHolidays = mkRuleHolidays
|
|
[ ( "Neujahr" , "neujahr(s?tag)?"
|
|
, monthDay 1 1 )
|
|
, ( "Valentinstag" , "valentin'?stag"
|
|
, monthDay 2 14 )
|
|
, ( "Schweizer Bundesfeiertag"
|
|
, "schweiz(er)? (bundes)?feiertag|bundes feiertag"
|
|
, monthDay 8 1 )
|
|
, ( "Tag der Deutschen Einheit" , "tag (der)? deutsc?hen? einheit"
|
|
, monthDay 10 3 )
|
|
, ( "Oesterreichischer Nationalfeiertag"
|
|
, "((ö)sterreichischer?)? nationalfeiertag|national feiertag"
|
|
, monthDay 10 26 )
|
|
, ( "Halloween" , "hall?owe?en?"
|
|
, monthDay 10 31 )
|
|
, ( "Allerheiligen" , "allerheiligen?|aller heiligen?"
|
|
, monthDay 11 1 )
|
|
, ( "Nikolaus" , "nikolaus(tag)?|nikolaus tag|nikolo"
|
|
, monthDay 12 6 )
|
|
, ( "Heiligabend" , "heilig(er)? abend"
|
|
, monthDay 12 24 )
|
|
, ( "Weihnachten" , "weih?nacht(en|stag)?"
|
|
, monthDay 12 25 )
|
|
, ( "Silvester" , "silvester"
|
|
, monthDay 12 31 )
|
|
, ( "Muttertag" , "mutt?ertag|mutt?er (tag)?"
|
|
, nthDOWOfMonth 2 7 5 )
|
|
, ( "Vatertag" , "vatt?er( ?tag)?"
|
|
, nthDOWOfMonth 3 7 6 )
|
|
]
|
|
|
|
ruleComputedHolidays :: [Rule]
|
|
ruleComputedHolidays = mkRuleHolidays
|
|
[ ( "Christi Himmelfahrt", "(christi\\s+)?himmelfahrt(stag)?"
|
|
, cycleNthAfter False TG.Day 39 easterSunday )
|
|
, ( "Aschermittwoch", "ascher?(tag|mittwoch)"
|
|
, cycleNthAfter False TG.Day (-46) easterSunday )
|
|
, ( "Aschura", "asc?hura(\\-?tag)?"
|
|
, cycleNthAfter False TG.Day 9 muharram )
|
|
, ( "Bhai Dooj", "bhai(ya)?\\s+d(u|oo)j|bhau\\-beej|bhai\\s+(tika|phonta)"
|
|
, cycleNthAfter False TG.Day 4 dhanteras )
|
|
, ( "Chhath", "chhathi?|chhath (parv|puja)|dala (chhath|puja)|surya shashthi"
|
|
, cycleNthAfter False TG.Day 8 dhanteras )
|
|
, ( "Boghi", "boghi|bogi\\s+pandigai"
|
|
, cycleNthAfter False TG.Day (-1) thaiPongal )
|
|
, ( "Chinesisches Neujahr", "chinesische(s|r)\\s+(neujahr(s(tag|fest))?|frühlingsfest)"
|
|
, chineseNewYear )
|
|
, ( "Aschermontag"
|
|
, "(orthodoxer?\\s+)?(ascher|reiner?\\s+|sauberer?\\s+)montag"
|
|
, cycleNthAfter False TG.Day (-48) orthodoxEaster )
|
|
, ( "Corpus Christi", "corpus\\s+christi|fronleichnam"
|
|
, cycleNthAfter False TG.Day 60 easterSunday )
|
|
, ( "Dhanteras", "dhanatrayodashi|dhanteras|dhanvantari\\s+trayodashi"
|
|
, dhanteras )
|
|
, ( "Diwali", "deepavali|diwali|lakshmi\\s+puja"
|
|
, cycleNthAfter False TG.Day 2 dhanteras )
|
|
, ( "Durga Ashtami", "(durga|maha)(\\s+a)?shtami"
|
|
, cycleNthAfter False TG.Day 7 navaratri )
|
|
, ( "Ostermontag", "ostermontag"
|
|
, cycleNthAfter False TG.Day 1 easterSunday )
|
|
, ( "Ostersonntag", "ostersonntag", easterSunday )
|
|
, ( "Eid al-Adha", "bakr[\\-\\s]e?id|e?id [au]l\\-adha|opferfest"
|
|
, eidalAdha )
|
|
, ( "Eid al-Fitr", "eid al\\-fitr", eidalFitr )
|
|
, ( "Govardhan Puja", "govardhan\\s+puja|annak(u|oo)t"
|
|
, cycleNthAfter False TG.Day 3 dhanteras )
|
|
, ( "Karfreitag", "(kar|stiller\\s+|hoher\\s+)freitag"
|
|
, cycleNthAfter False TG.Day (-2) easterSunday )
|
|
, ( "Guru Gobind Singh Jayanti"
|
|
, "guru\\s+(gobind|govind)\\s+singh\\s+(Geburtstag|jayanti)"
|
|
, guruGobindSinghJayanti )
|
|
, ( "Holi", "(rangwali )?holi|dhuleti|dhulandi|phagwah"
|
|
, cycleNthAfter False TG.Day 39 vasantPanchami )
|
|
, ( "Holika Dahan", "holika dahan|kamudu pyre|chhoti holi"
|
|
, cycleNthAfter False TG.Day 38 vasantPanchami )
|
|
, ( "Karsamstag"
|
|
, "(kar|stiller\\s+)samstag|karsonnabend"
|
|
, cycleNthAfter False TG.Day (-1) easterSunday )
|
|
, ( "Islamisches Neujahr", "(arabisches|hijri|islamisches) neujahr|amun jadid|muharram"
|
|
, muharram )
|
|
, ( "Isra and Mi'raj"
|
|
, "isra and mi'raj|aufstieg des propheten|(die\\s+)?nachtreise|aufstieg\\s+in\\s+den\\s+himmel"
|
|
, cycleNthAfter False TG.Day 26 rajab
|
|
)
|
|
, ( "Jumu'atul-Wida", "jumu'atul\\-widaa?'?|jamat[\\-\\s]ul[\\-\\s]vida"
|
|
, predNthAfter (-1) (dayOfWeek 5) eidalFitr )
|
|
, ( "Kaanum Pongal", "(kaanum|kanni)\\s+pongal"
|
|
, cycleNthAfter False TG.Day 2 thaiPongal )
|
|
, ( "Lag BaOmer", "lag (b|l)[a']omer", lagBaOmer )
|
|
, ( "Vaisakhi", "mesadi|[bv]aisakhi|vaisakhadi|vasakhi|vaishakhi", vaisakhi)
|
|
, ( "Lailat al-Qadr"
|
|
, "la[iy]lat al[\\-\\s][qk]adr|(die)? nacht der (bestimmung|allmacht)"
|
|
, cycleNthAfter False TG.Day 26 ramadan )
|
|
, ( "Lazarus-Samstag", "lazarus(\\-|\\s+)samstag"
|
|
, cycleNthAfter False TG.Day (-8) orthodoxEaster )
|
|
, ( "Maha Navami", "maha\\s+navami", cycleNthAfter False TG.Day 8 navaratri )
|
|
, ( "Maha Saptami", "maha\\s+saptami", cycleNthAfter False TG.Day 6 navaratri )
|
|
, ( "Mattu Pongal", "maa?ttu\\s+pongal"
|
|
, cycleNthAfter False TG.Day 1 thaiPongal )
|
|
, ( "Gründonnerstag"
|
|
, "(grün|hoher\\s+|heiliger\\s+|weißer\\s+|palm)donnerstag"
|
|
, cycleNthAfter False TG.Day (-3) easterSunday )
|
|
, ( "Maulid an-Nabī"
|
|
, "Maulid\\s+an\\-Nabī|mawlid(\\s+al\\-nab(awi|i\\s+al\\-sharif))?|mevli[dt]|mulud|geburtstag des propheten( muhammad)?"
|
|
, mawlid )
|
|
, ( "Naraka Chaturdashi"
|
|
, "naraka? (nivaran )?chaturdashi|(kali|roop) chaudas|choti diwali"
|
|
, cycleNthAfter False TG.Day 1 dhanteras )
|
|
, ( "Orthodoxer Ostermontag", "orthodoxer\\s+ostermontag"
|
|
, cycleNthAfter False TG.Day 1 orthodoxEaster )
|
|
, ( "Orthodoxer Ostersonntag", "orthodoxer\\s+ostersonntag"
|
|
, orthodoxEaster )
|
|
, ( "Orthodoxer Karsamstag", "orthodoxer\\s+karsamstag"
|
|
, cycleNthAfter False TG.Day (-1) orthodoxEaster )
|
|
, ( "Orthodoxer Karfreitag", "orthodoxer\\s+karfreitag"
|
|
, cycleNthAfter False TG.Day (-2) orthodoxEaster )
|
|
, ( "Orthodoxer Palmsonntag", "orthodoxer\\s+palmsonntag"
|
|
, cycleNthAfter False TG.Day (-7) orthodoxEaster )
|
|
, ( "Palmsonntag", "palmsonntag"
|
|
, cycleNthAfter False TG.Day (-7) easterSunday )
|
|
, ( "Pfingsten", "pfingsten|pentecost"
|
|
, cycleNthAfter False TG.Day 49 easterSunday )
|
|
, ( "Purim", "purim", purim )
|
|
, ( "Raksha Bandhan", "raksha(\\s+)?bandhan|rakhi", rakshaBandhan )
|
|
, ( "Pargat Diwas", "pargat diwas|(maharishi )?valmiki jayanti", pargatDiwas )
|
|
, ( "Mahavir Jayanti", "(mahavir|mahaveer) (jayanti|janma kalyanak)"
|
|
, mahavirJayanti )
|
|
, ( "Maha Shivaratri", "maha(\\s+)?shivaratri", mahaShivaRatri)
|
|
, ( "Dayananda Saraswati Jayanti","((maharishi|swami) )?(dayananda )?saraswati jayanti", saraswatiJayanti )
|
|
, ( "Karva Chauth", "karva\\s+chauth|karaka\\s+chaturthi", karvaChauth)
|
|
, ( "Krishna Janmashtami", "(krishna )?janmashtami|gokulashtami", krishnaJanmashtami )
|
|
, ( "Schmini Azeret", "sc?he?mini\\s+at?zeret"
|
|
, cycleNthAfter False TG.Day 21 roshHashana )
|
|
, ( "Fastnacht", "fastnacht(sdienstag)?|mardi gras"
|
|
, cycleNthAfter False TG.Day (-47) easterSunday )
|
|
, ( "Shushan Purim", "shushan\\s+purim", cycleNthAfter False TG.Day 1 purim )
|
|
, ( "Simchat Torah", "simc?hat\\s+torah"
|
|
, cycleNthAfter False TG.Day 22 roshHashana )
|
|
, ( "Thai Pongal"
|
|
, "(thai )?pongal|pongal pandigai|(makara? |magha )?sankranth?i|maghi"
|
|
, thaiPongal )
|
|
, ( "Thiru Onam", "(thiru(v|\\s+))?onam", thiruOnam )
|
|
, ( "Tisha B'Av", "tisha b'av", tishaBAv )
|
|
, ( "Dreifaltigkeitssonntag",
|
|
"trinitatis(fest)?|(dreifaltigkeits|goldener\\s+)sonntag|drei(faltigkeit|einigkeit)(sfest)?"
|
|
, cycleNthAfter False TG.Day 56 easterSunday )
|
|
, ( "Vasant Panchami", "[bv]asant\\s+panchami", vasantPanchami )
|
|
, ( "Vijayadashami", "dasara|duss(eh|he)ra|vijayadashami"
|
|
, cycleNthAfter False TG.Day 9 navaratri )
|
|
, ( "Tu biSchevat", "tu b[i']sc?he?vat", tuBishvat )
|
|
, ( "Vesak", "v(e|ai)sak(ha)?|buddha(\\-?tag|\\s+purnima)|wesakfest", vesak )
|
|
, ( "Jom Ha'atzmaut", "[yj]om ha'?atzmaut", yomHaatzmaut )
|
|
, ( "Jom HaShoah"
|
|
, "[yj]om hashoah|[yj]om hazikaron lashoah ve-lag'vurah|holocaust\\-?gedenktag"
|
|
, cycleNthAfter False TG.Day 12 passover )
|
|
, ( "Jom Kippur", "[yj]om\\s+kippur", cycleNthAfter False TG.Day 9 roshHashana )
|
|
, ( "Pfingstmontag", "pfingstmontag|(pentecost|whit)\\s+montag"
|
|
, cycleNthAfter False TG.Day 50 easterSunday )
|
|
, ( "Rabindra Jayanti", "rabindra(nath)?\\s+jayanti", rabindraJayanti )
|
|
, ("Guru Ravidass Jayanti", "guru\\s+ravidass?\\s+(geburtstag|jayanti)"
|
|
, ravidassJayanti )
|
|
]
|
|
|
|
ruleComputedHolidays' :: [Rule]
|
|
ruleComputedHolidays' = mkRuleHolidays'
|
|
[ ( "Global Youth Service-Tag", "global youth service[\\-\\s]?tag|gysd"
|
|
, let start = globalYouthServiceDay
|
|
end = cycleNthAfter False TG.Day 2 globalYouthServiceDay
|
|
in interval TTime.Open start end )
|
|
, ( "Große Fastenzeit", "große\\s+fastenzeit"
|
|
, let start = cycleNthAfter False TG.Day (-48) orthodoxEaster
|
|
end = cycleNthAfter False TG.Day (-9) orthodoxEaster
|
|
in interval TTime.Open start end )
|
|
, ( "Chanukka", "c?hann?ukk?ah?"
|
|
, let start = chanukah
|
|
end = cycleNthAfter False TG.Day 7 chanukah
|
|
in interval TTime.Open start end )
|
|
, ( "Fastenzeit", "fastenzeit"
|
|
, let start = cycleNthAfter False TG.Day (-46) easterSunday
|
|
end = cycleNthAfter False TG.Day (-1) easterSunday
|
|
in interval TTime.Open start end )
|
|
, ( "Navaratri", "durga\\s+puja|durgotsava|nava?rath?ri"
|
|
, let start = navaratri
|
|
end = cycleNthAfter False TG.Day 9 navaratri
|
|
in interval TTime.Open start end )
|
|
, ( "Pessach", "passover|pess?a[ck]?h|pascha|Passah?"
|
|
, let start = passover
|
|
end = cycleNthAfter False TG.Day 8 passover
|
|
in interval TTime.Open start end )
|
|
, ( "Ramadan", "rama[dt]h?an|ramzaa?n"
|
|
, let start = ramadan
|
|
end = cycleNthAfter False TG.Day (-1) eidalFitr
|
|
in interval TTime.Open start end )
|
|
, ( "Rosch haSchana", "rosch ha\\-?schanah?"
|
|
, let start = roshHashana
|
|
end = cycleNthAfter False TG.Day 2 roshHashana
|
|
in interval TTime.Open start end )
|
|
, ( "Schawuot", "sc?ha[vw]u'?oth?|shovuos"
|
|
, let start = cycleNthAfter False TG.Day 50 passover
|
|
end = cycleNthAfter False TG.Day 52 passover
|
|
in interval TTime.Open start end )
|
|
, ( "Sukkot", "Laubhüttenfest|su[ck]{2}o[st]"
|
|
, let start = cycleNthAfter False TG.Day 14 roshHashana
|
|
end = cycleNthAfter False TG.Day 22 roshHashana
|
|
in interval TTime.Open start end )
|
|
-- Does not account for leap years, so every 365 days.
|
|
, ( "Parsi Neujahr", "parsi neujahr|jamshedi navroz"
|
|
, predEveryNDaysFrom 365 (2020, 8, 16)
|
|
)
|
|
, ( "Earth Hour", "earth hour|stunde der erde"
|
|
, computeEarthHour )
|
|
, ( "Königstag", "königstag|koningsdag"
|
|
, computeKingsDay )
|
|
]
|
|
|
|
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
|
|
Token Time <$> minutesBefore n td
|
|
_ -> 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:_) -> Token Time <$> minutesBefore 15 td
|
|
_ -> 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:_) -> Token Time <$> minutesBefore 30 td
|
|
_ -> Nothing
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
ruleLastTime :: Rule
|
|
ruleLastTime = Rule
|
|
{ name = "last <time>"
|
|
, pattern =
|
|
[ regex "letzten?|letztes"
|
|
, Predicate isOkWithThisNext
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) ->
|
|
tt $ predNth (-1) False td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleDatetimeDatetimeInterval :: Rule
|
|
ruleDatetimeDatetimeInterval = Rule
|
|
{ name = "<datetime> - <datetime> (interval)"
|
|
, pattern =
|
|
[ Predicate isNotLatent
|
|
, regex "\\-|bis( zum)?|auf( den)?"
|
|
, Predicate isNotLatent
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Time td1:_:Token Time td2:_) ->
|
|
Token Time <$> interval TTime.Closed td1 td2
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleDateDateInterval :: Rule
|
|
ruleDateDateInterval = Rule
|
|
{ name = "dd.(mm.)? - dd.mm.(yy[yy]?)? (interval)"
|
|
, pattern =
|
|
[ regex "(?:vo[nm]\\s+)?(10|20|30|31|[012]?[1-9])\\.?((?<=\\.)(?:10|11|12|0?[1-9])(?:\\.?))?"
|
|
, regex "\\-|/|bis( zum)?|auf( den)?"
|
|
, regex "(10|20|30|31|[012]?[1-9])\\.(10|11|12|0?[1-9])\\.?((?<=\\.)\\d{2,4})?"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token RegexMatch (GroupMatch (d1:"":_)):
|
|
_:
|
|
Token RegexMatch (GroupMatch (d2:m2:"":_)):
|
|
_) -> do
|
|
d1 <- parseInt d1
|
|
d2 <- parseInt d2
|
|
m2 <- parseInt m2
|
|
Token Time <$> interval TTime.Closed (monthDay m2 d1) (monthDay m2 d2)
|
|
(Token RegexMatch (GroupMatch (d1:"":_)):
|
|
_:
|
|
Token RegexMatch (GroupMatch (d2:m2:y:_)):
|
|
_) -> do
|
|
d1 <- parseInt d1
|
|
d2 <- parseInt d2
|
|
m2 <- parseInt m2
|
|
y <- parseInt y
|
|
Token Time <$> interval TTime.Closed (yearMonthDay y m2 d1) (yearMonthDay y m2 d2)
|
|
(Token RegexMatch (GroupMatch (d1:m1:_)):
|
|
_:
|
|
Token RegexMatch (GroupMatch (d2:m2:"":_)):
|
|
_) -> do
|
|
d1 <- parseInt d1
|
|
d2 <- parseInt d2
|
|
m1 <- parseInt m1
|
|
m2 <- parseInt m2
|
|
Token Time <$> interval TTime.Closed (monthDay m1 d1) (monthDay m2 d2)
|
|
(Token RegexMatch (GroupMatch (d1:m1:_)):
|
|
_:
|
|
Token RegexMatch (GroupMatch (d2:m2:y:_)):
|
|
_) -> do
|
|
d1 <- parseInt d1
|
|
d2 <- parseInt d2
|
|
m1 <- parseInt m1
|
|
m2 <- parseInt m2
|
|
y <- parseInt y
|
|
Token Time <$> interval TTime.Closed (yearMonthDay y m1 d1) (yearMonthDay y m2 d2)
|
|
_ -> Nothing
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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( zum)?|auf( den)?"
|
|
, 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( zum)?|auf( den)?"
|
|
, 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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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(ä)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(ö)lf (uhr)?"
|
|
]
|
|
, prod = \_ -> tt $ hour False 12
|
|
}
|
|
|
|
ruleThisnextDayofweek :: Rule
|
|
ruleThisnextDayofweek = Rule
|
|
{ name = "this|next <day-of-week>"
|
|
, pattern =
|
|
[ regex "diese(n|r)|kommenden|n(ä)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(ä)chste(r|n|s)?|kommende(r|n|s)?"
|
|
, dimension TimeGrain
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token TimeGrain grain:_) ->
|
|
tt $ cycleNth grain 1
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleAfterNextCycle :: Rule
|
|
ruleAfterNextCycle = Rule
|
|
{ name = "after next <cycle>"
|
|
, pattern =
|
|
[ regex "(ü)ber ?n(ä)chste[ns]?"
|
|
, dimension TimeGrain
|
|
]
|
|
, prod = \case
|
|
(_:Token TimeGrain grain:_) ->
|
|
tt $ cycleNth grain 2
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleTimeofdayApproximately :: Rule
|
|
ruleTimeofdayApproximately = Rule
|
|
{ name = "<time-of-day> approximately"
|
|
, pattern =
|
|
[ Predicate isATimeOfDay
|
|
, regex "ca\\.?|circa|zirka|ungef(ä)hr|(in )?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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
ruleInduringThePartofday :: Rule
|
|
ruleInduringThePartofday = Rule
|
|
{ name = "in|during the <part-of-day>"
|
|
, pattern =
|
|
[ regex "(in|an|am|w(ä)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 $ and . sequence [isNotLatent, 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
|
|
}
|
|
|
|
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 "(?:am\\s+)?([012]?[1-9]|10|20|30|31)\\.(10|11|12|0?[1-9])\\.?"
|
|
]
|
|
, 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(ü)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
|
|
}
|
|
|
|
ruleExactlyTimeofday :: Rule
|
|
ruleExactlyTimeofday = Rule
|
|
{ name = "exactly <time-of-day>"
|
|
, pattern =
|
|
[ regex "genau|exakt|p(ü)nktlich|punkt( um)?"
|
|
, Predicate isATimeOfDay
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> tt $ notLatent td
|
|
_ -> Nothing
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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 now
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleAfterWork :: Rule
|
|
ruleAfterWork = Rule
|
|
{ name = "after work"
|
|
, pattern =
|
|
[ regex "nach (der)? arbeit|(am)? feier ?abend"
|
|
]
|
|
, prod = \_ -> do
|
|
td2 <- interval TTime.Open (hour False 17) (hour False 21)
|
|
Token Time . partOfDay <$> intersect today td2
|
|
}
|
|
|
|
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(ü)nktlich|punkt( um)?"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Time td:_) -> tt $ notLatent td
|
|
_ -> Nothing
|
|
}
|
|
|
|
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 now (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
|
|
}
|
|
|
|
|
|
ruleDayOfWeekIntersectDuration :: Rule
|
|
ruleDayOfWeekIntersectDuration = Rule
|
|
{ name = "<day-of-week> in <duration>"
|
|
, pattern =
|
|
[ Predicate isADayOfWeek
|
|
, regex "(in|vor)"
|
|
, dimension Duration
|
|
]
|
|
, prod = \case
|
|
(Token Time td:Token RegexMatch (GroupMatch (match:_)):Token Duration dd:_) ->
|
|
case Text.toLower match of
|
|
"vor" -> Token Time <$> intersect td (durationIntervalAgo dd)
|
|
_ -> Token Time <$> intersect td (inDurationInterval dd)
|
|
_ -> Nothing
|
|
}
|
|
ruleAboutTimeofday :: Rule
|
|
ruleAboutTimeofday = Rule
|
|
{ name = "about <time-of-day>"
|
|
, pattern =
|
|
[ regex "so( um)?|(so |um |so um )?circa|zirka|ca\\.?|ungef(ä)hr|(etwa|gegen)( so| um| so um)?"
|
|
, 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(ä)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(ä)testens"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Time td:_:_) -> tt $ withDirection TTime.Before td
|
|
_ -> Nothing
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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 = \_ -> tt $ mkOkForThisNext weekend
|
|
}
|
|
|
|
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(ä)chste|kommende)[ns]?"
|
|
, Predicate $ and . sequence [isNotLatent, isOkWithThisNext]
|
|
]
|
|
, 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})-(1[0-2]|0?[1-9])-(3[01]|[12]\\d|0?[1-9])"
|
|
]
|
|
, 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(ä)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(ü)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 today 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"
|
|
, Predicate isOkWithThisNext
|
|
]
|
|
, 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
|
|
}
|
|
|
|
ruleAfterLunch :: Rule
|
|
ruleAfterLunch = Rule
|
|
{ name = "after lunch"
|
|
, pattern =
|
|
[ regex "nach dem mittagessen|nachmittags?"
|
|
]
|
|
, prod = \_ -> do
|
|
td2 <- interval TTime.Open (hour False 13) (hour False 17)
|
|
Token Time . partOfDay <$> intersect today 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 $
|
|
or . sequence [isIntegerBetween (- 10000) 0, isIntegerBetween 25 999]
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(token:_) -> do
|
|
y <- getIntValue token
|
|
tt . mkLatent $ year y
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleAfterTimeofday :: Rule
|
|
ruleAfterTimeofday = Rule
|
|
{ name = "after <time-of-day>"
|
|
, pattern =
|
|
[ regex "nach|ab|fr(ü)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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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:_) -> Token Time <$> minutesBefore 30 td
|
|
_ -> 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 "(ü)ber ?n(ä)chste[ns]?"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) ->
|
|
tt $ predNth 1 True td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleHhmm :: Rule
|
|
ruleHhmm = Rule
|
|
{ name = "hh:mm"
|
|
, pattern =
|
|
[ regex "((?:[01]?\\d)|(?:2[0-3]))[:.h]([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
|
|
td2 <- interval TTime.Open (hour False 18) (hour False 0)
|
|
Token Time . partOfDay <$> intersect today 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
|
|
}
|
|
|
|
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 "[ui]m"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td1:_:Token Time td2:_) ->
|
|
tt $ predLastOf td1 td2
|
|
_ -> Nothing
|
|
}
|
|
|
|
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 (Text.toLower ap == "a") $ hourMinute True h m
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleTimeofdayTimeofdayInterval :: Rule
|
|
ruleTimeofdayTimeofdayInterval = Rule
|
|
{ name = "<time-of-day> - <time-of-day> (interval)"
|
|
, pattern =
|
|
[ Predicate $ and . sequence [isNotLatent, isATimeOfDay]
|
|
, 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 $ and . sequence [isNotLatent, isATimeOfDay]
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Time td1:_:Token Time td2:_) ->
|
|
Token Time <$> interval TTime.Closed td1 td2
|
|
_ -> Nothing
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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 $ and . sequence [isNotLatent, isATimeOfDay]
|
|
, 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 (Text.toUpper tz) td
|
|
_ -> Nothing
|
|
}
|
|
|
|
rules :: [Rule]
|
|
rules =
|
|
[ ruleADuration
|
|
, ruleAboutTimeofday
|
|
, ruleAbsorptionOfAfterNamedDay
|
|
, ruleAfterDuration
|
|
, ruleAfterLunch
|
|
, ruleAfterNextTime
|
|
, ruleAfterTimeofday
|
|
, ruleAfterTimeofdayPostfix
|
|
, ruleAfterWork
|
|
, ruleAfternoon
|
|
, ruleAtTimeofday
|
|
, ruleBetweenDatetimeAndDatetimeInterval
|
|
, ruleBetweenTimeofdayAndTimeofdayInterval
|
|
, ruleByTheEndOfTime
|
|
, ruleDatetimeDatetimeInterval
|
|
, ruleDateDateInterval
|
|
, ruleDayofmonthNonOrdinalNamedmonth
|
|
, ruleDayofmonthNonOrdinalOfNamedmonth
|
|
, ruleDayofmonthOrdinal
|
|
, ruleDayofmonthordinalNamedmonth
|
|
, ruleDayofmonthordinalNamedmonthYear
|
|
, ruleDurationAfterTime
|
|
, ruleDurationAgo
|
|
, ruleDurationBeforeTime
|
|
, ruleDurationFromNow
|
|
, ruleDurationHence
|
|
, ruleEvening
|
|
, ruleExactlyTimeofday
|
|
, ruleFromDatetimeDatetimeInterval
|
|
, ruleFromTimeofdayTimeofdayInterval
|
|
, ruleHalfIntegerGermanStyleHourofday
|
|
, ruleHhmm
|
|
, ruleHhmmMilitary
|
|
, ruleHhmmMilitaryAmpm
|
|
, ruleHourofdayIntegerAsRelativeMinutes
|
|
, ruleInDuration
|
|
, ruleInduringThePartofday
|
|
, ruleIntersect
|
|
, ruleIntersectBy
|
|
, ruleIntersectByOfFromS
|
|
, ruleDayOfWeekIntersectDuration
|
|
, ruleLastCycle
|
|
, ruleLastCycleOfTime
|
|
, ruleLastDayofweekOfTime
|
|
, ruleLastNCycle
|
|
, ruleLastTime
|
|
, ruleLunch
|
|
, ruleMidnighteodendOfDay
|
|
, ruleMmdd
|
|
, ruleMmddyyyy
|
|
, ruleMonthDdddInterval
|
|
, ruleMorning
|
|
, ruleNamedmonthDayofmonthNonOrdinal
|
|
, ruleNamedmonthDayofmonthOrdinal
|
|
, ruleNextCycle
|
|
, ruleAfterNextCycle
|
|
, ruleNextNCycle
|
|
, ruleNextTime
|
|
, ruleNight
|
|
, ruleNoon
|
|
, ruleNthTimeAfterTime
|
|
, ruleNthTimeAfterTime2
|
|
, ruleNthTimeOfTime
|
|
, ruleNthTimeOfTime2
|
|
, ruleOnANamedday
|
|
, ruleOnDate
|
|
, ruleOrdinalCycleAfterTime
|
|
, ruleOrdinalCycleOfTime
|
|
, ruleOrdinalQuarter
|
|
, ruleOrdinalQuarterYear
|
|
, rulePartofdayOfTime
|
|
, ruleRelativeMinutesAfterpastIntegerHourofday
|
|
, ruleRelativeMinutesTotillbeforeIntegerHourofday
|
|
, ruleTheCycleAfterTime
|
|
, ruleTheCycleBeforeTime
|
|
, ruleTheDayofmonthNonOrdinal
|
|
, ruleTheDayofmonthOrdinal
|
|
, ruleTheIdesOfNamedmonth
|
|
, ruleTheOrdinalCycleAfterTime
|
|
, ruleTheOrdinalCycleOfTime
|
|
, ruleThisCycle
|
|
, ruleThisPartofday
|
|
, ruleThisTime
|
|
, ruleThisnextDayofweek
|
|
, ruleTimeAfterNext
|
|
, ruleTimeBeforeLast
|
|
, ruleTimePartofday
|
|
, ruleTimeofdayApproximately
|
|
, ruleTimeofdayLatent
|
|
, ruleTimeofdayOclock
|
|
, ruleTimeofdaySharp
|
|
, ruleTimeofdayTimeofdayInterval
|
|
, ruleTimeofdayTimeofdayInterval2
|
|
, ruleTonight
|
|
, ruleUntilTimeofday
|
|
, ruleUntilTimeofdayPostfix
|
|
, ruleWeekend
|
|
, ruleWithinDuration
|
|
, ruleYear
|
|
, ruleYearLatent
|
|
, ruleYearLatent2
|
|
, ruleYyyymmdd
|
|
, ruleQuarterTotillbeforeIntegerHourofday
|
|
, ruleHalfTotillbeforeIntegerHourofday
|
|
, ruleQuarterAfterpastIntegerHourofday
|
|
, ruleHalfAfterpastIntegerHourofday
|
|
, ruleHourofdayQuarter
|
|
, ruleHourofdayHalf
|
|
, ruleTimezone
|
|
]
|
|
++ ruleInstants
|
|
++ ruleDaysOfWeek
|
|
++ ruleMonths
|
|
++ ruleSeasons
|
|
++ ruleHolidays
|
|
++ ruleComputedHolidays
|
|
++ ruleComputedHolidays'
|