mirror of
https://github.com/facebook/duckling.git
synced 2025-01-06 04:53:13 +03:00
a6b7253aa4
Summary: also kill redundant `isGrain` helper from `Time`. Reviewed By: dwhit, haoxuany Differential Revision: D18937649 fbshipit-source-id: ed658cc3bac70e6592dabae536a31a4c2da8a578
1633 lines
42 KiB
Haskell
1633 lines
42 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 OverloadedStrings #-}
|
|
{-# LANGUAGE NoRebindableSyntax #-}
|
|
|
|
module Duckling.Time.HR.Rules
|
|
( rules
|
|
) where
|
|
|
|
import Data.Maybe
|
|
import Data.String
|
|
import Data.Text (Text)
|
|
import Prelude
|
|
import qualified Data.Text as Text
|
|
|
|
import Duckling.Dimensions.Types
|
|
import Duckling.Duration.Helpers (isGrain)
|
|
import Duckling.Numeral.Helpers (parseInt)
|
|
import Duckling.Numeral.Types (NumeralData(..))
|
|
import Duckling.Ordinal.Types (OrdinalData(..))
|
|
import Duckling.Regex.Types
|
|
import Duckling.Time.Helpers
|
|
import Duckling.Time.Types (TimeData(..))
|
|
import Duckling.Types
|
|
import qualified Duckling.Numeral.Types as TNumeral
|
|
import qualified Duckling.Ordinal.Types as TOrdinal
|
|
import qualified Duckling.Time.Types as TTime
|
|
import qualified Duckling.TimeGrain.Types as TG
|
|
|
|
ruleDaysOfWeek :: [Rule]
|
|
ruleDaysOfWeek = mkRuleDaysOfWeek
|
|
[ ( "Monday" , "ponedjelja?ka?|pon\\.?" )
|
|
, ( "Tuesday" , "utora?ka?|uto?\\.?" )
|
|
, ( "Wednesday", "srijed(a|e|u)|sri\\.?" )
|
|
, ( "Thursday" , "(č|c)etvrta?ka?|(č|c)et\\.?" )
|
|
, ( "Friday" , "peta?ka?|pet\\.?" )
|
|
, ( "Saturday" , "subot(a|e|u)|sub?\\.?" )
|
|
, ( "Sunday" , "nedjelj(a|e|u)|ned\\.?" )
|
|
]
|
|
|
|
ruleMonths :: [Rule]
|
|
ruleMonths = mkRuleMonths
|
|
[ ( "January" , "sije(c|č)a?nj(a|u)?|januar(a|u)?|jan\\.?|sij?\\.?|prv(i|a|o(ga?)?)" )
|
|
, ( "February" , "(ve)?lja(c|č)(a|e|i)|februar(a|u)?|feb\\.?|ve(lj)?\\.?|drug(i|a|o(ga?)?)")
|
|
, ( "March" , "o(z|ž)uja?k(a|u)?|mart(a|u)?|mar\\.?|o(z|ž)u?\\.?|tre(c|ć)(i|a|e(ga?)?)" )
|
|
, ( "April" , "trava?nj(a|u)?|april(a|u)?|apr\\.?|tra\\.?|(č|c)etvrt(i|a|o(ga?)?)" )
|
|
, ( "May" , "sviba?nj(a|u)?|maj|svi\\.?|pet(i|a|o(ga?)?)" )
|
|
, ( "June" , "lipa?nj(a|u)?|jun(i|u|a)?|jun\\.?|lip?\\.?|(š|s)est(i|a|o(ga?)?)" )
|
|
, ( "July" , "srpa?nj(a|u)?|jul(i|u|a)?|jul\\.?|srp\\.?|sedm(i|a|o(ga?)?)" )
|
|
, ( "August" , "kolovoz(a|u)?|august(a|u)?|aug\\.?|kol\\.?|osm(i|a|o(ga?)?)" )
|
|
, ( "September", "ruja?n(a|u)?|septemba?r(a|u)?|sept?\\.?|ruj\\.?|devet(i|a|o(ga?)?)" )
|
|
, ( "October" , "listopad(a|u)?|oktobar(a|u)?|okt\\.?|lis\\.?|deset(i|a|o(ga?)?)" )
|
|
, ( "November" , "studen(i|oga?|om)|novemba?r(a|u)?|nov\\.?|stu\\.?|jedanaest(i|a|o(ga?)?)")
|
|
, ( "December" , "prosina?c(a|u)?|decemba?r(a|u)?|dec\\.?|pros?\\.?|dvanaest(i|a|o(ga?)?)" )
|
|
]
|
|
|
|
ruleHolidays :: [Rule]
|
|
ruleHolidays = mkRuleHolidays
|
|
[ ( "new year's eve" , "star(a|u|e) godin(a|e|u)" , monthDay 12 31 )
|
|
, ( "new year's day" , "nov(a|u|e) godin(a|e|u)" , monthDay 1 1 )
|
|
, ( "christmas eve" , "badnjaka?" , monthDay 12 24 )
|
|
, ( "christmas" , "(zi(c|ć)bo|bo(z|ž)i(c|ć))(a|u|ni|na)?", monthDay 12 25 )
|
|
, ( "halloween day" , "no(c|ć) vje(s|š)tica" , monthDay 10 31 )
|
|
, ( "Mother's Day" , "maj(c|č)in dan" , nthDOWOfMonth 2 7 5)
|
|
, ( "Father's Day" , "dan (o(c|č)eva|tata)" , nthDOWOfMonth 3 7 6)
|
|
, ( "valentine's day", "valentinov(og?|a|)" , monthDay 2 14 )
|
|
]
|
|
|
|
ruleSeasons :: [Rule]
|
|
ruleSeasons = mkRuleSeasons
|
|
[ ("summer", "ljet(os?|a)" , monthDay 6 21 , monthDay 9 23 )
|
|
, ("fall" , "jesen(i|as)?" , monthDay 9 23 , monthDay 12 21)
|
|
, ("winter", "zim(a|e|us)?" , monthDay 12 21, monthDay 3 20 )
|
|
, ("spring", "prolje(c|ć)(e|a)", monthDay 3 20 , monthDay 6 21 )
|
|
]
|
|
|
|
ruleHalfIntegerHrStyleHourofday :: Rule
|
|
ruleHalfIntegerHrStyleHourofday = Rule
|
|
{ name = "half <integer> (HR style hour-of-day)"
|
|
, pattern =
|
|
[ regex "pol?a?"
|
|
, Predicate isAnHourOfDay
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> Token Time <$> minutesBefore 30 td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleNumeralTotillbeforeIntegerHourofday :: Rule
|
|
ruleNumeralTotillbeforeIntegerHourofday = Rule
|
|
{ name = "numeral to|till|before <integer> (hour-of-day)"
|
|
, pattern =
|
|
[ Predicate $ isIntegerBetween 1 59
|
|
, regex "do"
|
|
, 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 "(kvarata?|(c|č)etvrt|frtalj)\\s+do"
|
|
, 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 "di pol?a?\\s+do"
|
|
, Predicate isAnHourOfDay
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> Token Time <$> minutesBefore 30 td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleNumeralAfterpastHourofday :: Rule
|
|
ruleNumeralAfterpastHourofday = Rule
|
|
{ name = "numeral after|past (hour-of-day)"
|
|
, pattern =
|
|
[ Predicate $ isIntegerBetween 1 59
|
|
, regex "poslije|nakon"
|
|
, Predicate isAnHourOfDay
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(token:_:Token Time td:_) -> do
|
|
n <- getIntValue token
|
|
Token Time <$> minutesAfter n td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleQuarterAfterpastHourofday :: Rule
|
|
ruleQuarterAfterpastHourofday = Rule
|
|
{ name = "quarter after|past (hour-of-day)"
|
|
, pattern =
|
|
[ regex "(kvarata?|(c|č)etvrt|frtalj)\\s+(poslije|nakon)"
|
|
, Predicate isAnHourOfDay
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> Token Time <$> minutesAfter 15 td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleHalfAfterpastHourofday :: Rule
|
|
ruleHalfAfterpastHourofday = Rule
|
|
{ name = "half after|past (hour-of-day)"
|
|
, pattern =
|
|
[ regex "(i pol?a?)\\s+(poslije|nakon)"
|
|
, Predicate isAnHourOfDay
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> Token Time <$> minutesAfter 30 td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleHourofdayNumeral :: Rule
|
|
ruleHourofdayNumeral = 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"
|
|
, pattern =
|
|
[ Predicate isAnHourOfDay
|
|
, regex "kvarata?|(c|č)etvrt|frtalj"
|
|
]
|
|
, 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"
|
|
, pattern =
|
|
[ Predicate isAnHourOfDay
|
|
, regex "i pol?a?"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:_) ->
|
|
tt $ hourMinute is12H hours 30
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleZaNumeralHourofday :: Rule
|
|
ruleZaNumeralHourofday = Rule
|
|
{ name = "za <integer> (hour-of-day)"
|
|
, pattern =
|
|
[ regex "za"
|
|
, Predicate $ isIntegerBetween 1 59
|
|
, 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
|
|
}
|
|
|
|
ruleZaQuarterHourofday :: Rule
|
|
ruleZaQuarterHourofday = Rule
|
|
{ name = "za quarter (hour-of-day)"
|
|
, pattern =
|
|
[ regex "za\\s+(kvarata?|(c|č)etvrt|frtalj)"
|
|
, Predicate isAnHourOfDay
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:
|
|
Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:
|
|
_) -> tt $ hourMinute is12H hours 15
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleZaHalfHourofday :: Rule
|
|
ruleZaHalfHourofday = Rule
|
|
{ name = "za half (hour-of-day)"
|
|
, pattern =
|
|
[ regex "za\\s+(i pol?a?)"
|
|
, Predicate isAnHourOfDay
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:
|
|
Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:
|
|
_) -> tt $ hourMinute is12H hours 30
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleSinceTimeofday :: Rule
|
|
ruleSinceTimeofday = Rule
|
|
{ name = "since <time-of-day>"
|
|
, pattern =
|
|
[ regex "od"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> tt $ withDirection TTime.After td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleLastTime :: Rule
|
|
ruleLastTime = Rule
|
|
{ name = "last <time>"
|
|
, pattern =
|
|
[ regex "(prethodn(i|u|a|e|o(ga?)?)|pro(s|š)l(ih?|u|a|e|o(ga?)?))"
|
|
, 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 "\\-"
|
|
, Predicate isNotLatent
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Time td1:_:Token Time td2:_) ->
|
|
Token Time <$> interval TTime.Closed td1 td2
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleCycleAfterTime :: Rule
|
|
ruleCycleAfterTime = Rule
|
|
{ name = "<cycle> after <time>"
|
|
, pattern =
|
|
[ dimension TimeGrain
|
|
, regex "nakon"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token TimeGrain grain:_:Token Time td:_) ->
|
|
tt $ cycleNthAfter False grain 1 td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleInDuration :: Rule
|
|
ruleInDuration = Rule
|
|
{ name = "in <duration>"
|
|
, pattern =
|
|
[ regex "za"
|
|
, dimension Duration
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Duration dd:_) -> tt $ inDuration dd
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleNow :: Rule
|
|
ruleNow = Rule
|
|
{ name = "now"
|
|
, pattern =
|
|
[ regex "((upravo|ov(aj?|og?|e|i))? ?sada?|trenutak|upravo|trenutno)|(ov(aj|og) trena?)"
|
|
]
|
|
, prod = \_ -> tt now
|
|
}
|
|
|
|
ruleLastCycleOfTime :: Rule
|
|
ruleLastCycleOfTime = Rule
|
|
{ name = "last <cycle> of <time>"
|
|
, pattern =
|
|
[ regex "zadnj(ih?|a|e(ga?)?)"
|
|
, dimension TimeGrain
|
|
, regex "u"
|
|
, 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 "od|izme(dj|đ)u"
|
|
, dimension Time
|
|
, regex "\\-"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td1:_:Token Time td2:_) ->
|
|
Token Time <$> interval TTime.Closed td1 td2
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleMonthDdddInterval :: Rule
|
|
ruleMonthDdddInterval = Rule
|
|
{ name = "<month> dd-dd (interval)"
|
|
, pattern =
|
|
[ Predicate isAMonth
|
|
, regex "(3[01]|[12]\\d|0?[1-9])"
|
|
, regex "\\-|do"
|
|
, regex "(3[01]|[12]\\d|0?[1-9])"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Time td:
|
|
Token RegexMatch (GroupMatch (m1:_)):
|
|
_:
|
|
Token RegexMatch (GroupMatch (m2:_)):
|
|
_) -> do
|
|
d1 <- parseInt m1
|
|
d2 <- parseInt m2
|
|
from <- intersect (dayOfMonth d1) td
|
|
to <- intersect (dayOfMonth d2) td
|
|
Token Time <$> interval TTime.Closed from to
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleYearLatent2 :: Rule
|
|
ruleYearLatent2 = Rule
|
|
{ name = "year (latent)"
|
|
, pattern =
|
|
[ Predicate $ isIntegerBetween 2101 10000
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(token:_) -> do
|
|
n <- getIntValue token
|
|
tt . mkLatent $ year n
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleTimeAfterNext :: Rule
|
|
ruleTimeAfterNext = Rule
|
|
{ name = "<time> after next"
|
|
, pattern =
|
|
[ dimension Time
|
|
, regex "nakon sljede(ć|c)(i|e|a)(ga?)?"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Time td:_) -> tt $ predNth 1 True td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleNoon :: Rule
|
|
ruleNoon = Rule
|
|
{ name = "noon"
|
|
, pattern =
|
|
[ regex "(u )?podne(va)?"
|
|
]
|
|
, prod = \_ -> tt $ hour False 12
|
|
}
|
|
|
|
ruleEarlyMorning :: Rule
|
|
ruleEarlyMorning = Rule
|
|
{ name = "early morning"
|
|
, pattern =
|
|
[ regex "(rano( (u )?u?jutros?)?)|(u ran(im|e) jutarnj(im|e) sat(ima|e))"
|
|
]
|
|
, prod = \_ -> Token Time . partOfDay . mkLatent <$>
|
|
interval TTime.Open (hour False 3) (hour False 9)
|
|
}
|
|
|
|
ruleToday :: Rule
|
|
ruleToday = Rule
|
|
{ name = "today"
|
|
, pattern =
|
|
[ regex "danas?|(dana(s|š)nj(i|eg) dana?) "
|
|
]
|
|
, prod = \_ -> tt today
|
|
}
|
|
|
|
ruleThisnextDayofweek :: Rule
|
|
ruleThisnextDayofweek = Rule
|
|
{ name = "this|next <day-of-week>"
|
|
, pattern =
|
|
[ regex "ov(aj?|og?|e)|sljede(c|ć)(i|u|a|e(ga?)?)"
|
|
, 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 "od|izme(dj|đ)u"
|
|
, Predicate isATimeOfDay
|
|
, regex "do|i"
|
|
, 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 "sljede(c|ć)(i|a|u|e(ga?)?)"
|
|
, dimension TimeGrain
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token TimeGrain grain:_) -> tt $ cycleNth grain 1
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleTimeofdayApproximately :: Rule
|
|
ruleTimeofdayApproximately = Rule
|
|
{ name = "<time-of-day> approximately"
|
|
, pattern =
|
|
[ Predicate isATimeOfDay
|
|
, regex "(-?ak)"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Time td:_) -> tt $ notLatent td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleForDuration :: Rule
|
|
ruleForDuration = Rule
|
|
{ name = "for <duration>"
|
|
, pattern =
|
|
[ regex "za( jo(s|š))?|u"
|
|
, dimension Duration
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Duration dd:_) -> tt $ inDuration dd
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleLastDayofweekTime :: Rule
|
|
ruleLastDayofweekTime = Rule
|
|
{ name = "last <day-of-week> <time>"
|
|
, pattern =
|
|
[ regex "zadnj(ih?|a|e(ga?)?)"
|
|
, Predicate isADayOfWeek
|
|
, regex "u"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td1:_:Token Time td2:_) ->
|
|
tt $ predLastOf td1 td2
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleDurationFromNow :: Rule
|
|
ruleDurationFromNow = Rule
|
|
{ name = "<duration> from now"
|
|
, pattern =
|
|
[ dimension Duration
|
|
, regex "od (sada?|ovog trenutka|dana(s|š)nj(i|eg) dana?)"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Duration dd:_) -> tt $ inDuration dd
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleLunch :: Rule
|
|
ruleLunch = Rule
|
|
{ name = "lunch"
|
|
, pattern =
|
|
[ regex "(((za )|(u vrijeme )) )?ru(c|č)a?k(a|om)?"
|
|
]
|
|
, prod = \_ -> Token Time . partOfDay . mkLatent <$>
|
|
interval TTime.Open (hour False 12) (hour False 14)
|
|
}
|
|
|
|
ruleLastCycle :: Rule
|
|
ruleLastCycle = Rule
|
|
{ name = "last <cycle>"
|
|
, pattern =
|
|
[ regex "prethodn(i|a|e|u)|pro(s|š)l(i|a|e|u|o(ga?)?)"
|
|
, dimension TimeGrain
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token TimeGrain grain:_) -> tt . cycleNth grain $ - 1
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleDdmm :: Rule
|
|
ruleDdmm = Rule
|
|
{ name = "dd.mm"
|
|
, pattern =
|
|
[ regex "(3[01]|[12]\\d|0?[1-9])\\/(0?[1-9]|1[0-2])"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token RegexMatch (GroupMatch (dd:mm:_)):_) -> do
|
|
d <- parseInt dd
|
|
m <- parseInt mm
|
|
tt $ monthDay m d
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleAfternoon :: Rule
|
|
ruleAfternoon = Rule
|
|
{ name = "afternoon"
|
|
, pattern =
|
|
[ regex "po(slije)?podne"
|
|
]
|
|
, prod = \_ -> Token Time . partOfDay . mkLatent <$>
|
|
interval TTime.Open (hour False 12) (hour False 20)
|
|
}
|
|
|
|
ruleTimeBeforeLast :: Rule
|
|
ruleTimeBeforeLast = Rule
|
|
{ name = "<time> before last"
|
|
, pattern =
|
|
[ dimension Time
|
|
, regex "prije (prethodn(e|o(ga?)?)|pro(s|š)l(ih?|u|a|e|o(ga?)?))"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Time td:_) ->
|
|
tt $ predNth (-2) False td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleLateNight :: Rule
|
|
ruleLateNight = Rule
|
|
{ name = "late night"
|
|
, pattern =
|
|
[ regex "(((u|po)\\s)?no(c|ć)(i|as|u)?|u?jutros?)"
|
|
]
|
|
, prod = \_ -> Token Time . partOfDay . mkLatent <$>
|
|
interval TTime.Open (hour False 0) (hour False 4)
|
|
}
|
|
|
|
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 "(u|tokom)"
|
|
, Predicate isAPartOfDay
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> tt $ notLatent td
|
|
_ -> 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 ","
|
|
, 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 "poslije|nakon|iza"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Ordinal od:Token Time td1:_:Token Time td2:_) ->
|
|
tt $ predNthAfter (TOrdinal.value od - 1) td1 td2
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleAfterDuration :: Rule
|
|
ruleAfterDuration = Rule
|
|
{ name = "after <duration>"
|
|
, pattern =
|
|
[ regex "(nakon|poslije)( jo(s|š))?"
|
|
, dimension Duration
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Duration dd:_) -> tt . withDirection TTime.After $ 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 True n
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleDayofmonthOrdinalOfNamedmonth :: Rule
|
|
ruleDayofmonthOrdinalOfNamedmonth = Rule
|
|
{ name = "<day-of-month> (ordinal) of <named-month>"
|
|
, pattern =
|
|
[ Predicate isDOMOrdinal
|
|
, regex "of|in"
|
|
, Predicate isAMonth
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(token:_:Token Time td:_) -> Token Time <$> intersectDOM td token
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleFromTimeofdayTimeofdayInterval :: Rule
|
|
ruleFromTimeofdayTimeofdayInterval = Rule
|
|
{ name = "from <time-of-day> - <time-of-day> (interval)"
|
|
, pattern =
|
|
[ regex "od"
|
|
, Predicate isATimeOfDay
|
|
, regex "\\-"
|
|
, 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 "to(c|č)no( u)?"
|
|
, Predicate isATimeOfDay
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> tt $ notLatent td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleUNamedday :: Rule
|
|
ruleUNamedday = Rule
|
|
{ name = "u <named-day>"
|
|
, pattern =
|
|
[ regex "u"
|
|
, Predicate isADayOfWeek
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:x:_) -> Just x
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleBetweenDatetimeAndDatetimeInterval :: Rule
|
|
ruleBetweenDatetimeAndDatetimeInterval = Rule
|
|
{ name = "between <datetime> and <datetime> (interval)"
|
|
, pattern =
|
|
[ regex "od|izme(dj|đ)u"
|
|
, dimension Time
|
|
, regex "do|i"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td1:_:Token Time td2:_) ->
|
|
Token Time <$> interval TTime.Closed td1 td2
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleByTheEndOfTime :: Rule
|
|
ruleByTheEndOfTime = Rule
|
|
{ name = "by the end of <time>"
|
|
, pattern =
|
|
[ regex "(do )(kraja|isteka)? "
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> Token Time <$> interval TTime.Closed now td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleAfterWork :: Rule
|
|
ruleAfterWork = Rule
|
|
{ name = "after work"
|
|
, pattern =
|
|
[ regex "poslije (posla|kraja radnog vremena)"
|
|
]
|
|
, prod = \_ -> do
|
|
td <- interval TTime.Open (hour False 17) (hour False 21)
|
|
Token Time . partOfDay . notLatent <$> intersect today td
|
|
}
|
|
|
|
ruleLastDayofweekTime2 :: Rule
|
|
ruleLastDayofweekTime2 = Rule
|
|
{ name = "last <day-of-week> <time>"
|
|
, pattern =
|
|
[ regex "zadnj(ih?|a|e(ga?)?)"
|
|
, Predicate isADayOfWeek
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td1:Token Time td2:_) ->
|
|
tt $ predLastOf td1 td2
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleLastNCycle :: Rule
|
|
ruleLastNCycle = Rule
|
|
{ name = "last n <cycle>"
|
|
, pattern =
|
|
[ regex "prethodn(ih?|a|e)|pro(s|š)l(a|e|ih?)"
|
|
, 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
|
|
}
|
|
|
|
ruleWithinDuration :: Rule
|
|
ruleWithinDuration = Rule
|
|
{ name = "within <duration>"
|
|
, pattern =
|
|
[ regex "(u|za )vrijeme"
|
|
, 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 "(u )?pono(c|ć)i?|(the )?(EOD|((do )? kraja? dana))"
|
|
]
|
|
, 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 "(oko|cca|otprilike)"
|
|
, 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 "((nekad|najkasnije) )?(prije|do)"
|
|
, Predicate isATimeOfDay
|
|
]
|
|
, 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 "u|@"
|
|
, 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 "u"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Ordinal od:Token Time td1:_:Token Time td2:_) -> Token Time .
|
|
predNth (TOrdinal.value od - 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 td:Token Time pod:_) -> Token Time <$> intersect pod td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleWeekend :: Rule
|
|
ruleWeekend = Rule
|
|
{ name = "week-end"
|
|
, pattern =
|
|
[ regex "(za )?vikenda?"
|
|
]
|
|
, prod = \_ -> tt $ mkOkForThisNext weekend
|
|
}
|
|
|
|
rulePrijeDuration :: Rule
|
|
rulePrijeDuration = Rule
|
|
{ name = "prije <duration>"
|
|
, pattern =
|
|
[ regex "prije"
|
|
, dimension Duration
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Duration dd:_) -> tt $ durationAgo dd
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleAboutDuration :: Rule
|
|
ruleAboutDuration = Rule
|
|
{ name = "about <duration>"
|
|
, pattern =
|
|
[ regex "oko"
|
|
, dimension Duration
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Duration dd:_) -> tt $ inDuration dd
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleEomendOfMonth :: Rule
|
|
ruleEomendOfMonth = Rule
|
|
{ name = "EOM|End of month"
|
|
, pattern =
|
|
[ regex "(the )?(EOM|(do )? kraja mjeseca)"
|
|
]
|
|
, prod = \_ -> tt $ cycleNth TG.Month 1
|
|
}
|
|
|
|
ruleNameddayDayofmonthOrdinal :: Rule
|
|
ruleNameddayDayofmonthOrdinal = Rule
|
|
{ name = "<named-day> <day-of-month> (ordinal)"
|
|
, pattern =
|
|
[ Predicate isADayOfWeek
|
|
, Predicate isDOMOrdinal
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Time td:token:_) -> Token Time <$> intersectDOM td token
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleNextTime :: Rule
|
|
ruleNextTime = Rule
|
|
{ name = "next <time>"
|
|
, pattern =
|
|
[ regex "sljede(c|ć)(i|u|a|e(ga?)?)"
|
|
, 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:_:Token Time td:_) -> do
|
|
n <- getIntValue token
|
|
tt $ cycleNthAfter False TG.Quarter (n - 1) td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleYyyymmdd :: Rule
|
|
ruleYyyymmdd = Rule
|
|
{ name = "yyyy-mm-dd"
|
|
, pattern =
|
|
[ regex "(\\d{2,4})-(0?[1-9]|1[0-2])-(3[01]|[12]\\d|0?[1-9])"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token RegexMatch (GroupMatch (yy:mm:dd:_)):_) -> do
|
|
y <- parseInt yy
|
|
m <- parseInt mm
|
|
d <- parseInt dd
|
|
tt $ yearMonthDay y m d
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleNextNCycle :: Rule
|
|
ruleNextNCycle = Rule
|
|
{ name = "next n <cycle>"
|
|
, pattern =
|
|
[ regex "(u )?(sljede(c|ć)(ih?|a|eg?))"
|
|
, 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
|
|
}
|
|
|
|
ruleMorning :: Rule
|
|
ruleMorning = Rule
|
|
{ name = "morning"
|
|
, pattern =
|
|
[ regex "(u )?u?jutros?"
|
|
]
|
|
, prod = \_ -> Token Time . partOfDay . mkLatent <$>
|
|
interval TTime.Open (hour False 4) (hour False 12)
|
|
}
|
|
|
|
ruleThisPartofday :: Rule
|
|
ruleThisPartofday = Rule
|
|
{ name = "this <part-of-day>"
|
|
, pattern =
|
|
[ regex "ov(aj?|og?|i|e)"
|
|
, Predicate isAPartOfDay
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> Token Time . partOfDay . notLatent <$>
|
|
intersect today td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleThisCycle :: Rule
|
|
ruleThisCycle = Rule
|
|
{ name = "this <cycle>"
|
|
, pattern =
|
|
[ regex "ov(aj?|og?|e|i)"
|
|
, dimension TimeGrain
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token TimeGrain grain:_) -> tt $ cycleNth grain 0
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleUNamedmonth :: Rule
|
|
ruleUNamedmonth = Rule
|
|
{ name = "u <named-month>"
|
|
, pattern =
|
|
[ regex "u"
|
|
, Predicate isAMonth
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:x:_) -> Just x
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleThisTime :: Rule
|
|
ruleThisTime = Rule
|
|
{ name = "this <time>"
|
|
, pattern =
|
|
[ regex "ov(aj?|og?|e)(sad)?"
|
|
, Predicate isOkWithThisNext
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> tt $ predNth 0 False td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleDayofmonthNonOrdinalOfNamedmonth :: Rule
|
|
ruleDayofmonthNonOrdinalOfNamedmonth = Rule
|
|
{ name = "<day-of-month> (non ordinal) of <named-month>"
|
|
, pattern =
|
|
[ Predicate isDOMInteger
|
|
, regex "of|in"
|
|
, Predicate isAMonth
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(token:_:Token Time td:_) -> Token Time <$> intersectDOM td token
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleHhmmMilitaryPrefixedWithMToAvoidAmbiguityWithYears :: Rule
|
|
ruleHhmmMilitaryPrefixedWithMToAvoidAmbiguityWithYears = Rule
|
|
{ name = "hhmm (military, prefixed with m to avoid ambiguity with years)"
|
|
, pattern =
|
|
[ regex "m((?:[01]?\\d)|(?:2[0-3]))([0-5]\\d)"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do
|
|
h <- parseInt hh
|
|
m <- parseInt mm
|
|
tt . timeOfDayAMPM False $ hourMinute False h m
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleDayBeforeYesterday :: Rule
|
|
ruleDayBeforeYesterday = Rule
|
|
{ name = "day before yesterday"
|
|
, pattern =
|
|
[ regex "(prekju(c|č)er)"
|
|
]
|
|
, prod = \_ -> tt . cycleNth TG.Day $ - 2
|
|
}
|
|
|
|
ruleAfterLunch :: Rule
|
|
ruleAfterLunch = Rule
|
|
{ name = "after lunch"
|
|
, pattern =
|
|
[ regex "poslije ru(c|č)ka"
|
|
]
|
|
, prod = \_ -> do
|
|
td <- interval TTime.Open (hour False 13) (hour False 17)
|
|
Token Time . partOfDay . notLatent <$> intersect today td
|
|
}
|
|
|
|
ruleYearLatent :: Rule
|
|
ruleYearLatent = Rule
|
|
{ name = "year (latent)"
|
|
, pattern =
|
|
[ Predicate $
|
|
or . sequence [isIntegerBetween (- 10000) 0, isIntegerBetween 25 999]
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(token:_) -> do
|
|
n <- getIntValue token
|
|
tt . mkLatent $ year n
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleYesterday :: Rule
|
|
ruleYesterday = Rule
|
|
{ name = "yesterday"
|
|
, pattern =
|
|
[ regex "(ju(c|č)er)"
|
|
]
|
|
, prod = \_ -> tt . cycleNth TG.Day $ - 1
|
|
}
|
|
|
|
ruleAfterTimeofday :: Rule
|
|
ruleAfterTimeofday = Rule
|
|
{ name = "after <time-of-day>"
|
|
, pattern =
|
|
[ regex "(nekad |najranije )?(prije|od)"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> tt $ withDirection TTime.After td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleDayofmonthOrdinal :: Rule
|
|
ruleDayofmonthOrdinal = Rule
|
|
{ name = "<day-of-month>. (ordinal)"
|
|
, pattern =
|
|
[ Predicate isDOMOrdinal
|
|
, regex "\\.|i|og"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(token:_) -> do
|
|
v <- getIntValue token
|
|
tt $ dayOfMonth v
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleOrdinalCycleAfterTime :: Rule
|
|
ruleOrdinalCycleAfterTime = Rule
|
|
{ name = "<ordinal> <cycle> after <time>"
|
|
, pattern =
|
|
[ dimension Ordinal
|
|
, dimension TimeGrain
|
|
, regex "nakon"
|
|
, 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 "od|u"
|
|
, 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 "nakon sljede(ć|c)(i|e|a)(ga?)?"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> tt $ predNth 1 True td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleDayAfterTomorrow :: Rule
|
|
ruleDayAfterTomorrow = Rule
|
|
{ name = "day after tomorrow"
|
|
, pattern =
|
|
[ regex "(preko?sutra)"
|
|
]
|
|
, prod = \_ -> tt $ cycleNth TG.Day 2
|
|
}
|
|
|
|
ruleHhmm :: Rule
|
|
ruleHhmm = Rule
|
|
{ name = "hh:mm"
|
|
, pattern =
|
|
[ regex "((?:[01]?\\d)|(?:2[0-3]))[(:.\\si]+([0-5]\\d)"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token RegexMatch (GroupMatch (hh:mm:_)):_) -> do
|
|
h <- parseInt hh
|
|
m <- parseInt mm
|
|
tt $ hourMinute True h m
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleTonight :: Rule
|
|
ruleTonight = Rule
|
|
{ name = "tonight"
|
|
, pattern =
|
|
[ regex "(na)?ve(c|č)er(as)?"
|
|
]
|
|
, prod = \_ -> do
|
|
evening <- interval TTime.Open (hour False 18) (hour False 0)
|
|
Token Time . partOfDay . notLatent <$> intersect today evening
|
|
}
|
|
|
|
ruleBeforeLasttime :: Rule
|
|
ruleBeforeLasttime = Rule
|
|
{ name = "before last<time>"
|
|
, pattern =
|
|
[ regex "prije (prethodn(i|u|a|e|o(ga?)?)|pro(s|š)l(ih?|a|e|o(ga?)?))"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> tt $ predNth (-2) False td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleTimezone :: Rule
|
|
ruleTimezone = Rule
|
|
{ name = "<time> timezone"
|
|
, pattern =
|
|
[ Predicate $ and . sequence [isNotLatent, isGrainFinerThan TG.Day]
|
|
, 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
|
|
}
|
|
|
|
ruleYear :: Rule
|
|
ruleYear = Rule
|
|
{ name = "year"
|
|
, pattern =
|
|
[ Predicate $ isIntegerBetween 1000 2100
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(token:_) -> do
|
|
n <- getIntValue token
|
|
tt $ year n
|
|
_ -> 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
|
|
}
|
|
|
|
ruleAbsorptionOfAfterNamedDay :: Rule
|
|
ruleAbsorptionOfAfterNamedDay = Rule
|
|
{ name = "absorption of , after named day"
|
|
, pattern =
|
|
[ Predicate isADayOfWeek
|
|
, regex ","
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(x:_) -> Just x
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleByTime :: Rule
|
|
ruleByTime = Rule
|
|
{ name = "by <time>"
|
|
, pattern =
|
|
[ regex "do"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(_:Token Time td:_) -> Token Time <$> interval TTime.Open now td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleCycleBeforeTime :: Rule
|
|
ruleCycleBeforeTime = Rule
|
|
{ name = "<cycle> before <time>"
|
|
, pattern =
|
|
[ dimension TimeGrain
|
|
, regex "prije"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token TimeGrain grain:_:Token Time td:_) ->
|
|
tt $ cycleNthAfter False grain (-1) td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleDdmmyyyy :: Rule
|
|
ruleDdmmyyyy = Rule
|
|
{ name = "dd/mm/yyyy"
|
|
, pattern =
|
|
[ regex "(3[01]|[12]\\d|0?[1-9])[\\/](0?[1-9]|1[0-2])[\\/](\\d{2,4})"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token RegexMatch (GroupMatch (dd:mm:yy:_)):_) -> do
|
|
y <- parseInt yy
|
|
m <- parseInt mm
|
|
d <- parseInt dd
|
|
tt $ yearMonthDay y m d
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleTimeofdayTimeofdayInterval :: Rule
|
|
ruleTimeofdayTimeofdayInterval = Rule
|
|
{ name = "<time-of-day> - <time-of-day> (interval)"
|
|
, pattern =
|
|
[ Predicate $ and . sequence [isNotLatent, isATimeOfDay]
|
|
, regex "\\-|:"
|
|
, Predicate 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 "nakon|poslije|od"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Duration dd:_:Token Time td:_) ->
|
|
tt $ durationAfter dd td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleEveningnight :: Rule
|
|
ruleEveningnight = Rule
|
|
{ name = "evening|night"
|
|
, pattern =
|
|
[ regex "(na)?ve(c|č)er(i|as)?"
|
|
]
|
|
, prod = \_ -> Token Time . mkOkForThisNext . partOfDay . mkLatent <$>
|
|
interval TTime.Open (hour False 18) (hour False 0)
|
|
}
|
|
|
|
ruleOrdinalQuarter :: Rule
|
|
ruleOrdinalQuarter = Rule
|
|
{ name = "<ordinal> quarter"
|
|
, pattern =
|
|
[ dimension Ordinal
|
|
, Predicate $ isGrain TG.Quarter
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(token:_) -> do
|
|
n <- getIntValue token
|
|
tt . cycleNthAfter True TG.Quarter (n - 1) $
|
|
cycleNth TG.Year 0
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleDayBeforeDayBeforeYesterday :: Rule
|
|
ruleDayBeforeDayBeforeYesterday = Rule
|
|
{ name = "day before day before yesterday"
|
|
, pattern =
|
|
[ regex "(prek\\s?prekju(c|č)er)"
|
|
]
|
|
, prod = \_ -> tt . cycleNth TG.Day $ - 3
|
|
}
|
|
|
|
ruleDurationBeforeTime :: Rule
|
|
ruleDurationBeforeTime = Rule
|
|
{ name = "<duration> before <time>"
|
|
, pattern =
|
|
[ dimension Duration
|
|
, regex "prije"
|
|
, dimension Time
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Duration dd:_:Token Time td:_) ->
|
|
tt $ durationBefore dd td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleEoyendOfYear :: Rule
|
|
ruleEoyendOfYear = Rule
|
|
{ name = "EOY|End of year"
|
|
, pattern =
|
|
[ regex "(the )?(EOY|(do )? kraja? godine)"
|
|
]
|
|
, prod = \_ -> tt $ cycleNth TG.Year 1
|
|
}
|
|
|
|
ruleTomorrow :: Rule
|
|
ruleTomorrow = Rule
|
|
{ name = "tomorrow"
|
|
, pattern =
|
|
[ regex "(sutra(dan)?)"
|
|
]
|
|
, prod = \_ -> tt $ cycleNth TG.Day 1
|
|
}
|
|
|
|
ruleTimeofdayOclock :: Rule
|
|
ruleTimeofdayOclock = Rule
|
|
{ name = "<time-of-day> o'clock"
|
|
, pattern =
|
|
[ Predicate isATimeOfDay
|
|
, regex "sat(i|a)?"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token Time td:_) -> tt $ notLatent td
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleYear2 :: Rule
|
|
ruleYear2 = Rule
|
|
{ name = "year"
|
|
, pattern =
|
|
[ Predicate $ isOrdinalBetween 1000 2100
|
|
, regex "\\.|e"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(token:_) -> do
|
|
v <- getIntValue token
|
|
tt $ year v
|
|
_ -> 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
|
|
intVal <- parseInt match
|
|
dom <- intersectDOM td token
|
|
Token Time <$> intersect dom (year intVal)
|
|
_ -> Nothing
|
|
}
|
|
|
|
ruleHhmmss :: Rule
|
|
ruleHhmmss = Rule
|
|
{ name = "hh:mm:ss"
|
|
, pattern =
|
|
[ regex "((?:[01]?\\d)|(?:2[0-3]))[:.]([0-5]\\d)[:.]([0-5]\\d)"
|
|
]
|
|
, prod = \tokens -> case tokens of
|
|
(Token RegexMatch (GroupMatch (hh:mm:ss:_)):_) -> do
|
|
h <- parseInt hh
|
|
m <- parseInt mm
|
|
s <- parseInt ss
|
|
tt $ hourMinuteSecond True h m s
|
|
_ -> Nothing
|
|
}
|
|
|
|
rules :: [Rule]
|
|
rules =
|
|
[ ruleAboutDuration
|
|
, ruleAboutTimeofday
|
|
, ruleAbsorptionOfAfterNamedDay
|
|
, ruleAfterDuration
|
|
, ruleAfterLunch
|
|
, ruleAfterNextTime
|
|
, ruleAfterTimeofday
|
|
, ruleAfterWork
|
|
, ruleAfternoon
|
|
, ruleAtTimeofday
|
|
, ruleBeforeLasttime
|
|
, ruleBetweenDatetimeAndDatetimeInterval
|
|
, ruleBetweenTimeofdayAndTimeofdayInterval
|
|
, ruleByTheEndOfTime
|
|
, ruleByTime
|
|
, ruleCycleAfterTime
|
|
, ruleCycleBeforeTime
|
|
, ruleDatetimeDatetimeInterval
|
|
, ruleDayAfterTomorrow
|
|
, ruleDayBeforeDayBeforeYesterday
|
|
, ruleDayBeforeYesterday
|
|
, ruleDayofmonthNonOrdinalNamedmonth
|
|
, ruleDayofmonthNonOrdinalOfNamedmonth
|
|
, ruleDayofmonthOrdinal
|
|
, ruleDayofmonthOrdinalOfNamedmonth
|
|
, ruleDayofmonthordinalNamedmonth
|
|
, ruleDayofmonthordinalNamedmonthYear
|
|
, ruleDdmm
|
|
, ruleDdmmyyyy
|
|
, ruleDurationAfterTime
|
|
, ruleDurationBeforeTime
|
|
, ruleDurationFromNow
|
|
, ruleEarlyMorning
|
|
, ruleEomendOfMonth
|
|
, ruleEoyendOfYear
|
|
, ruleEveningnight
|
|
, ruleExactlyTimeofday
|
|
, ruleForDuration
|
|
, ruleFromDatetimeDatetimeInterval
|
|
, ruleFromTimeofdayTimeofdayInterval
|
|
, ruleHalfIntegerHrStyleHourofday
|
|
, ruleHhmm
|
|
, ruleHhmmMilitaryPrefixedWithMToAvoidAmbiguityWithYears
|
|
, ruleHhmmss
|
|
, ruleInDuration
|
|
, ruleInduringThePartofday
|
|
, ruleIntersect
|
|
, ruleIntersectBy
|
|
, ruleLastCycle
|
|
, ruleLastCycleOfTime
|
|
, ruleLastDayofweekTime
|
|
, ruleLastDayofweekTime2
|
|
, ruleLastNCycle
|
|
, ruleLastTime
|
|
, ruleLateNight
|
|
, ruleLunch
|
|
, ruleMidnighteodendOfDay
|
|
, ruleMonthDdddInterval
|
|
, ruleMorning
|
|
, ruleNameddayDayofmonthOrdinal
|
|
, ruleNamedmonthDayofmonthNonOrdinal
|
|
, ruleNamedmonthDayofmonthOrdinal
|
|
, ruleNextCycle
|
|
, ruleNextNCycle
|
|
, ruleNextTime
|
|
, ruleNoon
|
|
, ruleNow
|
|
, ruleNthTimeAfterTime
|
|
, ruleNthTimeOfTime
|
|
, ruleOrdinalCycleAfterTime
|
|
, ruleOrdinalCycleOfTime
|
|
, ruleOrdinalQuarter
|
|
, ruleOrdinalQuarterYear
|
|
, rulePrijeDuration
|
|
, ruleNumeralAfterpastHourofday
|
|
, ruleQuarterAfterpastHourofday
|
|
, ruleHalfAfterpastHourofday
|
|
, ruleNumeralTotillbeforeIntegerHourofday
|
|
, ruleQuarterTotillbeforeIntegerHourofday
|
|
, ruleHalfTotillbeforeIntegerHourofday
|
|
, ruleHourofdayNumeral
|
|
, ruleHourofdayQuarter
|
|
, ruleHourofdayHalf
|
|
, ruleSinceTimeofday
|
|
, ruleThisCycle
|
|
, ruleThisPartofday
|
|
, ruleThisTime
|
|
, ruleThisnextDayofweek
|
|
, ruleTimeAfterNext
|
|
, ruleTimeBeforeLast
|
|
, ruleTimePartofday
|
|
, ruleTimezone
|
|
, ruleTimeofdayApproximately
|
|
, ruleTimeofdayLatent
|
|
, ruleTimeofdayOclock
|
|
, ruleTimeofdayTimeofdayInterval
|
|
, ruleToday
|
|
, ruleTomorrow
|
|
, ruleTonight
|
|
, ruleUNamedday
|
|
, ruleUNamedmonth
|
|
, ruleUntilTimeofday
|
|
, ruleWeekend
|
|
, ruleWithinDuration
|
|
, ruleYear
|
|
, ruleYear2
|
|
, ruleYearLatent
|
|
, ruleYearLatent2
|
|
, ruleYesterday
|
|
, ruleYyyymmdd
|
|
, ruleZaNumeralHourofday
|
|
, ruleZaQuarterHourofday
|
|
, ruleZaHalfHourofday
|
|
]
|
|
++ ruleDaysOfWeek
|
|
++ ruleMonths
|
|
++ ruleHolidays
|
|
++ ruleSeasons
|