Duckling/Time/TR/Rules.hs (1,033 lines of code) (raw):
-- 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.TR.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.Types (TimeData(..), TimeIntervalType (Closed, Open))
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, "ş?imdi|şu(\\s)?an" )
, ( "today" , TG.Day , 0, "bugün" )
, ( "tomorrow" , TG.Day , 1, "yarın" )
, ( "yesterday" , TG.Day , -1, "dün" )
, ( "after tomorrow" , TG.Day , 2, "(yarından\\ssonraki)\\s?(gün)?" )
, ( "before yesterday", TG.Day , -2, "(dün\\sdeğil\\sevvelsi|dünden\\sönceki|öbürsü|öbürki)\\s(gün)?")
, ( "EOM|End of day", TG.Day , 1, "gün\\s(sonu(na|ndan?)?|bitimi(ne|nden?)?)?" )
, ( "EOM|End of month", TG.Month , 1, "ay\\s(sonu(na|ndan?)?|bitimi(ne|nden?)?)?" )
, ( "EOY|End of year" , TG.Year , 1, "yıl\\s(sonu(na|ndan?)?|bitimi(ne|nden?)?)?" )
]
ruleDaysOfWeek :: [Rule]
ruleDaysOfWeek = mkRuleDaysOfWeek
[ ( "Pazartesi", "pazartesi'?(si|den|ye)?|pzts?")
, ( "Salı" , "salı?'?(sı|dan|ya)?" )
, ( "Çarşamba" , "çar(şamba)?'?(sı|dan|ya)?" )
, ( "Perşembe" , "per(şembe)?'?(si|den|ye)?" )
, ( "Cuma" , "cuma?'?(sı|dan|ya)?" )
, ( "Cumartesi", "cumartesi'?(si|den|ye)?|cmt" )
, ( "Pazar" , "paz(ar)?'?(ı|dan|a)?" )
]
ruleMonths :: [Rule]
ruleMonths = mkRuleMonths
[ ( "Ocak" , "ocak?'?(ğın|tan|ğ?a)?" )
, ( "Şubat" , "şub(at)?'?(a|ın|tan)?" )
, ( "Mart" , "mart?'?(ın|a|tan)?" )
, ( "Nisan" , "nis(an)?'?(ın|a|dan)?" )
, ( "Mayıs" , "may(ıs)?'?(ın|a|tan)?" )
, ( "Haziran", "haz(iran)?'?(ın|a|dan)?" )
, ( "Temmuz" , "tem(muz)?'?(un|a|dan)?" )
, ( "Ağustos", "ağu(stos)?'?(un|a|tan)?" )
, ( "Eylül" , "eyl(ül)?'?(ün|e|den)?" )
, ( "Ekim" , "ekim?'?(in|den|e)?" )
, ( "Kasım" , "kas(ım)?'?(ın|dan|a)?" )
, ( "Aralık" , "ara(lık?)?'?(ğın|ğa|tan)?")
]
ruleSeasons :: [Rule]
ruleSeasons = mkRuleSeasons
[ ( "yaz", "yaz(ın|a|dan)?", monthDay 6 21, monthDay 9 23 )
, ( "sonbahar", "sonbahar(ın|a|dan)?", monthDay 9 23, monthDay 12 21 )
, ( "kış", "kış(ın|a|tan)?", monthDay 12 21, monthDay 3 20 )
, ( "ilkbahar", "ilkbahar(ın|a|dan)?", monthDay 3 20, monthDay 6 21 )
]
ruleHolidays :: [Rule]
ruleHolidays = mkRuleHolidays
[ ( "Yılbaşı" , "yılbaşı(ndan|na)?|yılbaşı(\\statili(nden|ne))?" , monthDay 1 1 )
, ( "Ulusal Egemenlik ve Çocuk Bayramı" , "(ulusal\\segemenlik\\sve\\s)?çocuk\\sbayramı" , monthDay 4 23 )
, ( "Emek ve Dayanışma Günü" , "emek\\sve\\sdayanışma\\sgünü" , monthDay 5 1 )
, ( "Atatürk’ü Anma, Gençlik ve Spor Bayramı", "(gençlik\\sve\\sspor|spor|gençlik)\\sbayramı" , monthDay 5 19 )
, ( "Zafer Bayramı" , "zafer\\sbayramı" , monthDay 8 30 )
, ( "Cumhuriyet Bayramı" , "cumhuriyet\\sbayramı" , monthDay 10 29 )
]
ruleComputedHolidays:: [Rule]
ruleComputedHolidays = mkRuleHolidays
[ ("Kurban Bayramı", "kurban\\sbayramı", eidalAdha)
, ("Ramazan Bayramı", "ramazan\\sbayramı", eidalFitr)
]
rulePartOfDays :: Rule
rulePartOfDays = Rule
{ name = "part of days"
, pattern =
[ regex "(sabah(ı|a|tan)?|öğlen?|akşam|gece|öğle\\syemeği)"
]
, prod = \case
(Token RegexMatch (GroupMatch (match:_)):_) -> do
let (start, end) = case Text.toLower match of
"sabah" -> (hour False 0, hour False 12 )
"sabahı" -> (hour False 0, hour False 12 )
"sabaha" -> (hour False 0, hour False 12 )
"sabahtan" -> (hour False 0, hour False 12 )
"akşam" -> (hour False 18, hour False 0 )
"gece" -> (hour False 18, hour False 0 )
"öğlen" -> (hour False 12, hour False 14)
"öğle" -> (hour False 12, hour False 14)
"öğle yemeği" -> (hour False 12, hour False 14)
_ -> (hour False 12, hour False 19)
td <- interval TTime.Open start end
tt $ partOfDay $ mkLatent td
_ -> Nothing
}
rulePrecisionTOD :: Rule
rulePrecisionTOD = Rule
{ name = "about|exactly <time-of-day>"
, pattern =
[ Predicate $ isGrainFinerThan TG.Year
, regex "gibi|civarı(nda)?"
]
, prod = \case
(Token Time td:_) -> tt $ notLatent td
_ -> Nothing
}
rulePrecisionTOD2 :: Rule
rulePrecisionTOD2 = Rule
{ name = "about|exactly <time-of-day>"
, pattern =
[ regex "yaklaşık|tam(\\solarak)?"
, Predicate $ isGrainFinerThan TG.Year
]
, prod = \case
(_:Token Time td:_) -> tt $ notLatent td
_ -> Nothing
}
ruleDatetimeDatetimeInterval :: Rule
ruleDatetimeDatetimeInterval = Rule
{ name = "<datetime> - <datetime> (interval)"
, pattern =
[ Predicate isNotLatent
, regex "\\-"
, Predicate isNotLatent
]
, prod = \case
(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 "(?:с\\s+)?(10|20|30|31|[012]?[1-9])\\.?((?<=\\.)(?:10|11|12|0?[1-9])(?:\\.?))?"
, regex "\\-|/"
, regex "(10|20|30|31|[012]?[1-9])\\.(10|11|12|0?[1-9])\\.?((?<=\\.)\\d{2,4})?"
]
, prod = \case
(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
}
ruleInDuration :: Rule
ruleInDuration = Rule
{ name = "in <duration>"
, pattern =
[ dimension Duration
, regex "içinde|içerisinde"
]
, prod = \case
(Token Duration dd:_) ->
tt $ inDuration dd
_ -> Nothing
}
ruleDurationHence :: Rule
ruleDurationHence = Rule
{ name = "<duration> hence"
, pattern =
[ dimension Duration
, regex "sonra"
]
, prod = \case
(Token Duration dd:_) ->
tt $ inDuration dd
_ -> Nothing
}
ruleDurationFromNow :: Rule
ruleDurationFromNow = Rule
{ name = "<duration> from now"
, pattern =
[ regex "(bugünden\\s)?sonra(ki)?"
, dimension Duration
]
, prod = \case
(_:Token Duration dd:_) ->
tt $ inDuration dd
_ -> Nothing
}
ruleLastCycleOfTime :: Rule
ruleLastCycleOfTime = Rule
{ name = "last <cycle> of <time>"
, pattern =
[ dimension Time
, regex "son"
, dimension TimeGrain
]
, prod = \case
(Token Time td:_:Token TimeGrain grain:_) ->
tt $ cycleLastOf grain td
_ -> Nothing
}
ruleYearLatent2 :: Rule
ruleYearLatent2 = Rule
{ name = "year (latent)"
, pattern =
[ Predicate $ isIntegerBetween 2101 10000
]
, prod = \case
(token:_) -> do
v <- getIntValue token
tt $ mkLatent $ year v
_ -> Nothing
}
ruleNoon :: Rule
ruleNoon = Rule
{ name = "noon"
, pattern =
[ regex "öğle(n|den|ye)?"
]
, prod = \_ -> tt $ hour False 12
}
ruleThisnextDayofweek :: Rule
ruleThisnextDayofweek = Rule
{ name = "this|next <day-of-week>"
, pattern =
[ regex "bu|sonraki"
, Predicate isADayOfWeek
]
, prod = \case
(_:Token Time td:_) ->
tt $ predNth 0 True td
_ -> Nothing
}
ruleBetweenTimeofdayAndTimeofdayInterval :: Rule
ruleBetweenTimeofdayAndTimeofdayInterval = Rule
{ name = "between <time-of-day> and <time-of-day> (interval)"
, pattern =
[ Predicate isATimeOfDay
, regex "ile"
, Predicate isATimeOfDay
, regex "arası"
]
, prod = \case
(_:Token Time td1:_:Token Time td2:_) ->
Token Time <$> interval TTime.Closed td1 td2
_ -> Nothing
}
ruleNextCycle :: Rule
ruleNextCycle = Rule
{ name = "next <cycle>"
, pattern =
[ regex "sonraki|önümüzdeki|gelecek"
, dimension TimeGrain
]
, prod = \case
(_:Token TimeGrain grain:_) ->
tt $ cycleNth grain 1
_ -> Nothing
}
ruleLastCycle :: Rule
ruleLastCycle = Rule
{ name = "last <cycle>"
, pattern =
[ regex "son|geçen|geçtiğimiz|önceki"
, dimension TimeGrain
]
, prod = \case
(_:Token TimeGrain grain:_) ->
tt $ cycleNth grain (-1)
_ -> Nothing
}
ruleLunch :: Rule
ruleLunch = Rule
{ name = "lunch"
, pattern =
[ regex "öğlen? (yemeği|arası)"
]
, prod = \_ ->
let from = hour False 12
to = hour False 14
in Token Time . mkLatent . partOfDay <$>
interval TTime.Open from to
}
ruleAfternoon :: Rule
ruleAfternoon = Rule
{ name = "afternoon"
, pattern =
[ regex "öğleden sonra"
]
, prod = \_ ->
let from = hour False 12
to = hour False 19
in Token Time . mkLatent . partOfDay <$>
interval TTime.Open from to
}
ruleEvening :: Rule
ruleEvening = Rule
{ name = "evening"
, pattern =
[ regex "akşam(a|dan)?"
]
, prod = \_ ->
let from = hour False 18
to = hour False 0
in Token Time . mkLatent . partOfDay <$>
interval TTime.Open from to
}
ruleHourofdayIntegerAsRelativeMinutes :: Rule
ruleHourofdayIntegerAsRelativeMinutes = Rule
{ name = "<hour-of-day> <integer> (as relative minutes)"
, pattern =
[ Predicate $ and . sequence [isNotLatent, isAnHourOfDay]
, Predicate $ isIntegerBetween 1 59
]
, prod = \case
(Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}:
token:
_) -> do
n <- getIntValue token
tt $ hourMinute is12H hours n
_ -> Nothing
}
ruleDayofmonthordinalNamedmonth :: Rule
ruleDayofmonthordinalNamedmonth = Rule
{ name = "<day-of-month>(ordinal) <named-month>"
, pattern =
[ Predicate isDOMOrdinal
, Predicate isAMonth
]
, prod = \case
(token:Token Time td:_) -> Token Time <$> intersectDOM td token
_ -> Nothing
}
ruleIntervalBy :: Rule
ruleIntervalBy = Rule
{ name = "by <time>"
, pattern =
[ dimension Time
, regex "kadar"
]
, prod = \case
(Token Time td:_) -> Token Time <$> interval TTime.Open now td
_ -> Nothing
}
ruleIntersectBy :: Rule
ruleIntersectBy = Rule
{ name = "intersect by ','"
, pattern =
[ Predicate isNotLatent
, regex ","
, Predicate isNotLatent
]
, prod = \case
(Token Time td1:_:Token Time td2:_) ->
Token Time <$> intersect td1 td2
_ -> Nothing
}
ruleNthTimeAfterTime :: Rule
ruleNthTimeAfterTime = Rule
{ name = "nth <time> after <time>"
, pattern =
[ dimension Time
, regex "sonra(ki)?"
, dimension Ordinal
, dimension Time
]
, prod = \case
(Token Time td1:
_:
Token Ordinal OrdinalData{TOrdinal.value = v}:
Token Time td2:
_) -> tt $ predNthAfter (v - 1) td1 td2
_ -> Nothing
}
ruleMMDD :: Rule
ruleMMDD = Rule
{ name = "mm/dd"
, pattern =
[ regex "([012]?[1-9]|10|20|30|31)\\.(10|11|12|0?[1-9])\\.?"
]
, prod = \case
(Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do
d <- parseInt m1
m <- parseInt m2
tt $ monthDay m d
_ -> Nothing
}
ruleMMDDYYYY :: Rule
ruleMMDDYYYY = Rule
{ name = "mm/dd/yyyy"
, pattern =
[ regex "(1[0-2]|0?[1-9])[-/\\s](3[01]|[12]\\d|0?[1-9])[-/\\s](\\d{2,4})"
]
, prod = \case
(Token RegexMatch (GroupMatch (mm:dd:yy:_)):_) -> do
y <- parseInt yy
m <- parseInt mm
d <- parseInt dd
tt $ yearMonthDay y m d
_ -> Nothing
}
ruleTimeofdayLatent :: Rule
ruleTimeofdayLatent = Rule
{ name = "time-of-day (latent)"
, pattern =
[ Predicate $ isIntegerBetween 0 23
]
, prod = \case
(token:_) -> do
n <- getIntValue token
tt $ mkLatent $ hour (n < 12) n
_ -> Nothing
}
ruleDurationAgo :: Rule
ruleDurationAgo = Rule
{ name = "<duration> ago"
, pattern =
[ dimension Duration
, regex "önce"
]
, prod = \case
(Token Duration dd:_:_) ->
tt $ durationAgo dd
_ -> Nothing
}
ruleIdesOfMonth :: Rule
ruleIdesOfMonth = Rule
{ name = "the ides of <named-month>"
, pattern =
[ Predicate isAMonth
, regex "ortası"
]
, prod = \case
(Token Time td@TimeData {TTime.form = Just (TTime.Month m)}:_) ->
Token Time <$>
intersect td (dayOfMonth $ if elem m [3, 5, 7, 10] then 15 else 13)
_ -> Nothing
}
ruleLastNCycle :: Rule
ruleLastNCycle = Rule
{ name = "last n <cycle>"
, pattern =
[ regex "son|geçen|geçtiğimiz|önceki"
, Predicate $ isIntegerBetween 1 9999
, dimension TimeGrain
]
, prod = \case
(_:token:Token TimeGrain grain:_) -> do
n <- getIntValue token
tt $ cycleN True grain (- n)
_ -> Nothing
}
ruleMidnighteodendOfDay :: Rule
ruleMidnighteodendOfDay = Rule
{ name = "midnight|EOD|end of day"
, pattern =
[ regex "gece\\syarısı|gün\\ssonu|gün\\sbitimi"
]
, prod = \_ -> tt $ hour False 0
}
ruleDayofmonthNonOrdinalNamedmonth :: Rule
ruleDayofmonthNonOrdinalNamedmonth = Rule
{ name = "<day-of-month> (non ordinal) <named-month>"
, pattern =
[ Predicate isDOMInteger
, Predicate isAMonth
]
, prod = \case
(token:Token Time td:_) -> Token Time <$> intersectDOM td token
_ -> Nothing
}
ruleIntersect :: Rule
ruleIntersect = Rule
{ name = "intersect"
, pattern =
[ Predicate isNotLatent
, Predicate isNotLatent
]
, prod = \case
(Token Time td1:Token Time td2:_) ->
Token Time <$> intersect td1 td2
_ -> Nothing
}
ruleUntilTimeofday :: Rule
ruleUntilTimeofday = Rule
{ name = "until <time-of-day>"
, pattern =
[ dimension Time
, regex "kadar"
]
, prod = \case
(_:Token Time td:_) -> tt $ withDirection TTime.Before td
_ -> Nothing
}
ruleAtTimeofday :: Rule
ruleAtTimeofday = Rule
{ name = "at <time-of-day>"
, pattern =
[ regex "saat"
, Predicate isATimeOfDay
]
, prod = \case
(_:Token Time td:_) -> tt $ notLatent td
_ -> Nothing
}
ruleAtTimeofday2 :: Rule
ruleAtTimeofday2 = Rule
{ name = "at <time-of-day>"
, pattern =
[ regex "saat"
, Predicate isATimeOfDay
, regex "'?(den|dan)?"
]
, prod = \case
(_:Token Time td:_) -> tt $ notLatent td
_ -> Nothing
}
ruleNthTimeOfTime :: Rule
ruleNthTimeOfTime = Rule
{ name = "nth <time> of <time>"
, pattern =
[ dimension Time
, dimension Ordinal
, dimension Time
]
, prod = \case
(Token Time td1:
Token Ordinal OrdinalData{TOrdinal.value = v}:
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 = \case
(Token Time td1:Token Time td2:_) ->
Token Time <$> intersect td1 td2
_ -> Nothing
}
ruleWeek :: Rule
ruleWeek = Rule
{ name = "week"
, pattern =
[ regex "((bu\\s)?hafta boyunca)|(bu hafta)|(haftanın geri kalanı)"
]
, prod = \case
(Token RegexMatch (GroupMatch (match:_)):_) ->
let end = cycleNthAfter True TG.Day (-2) $ cycleNth TG.Week 1
period = case Text.toLower match of
"hafta boyunca" -> interval Closed (cycleNth TG.Week 0) end
"haftanın geri kalanı" -> interval Open today end
"bu hafta" -> interval Open today end
_ -> Nothing
in case Text.toLower match of
"bu hafta" -> Token Time . mkLatent <$> period
_ -> Token Time <$> period
_ -> Nothing
}
ruleWeekend :: Rule
ruleWeekend = Rule
{ name = "week-end"
, pattern =
[ regex "hafta sonu"
]
, prod = \_ -> tt $ mkOkForThisNext weekend
}
ruleOrdinalQuarterYear :: Rule
ruleOrdinalQuarterYear = Rule
{ name = "<ordinal> quarter <year>"
, pattern =
[ dimension Ordinal
, Predicate $ isGrain TG.Quarter
, dimension Time
]
, prod = \case
(Token Ordinal od:_:Token Time td:_) ->
tt $ cycleNthAfter False TG.Quarter (TOrdinal.value od - 1) td
_ -> Nothing
}
ruleYYYYMMDD :: Rule
ruleYYYYMMDD = Rule
{ name = "yyyy-mm-dd"
, pattern =
[ regex "(\\d{2,4})-(0?[1-9]|10|11|12)-([012]?[1-9]|10|20|30|31)"
]
, prod = \case
(Token RegexMatch (GroupMatch (m1:m2:m3:_)):_) -> do
y <- parseInt m1
m <- parseInt m2
d <- parseInt m3
tt $ yearMonthDay y m d
_ -> Nothing
}
ruleNextNCycle :: Rule
ruleNextNCycle = Rule
{ name = "next n <cycle>"
, pattern =
[ regex "önümüzdeki|sonraki"
, Predicate $ isIntegerBetween 1 9999
, dimension TimeGrain
]
, prod = \case
(_:token:Token TimeGrain grain:_) -> do
v <- getIntValue token
tt $ cycleN True grain v
_ -> Nothing
}
ruleThisPartofday :: Rule
ruleThisPartofday = Rule
{ name = "this <part-of-day>"
, pattern =
[ regex "bu"
, Predicate isAPartOfDay
]
, prod = \case
(_:Token Time td:_) -> Token Time . partOfDay <$> intersect today td
_ -> Nothing
}
ruleThisCycle :: Rule
ruleThisCycle = Rule
{ name = "this <cycle>"
, pattern =
[ regex "bu"
, dimension TimeGrain
]
, prod = \case
(_:Token TimeGrain grain:_) ->
tt $ cycleNth grain 0
_ -> Nothing
}
ruleThisTime :: Rule
ruleThisTime = Rule
{ name = "this <time>"
, pattern =
[ regex "bu"
, Predicate isOkWithThisNext
]
, prod = \case
(_:Token Time td:_) -> tt $ predNth 0 False td
_ -> Nothing
}
ruleNextTime :: Rule
ruleNextTime = Rule
{ name = "next <time>"
, pattern =
[ regex "önümüzdeki|gelecek|sonraki"
, Predicate isOkWithThisNext
]
, prod = \case
(_:Token Time td:_) -> tt $ predNth 0 True td
_ -> Nothing
}
ruleLastTime :: Rule
ruleLastTime = Rule
{ name = "last <time>"
, pattern =
[ regex "geçen|önceki|geçtiğimiz|son"
, Predicate isOkWithThisNext
]
, prod = \case
(_:Token Time td:_) -> tt $ predNth (- 1) False td
_ -> Nothing
}
ruleYearLatent :: Rule
ruleYearLatent = Rule
{ name = "year (latent)"
, pattern =
[ Predicate $ isIntegerBetween 25 999
]
, prod = \case
(token:_) -> do
y <- getIntValue token
tt $ mkLatent $ year y
_ -> Nothing
}
ruleAfterTimeofday :: Rule
ruleAfterTimeofday = Rule
{ name = "after <time-of-day>"
, pattern =
[ regex "sonraki|önümüzdeki"
, Predicate isATimeOfDay
]
, prod = \case
(_:Token Time td:_) -> tt $ withDirection TTime.After td
_ -> Nothing
}
ruleNight :: Rule
ruleNight = Rule
{ name = "night"
, pattern =
[ regex "gece(ye|den)?"
]
, 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 = \case
(Token Ordinal OrdinalData{TOrdinal.value = v}:_) ->
tt $ dayOfMonth v
_ -> Nothing
}
ruleOrdinalCycleOfTime :: Rule
ruleOrdinalCycleOfTime = Rule
{ name = "<ordinal> <cycle> of <time>"
, pattern =
[ dimension Time
, dimension Ordinal
, dimension TimeGrain
]
, prod = \case
(Token Time td:Token Ordinal od:Token TimeGrain grain:_) ->
tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td
_ -> Nothing
}
ruleHhmm :: Rule
ruleHhmm = Rule
{ name = "hh:mm"
, pattern =
[ regex "((?:[01]?\\d)|(?:2[0-3]))[:.ч]([0-5]\\d)(?:час(ов|а|у)?|ч)?"
]
, prod = \case
(Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do
h <- parseInt m1
m <- parseInt m2
tt $ hourMinute False h m
_ -> Nothing
}
ruleYear :: Rule
ruleYear = Rule
{ name = "year"
, pattern =
[ Predicate $ isIntegerBetween 1000 2100
]
, prod = \case
(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 = \case
(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 = \case
(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 = \case
(x:_) -> Just x
_ -> Nothing
}
ruleLastDayofweekOfTime :: Rule
ruleLastDayofweekOfTime = Rule
{ name = "last <day-of-week> of <time>"
, pattern =
[ dimension Time
, regex "son"
, Predicate isADayOfWeek
]
, prod = \case
(
Token Time td1:
_:
Token Time td2:
_) -> tt $ predLastOf td1 td2
_ -> Nothing
}
ruleTimeofdayTimeofdayInterval :: Rule
ruleTimeofdayTimeofdayInterval = Rule
{ name = "<time-of-day> - <time-of-day> (interval)"
, pattern =
[ Predicate $ and . sequence [isNotLatent, isATimeOfDay]
, regex "\\-"
, Predicate isATimeOfDay
]
, prod = \case
(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 "\\-|/"
, Predicate $ and . sequence [isNotLatent, isATimeOfDay]
]
, prod = \case
(Token Time td1:_:Token Time td2:_) ->
Token Time <$> interval TTime.Closed td1 td2
_ -> Nothing
}
ruleIntervalForDurationFrom :: Rule
ruleIntervalForDurationFrom = Rule
{ name = "for <duration> from <time>"
, pattern =
[ dimension Time
, regex "itibaren"
, dimension Duration
, regex "boyunca|süresince"
]
, prod = \case
(Token Time td1:_:Token Duration dd:_) ->
Token Time <$> interval TTime.Closed td1 (durationAfter dd td1)
_ -> Nothing
}
ruleDurationAfterTime :: Rule
ruleDurationAfterTime = Rule
{ name = "<duration> after <time>"
, pattern =
[ dimension Time
, regex "sonra(ki)?"
, dimension Duration
]
, prod = \case
(Token Time td:_:Token Duration dd:_) ->
tt $ durationAfter dd td
_ -> Nothing
}
ruleDurationAfterTime2 :: Rule
ruleDurationAfterTime2 = Rule
{ name = "<duration> after <time>"
, pattern =
[ dimension Time
, dimension Duration
, regex "sonra"
]
, prod = \case
(Token Time td:Token Duration dd:_:_) ->
tt $ durationAfter dd td
_ -> Nothing
}
ruleOrdinalQuarter :: Rule
ruleOrdinalQuarter = Rule
{ name = "<ordinal> quarter"
, pattern =
[ dimension Ordinal
, Predicate $ isGrain TG.Quarter
]
, prod = \case
(Token Ordinal OrdinalData{TOrdinal.value = v}:_) ->
tt $ cycleNthAfter False TG.Quarter (v - 1) $ cycleNth TG.Year 0
_ -> Nothing
}
ruleDurationBeforeTime :: Rule
ruleDurationBeforeTime = Rule
{ name = "<duration> before <time>"
, pattern =
[ dimension Time
, regex "önceki"
, dimension Duration
]
, prod = \case
(Token Time td:_:Token Duration dd:_) ->
tt $ durationBefore dd td
_ -> Nothing
}
rulePartofdayOfTime :: Rule
rulePartofdayOfTime = Rule
{ name = "<part-of-day> of <time>"
, pattern =
[ Predicate isAPartOfDay
, dimension Time
]
, prod = \case
(Token Time td1:Token Time td2:_) ->
Token Time <$> intersect td1 td2
_ -> 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 = \case
(Token Time td:
Token RegexMatch (GroupMatch (tz:_)):
_) -> Token Time <$> inTimezone (Text.toUpper tz) td
_ -> Nothing
}
rules :: [Rule]
rules =
[ ruleAbsorptionOfAfterNamedDay
, ruleAfterTimeofday
, ruleAfternoon
, ruleAtTimeofday
, ruleAtTimeofday2
, ruleBetweenTimeofdayAndTimeofdayInterval
, ruleDatetimeDatetimeInterval
, ruleDateDateInterval
, ruleDayofmonthNonOrdinalNamedmonth
, ruleDayofmonthOrdinal
, ruleDayofmonthordinalNamedmonth
, ruleDurationAfterTime
, ruleDurationAfterTime2
, ruleIntervalForDurationFrom
, ruleDurationAgo
, ruleDurationBeforeTime
, ruleEvening
, ruleHhmm
, ruleHhmmMilitary
, ruleHourofdayIntegerAsRelativeMinutes
, ruleIdesOfMonth
, ruleInDuration
, ruleIntervalBy
, ruleDurationHence
, ruleDurationFromNow
, ruleIntersect
, ruleIntersectBy
, ruleLastCycle
, ruleLastCycleOfTime
, ruleLastDayofweekOfTime
, ruleLastNCycle
, ruleLastTime
, ruleThisTime
, ruleNextTime
, ruleLunch
, ruleMidnighteodendOfDay
, ruleMMDD
, ruleMMDDYYYY
, ruleYYYYMMDD
, ruleNamedmonthDayofmonthNonOrdinal
, ruleNextCycle
, ruleNextNCycle
, ruleNight
, ruleNoon
, ruleNthTimeAfterTime
, ruleNthTimeOfTime
, ruleOrdinalCycleOfTime
, ruleOrdinalQuarter
, ruleOrdinalQuarterYear
, rulePartOfDays
, rulePartofdayOfTime
, rulePrecisionTOD
, rulePrecisionTOD2
, ruleThisCycle
, ruleThisPartofday
, ruleThisTime
, ruleThisnextDayofweek
, ruleTimePartofday
, ruleTimeofdayLatent
, ruleTimeofdayTimeofdayInterval
, ruleTimeofdayTimeofdayInterval2
, ruleUntilTimeofday
, ruleWeek
, ruleWeekend
, ruleYear
, ruleYearLatent
, ruleYearLatent2
, ruleTimezone
]
++ ruleInstants
++ ruleDaysOfWeek
++ ruleMonths
++ ruleSeasons
++ ruleHolidays
++ ruleComputedHolidays