-- Copyright (c) 2016-present, Facebook, Inc. -- All rights reserved. -- -- This source code is licensed under the BSD-style license found in the -- LICENSE file in the root directory of this source tree. An additional grant -- of patent rights can be found in the PATENTS file in the same directory. {-# LANGUAGE GADTs #-} {-# LANGUAGE NoRebindableSyntax #-} {-# LANGUAGE OverloadedStrings #-} module Duckling.Time.IT.Rules ( rules ) where import Data.Text (Text) import Prelude import qualified Data.Text as Text import Duckling.Dimensions.Types 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 ruleFestaDellaRepubblica :: Rule ruleFestaDellaRepubblica = Rule { name = "festa della repubblica" , pattern = [ regex "((festa del)?la )?repubblica" ] , prod = \_ -> tt $ monthDay 6 2 } ruleEpifania :: Rule ruleEpifania = Rule { name = "epifania" , pattern = [ regex "(epifania|befana)" ] , prod = \_ -> tt $ monthDay 1 6 } ruleDayofmonthNamedmonth :: Rule ruleDayofmonthNamedmonth = Rule { name = "<day-of-month> <named-month>" , pattern = [ Predicate isDOMInteger , Predicate isAMonth ] , prod = \tokens -> case tokens of (token:Token Time td:_) -> Token Time <$> intersectDOM td token _ -> Nothing } ruleTheDayAfterTomorrow :: Rule ruleTheDayAfterTomorrow = Rule { name = "the day after tomorrow" , pattern = [ regex "(il giorno )?dopo\\s?domani" ] , prod = \_ -> tt $ cycleNth TG.Day 2 } ruleInafterDuration :: Rule ruleInafterDuration = Rule { name = "in/after <duration>" , pattern = [ regex "[tf]ra|in|dopo" , dimension Duration ] , prod = \tokens -> case tokens of (_:Token Duration dd:_) -> tt $ inDuration dd _ -> Nothing } ruleTheLastCycle :: Rule ruleTheLastCycle = Rule { name = "the last <cycle>" , pattern = [ regex "(([nd]el)?l' ?ultim|(il|la) passat|([nd]el)?l[ao] scors)[oa]" , dimension TimeGrain ] , prod = \tokens -> case tokens of (_:Token TimeGrain grain:_) -> tt . cycleNth grain $ - 1 _ -> Nothing } ruleStanotte :: Rule ruleStanotte = Rule { name = "stanotte" , pattern = [ regex "(sta|nella )notte|(in|nella) nottata" ] , prod = \_ -> do let td1 = cycleNth TG.Day 1 td2 <- interval TTime.Open (hour False 0) (hour False 4) Token Time . partOfDay <$> intersect td1 td2 } ruleDomattina :: Rule ruleDomattina = Rule { name = "domattina" , pattern = [ regex "domattina" ] , prod = \_ -> do let td1 = cycleNth TG.Day 1 td2 <- interval TTime.Open (hour False 4) (hour False 12) Token Time . partOfDay <$> intersect td1 td2 } ruleTheCycleNext :: Rule ruleTheCycleNext = Rule { name = "the <cycle> next" , pattern = [ regex "l'|il|la|[nd]el(la)?" , dimension TimeGrain , regex "prossim[oa]" ] , prod = \tokens -> case tokens of (_:Token TimeGrain grain:_) -> tt $ cycleNth grain 1 _ -> Nothing } ruleCycleNext :: Rule ruleCycleNext = Rule { name = "<cycle> next" , pattern = [ dimension TimeGrain , regex "prossim[oa]" ] , prod = \tokens -> case tokens of (Token TimeGrain grain:_) -> tt $ cycleNth grain 1 _ -> Nothing } ruleFestaDellaLiberazione :: Rule ruleFestaDellaLiberazione = Rule { name = "festa della liberazione" , pattern = [ regex "((festa|anniversario) della|(al)?la) liberazione" ] , prod = \_ -> tt $ monthDay 4 25 } ruleStamattina :: Rule ruleStamattina = Rule { name = "stamattina" , pattern = [ regex "stamattina" ] , prod = \_ -> do let td1 = cycleNth TG.Day 0 td2 <- interval TTime.Open (hour False 4) (hour False 12) Token Time . partOfDay <$> intersect td1 td2 } ruleYearNotLatent :: Rule ruleYearNotLatent = Rule { name = "year (1000-2100 not latent)" , pattern = [ Predicate $ isIntegerBetween 1000 2100 ] , prod = \tokens -> case tokens of (token:_) -> do v <- getIntValue token tt $ year v _ -> Nothing } ruleValentinesDay :: Rule ruleValentinesDay = Rule { name = "valentine's day" , pattern = [ regex "san valentino|festa degli innamorati" ] , prod = \_ -> tt $ monthDay 2 14 } ruleTheOrdinalCycleOfTime :: Rule ruleTheOrdinalCycleOfTime = Rule { name = "the <ordinal> <cycle> of <time>" , pattern = [ regex "il|l[a']|[nd]el(l[a'])?" , dimension Ordinal , dimension TimeGrain , regex "di|del(l[a'])?" , 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 } 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 } ruleTheOrdinalQuarter :: Rule ruleTheOrdinalQuarter = Rule { name = "the <ordinal> quarter" , pattern = [ regex "il|[nd]el(l')?|l'" , 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 } ruleCycleOrdinalQuarterYear :: Rule ruleCycleOrdinalQuarterYear = 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 } ruleCycleTheOrdinalTime :: Rule ruleCycleTheOrdinalTime = Rule { name = "the <ordinal> <cycle> <time>" , pattern = [ regex "il|[nd]el(l')?|l'" , dimension Ordinal , dimension TimeGrain , dimension Time ] , prod = \tokens -> case tokens of (_:token:Token TimeGrain grain:Token Time td:_) -> do n <- getIntValue token tt $ cycleNthAfter True grain (n - 1) td _ -> Nothing } ruleDdddMonthInterval :: Rule ruleDdddMonthInterval = Rule { name = "dd-dd <month> (interval)" , pattern = [ regex "(3[01]|[12]\\d|0?[1-9])" , regex "\\-" , regex "(3[01]|[12]\\d|0?[1-9])" , 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 } ruleTimeLast :: Rule ruleTimeLast = Rule { name = "<time> last" , pattern = [ dimension Time , regex "(ultim|scors|passat)[oaie]" ] , prod = \tokens -> case tokens of (Token Time td:_) -> tt $ predNth (-1) False td _ -> Nothing } ruleThisDayofweek :: Rule ruleThisDayofweek = Rule { name = "this <day-of-week>" , pattern = [ regex "quest[oaie]" , Predicate isADayOfWeek ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> tt $ predNth 0 True td _ -> Nothing } ruleUna :: Rule ruleUna = Rule { name = "una" , pattern = [ regex "una" ] , prod = \_ -> tt . mkLatent $ hour True 1 } ruleNthTimeOfTime2 :: Rule ruleNthTimeOfTime2 = Rule { name = "nth <time> of <time>" , pattern = [ dimension Ordinal , dimension Time , regex "di|del(l[oa'])|in" , dimension Time ] , prod = \tokens -> case tokens of (Token Ordinal OrdinalData {TOrdinal.value = v}: Token Time td1: _: Token Time td2: _) -> Token Time . predNth (v - 1) False <$> intersect td2 td1 _ -> Nothing } ruleNewYearsDay :: Rule ruleNewYearsDay = Rule { name = "new year's day" , pattern = [ regex "(capodanno|primo dell' ?anno)" ] , prod = \_ -> tt $ monthDay 1 1 } ruleLastTime :: Rule ruleLastTime = Rule { name = "last <time> " , pattern = [ regex "(ultim|scors|passat)[oaie]" , dimension Time ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> tt $ predNth (-1) False td _ -> Nothing } ruleIlDayofmonthDeNamedmonth :: Rule ruleIlDayofmonthDeNamedmonth = Rule { name = "il <day-of-month> <named-month>" , pattern = [ regex "il|l'" , Predicate isDOMInteger , Predicate isAMonth ] , prod = \tokens -> case tokens of (_:token:Token Time td:_) -> Token Time <$> intersectDOM td token _ -> Nothing } ruleDatetimeDatetimeInterval :: Rule ruleDatetimeDatetimeInterval = Rule { name = "<datetime> - <datetime> (interval)" , pattern = [ Predicate isNotLatent , regex "\\-|[fs]ino a(l(l[e'])?)?" , Predicate isNotLatent ] , prod = \tokens -> case tokens of (Token Time td1:_:Token Time td2:_) -> Token Time <$> interval TTime.Closed td1 td2 _ -> Nothing } ruleEvening :: Rule ruleEvening = Rule { name = "evening" , pattern = [ regex "ser(ata|[ae])" ] , prod = \_ -> let from = hour False 18 to = hour False 0 in Token Time . mkLatent . partOfDay <$> interval TTime.Open from to } ruleDayOfMonthSt :: Rule ruleDayOfMonthSt = Rule { name = "day of month (1st)" , pattern = [ regex "(primo|1o|1º|1°)" ] , prod = \_ -> tt $ dayOfMonth 1 } ruleInDuration :: Rule ruleInDuration = Rule { name = "in|entro <duration>" , pattern = [ regex "(in|entro)" , dimension Duration ] , prod = \tokens -> case tokens of (Token RegexMatch (GroupMatch (match:_)): Token Duration dd: _) -> case Text.toLower match of "entro" -> Token Time <$> interval TTime.Open (cycleNth TG.Second 0) (inDuration dd) "in" -> tt $ inDuration dd _ -> Nothing _ -> Nothing } ruleInNamedmonth :: Rule ruleInNamedmonth = Rule { name = "in <named-month>" , pattern = [ regex "in|del mese( di)?" , Predicate isAMonth ] , prod = \tokens -> case tokens of (_:x:_) -> Just x _ -> Nothing } ruleLeIdiDiNamedmonth :: Rule ruleLeIdiDiNamedmonth = Rule { name = "le idi di <named-month>" , pattern = [ regex "(le )?idi di" , 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 } ruleRightNow :: Rule ruleRightNow = Rule { name = "right now" , pattern = [ regex "(subito|(immediata|attual)mente|(proprio )?adesso|(in questo|al) momento|ora)" ] , prod = \_ -> tt $ cycleNth TG.Second 0 } ruleToday :: Rule ruleToday = Rule { name = "today" , pattern = [ regex "(di )?oggi|in giornata" ] , prod = \_ -> tt $ cycleNth TG.Day 0 } ruleLastCycleOfTime :: Rule ruleLastCycleOfTime = Rule { name = "last <cycle> of <time>" , pattern = [ regex "(l')ultim[oa]" , dimension TimeGrain , regex "di|del(l[oa'])" , dimension Time ] , prod = \tokens -> case tokens of (_:Token TimeGrain grain:_:Token Time td:_) -> tt $ cycleLastOf grain td _ -> Nothing } ruleHhRelativeminutesDelPomeriggiotimeofday2 :: Rule ruleHhRelativeminutesDelPomeriggiotimeofday2 = Rule { name = "hh <relative-minutes> del pomeriggio(time-of-day)" , pattern = [ Predicate isAnHourOfDay , regex "e" , Predicate $ isIntegerBetween 1 59 , regex "d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}: _: token: _) -> do n <- getIntValue token let h = if hours > 12 then hours else hours + 12 tt $ hourMinute False h n _ -> 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 } ruleHourofdayAndRelativeMinutes :: Rule ruleHourofdayAndRelativeMinutes = Rule { name = "<hour-of-day> and <relative minutes>" , pattern = [ Predicate isAnHourOfDay , regex "e" , 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 } ruleRelativeMinutesToIntegerAsHourofday :: Rule ruleRelativeMinutesToIntegerAsHourofday = Rule { name = "relative minutes to <integer> (as hour-of-day)" , pattern = [ Predicate $ isIntegerBetween 1 59 , regex "a" , Predicate isAnHourOfDay ] , prod = \tokens -> case tokens of (token:_:Token Time td:_) -> do n <- getIntValue token t <- minutesBefore n td Just $ Token Time t _ -> Nothing } ruleHourofdayMinusIntegerAsRelativeMinutes :: Rule ruleHourofdayMinusIntegerAsRelativeMinutes = Rule { name = "<hour-of-day> minus <integer> (as relative minutes)" , pattern = [ Predicate isAnHourOfDay , regex "meno" , Predicate $ isIntegerBetween 1 59 ] , prod = \tokens -> case tokens of (Token Time td:_:token:_) -> do n <- getIntValue token t <- minutesBefore n td Just $ Token Time t _ -> Nothing } ruleHhRelativeminutesDelPomeriggiotimeofday :: Rule ruleHhRelativeminutesDelPomeriggiotimeofday = Rule { name = "hh <relative-minutes> del pomeriggio(time-of-day)" , pattern = [ Predicate $ and . sequence [isNotLatent, isAnHourOfDay] , Predicate $ isIntegerBetween 1 59 , regex "d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}: token: _) -> do n <- getIntValue token let h = if hours > 12 then hours else hours + 12 tt $ hourMinute False h n _ -> Nothing } ruleHhIntegerminutesDelPomeriggiotimeofday2 :: Rule ruleHhIntegerminutesDelPomeriggiotimeofday2 = Rule { name = "hh <relative-minutes> minutes del pomeriggio(time-of-day)" , pattern = [ Predicate isAnHourOfDay , regex "e" , Predicate $ isIntegerBetween 1 59 , regex "min(ut[oi]|\\.)? d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}: _: token: _) -> do n <- getIntValue token let h = if hours > 12 then hours else hours + 12 tt $ hourMinute False h n _ -> Nothing } ruleHourofdayIntegerMinutes :: Rule ruleHourofdayIntegerMinutes = Rule { name = "<hour-of-day> <integer> minutes" , pattern = [ Predicate $ and . sequence [isNotLatent, isAnHourOfDay] , Predicate $ isIntegerBetween 1 59 , regex "min(ut[oi]|\\.)?" ] , 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 } ruleHourofdayAndIntegerMinutes :: Rule ruleHourofdayAndIntegerMinutes = Rule { name = "<hour-of-day> and <integer> minutes" , pattern = [ Predicate isAnHourOfDay , regex "e" , Predicate $ isIntegerBetween 1 59 , regex "min(ut[oi]|\\.)?" ] , 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 } ruleMinutesToIntegerAsHourofday :: Rule ruleMinutesToIntegerAsHourofday = Rule { name = "minutes to <integer> (as hour-of-day)" , pattern = [ Predicate $ isIntegerBetween 1 59 , regex "min(ut[oi]|\\.)? a" , Predicate isAnHourOfDay ] , prod = \tokens -> case tokens of (token:_:Token Time td:_) -> do n <- getIntValue token t <- minutesBefore n td Just $ Token Time t _ -> Nothing } ruleHourofdayMinusIntegerMinutes :: Rule ruleHourofdayMinusIntegerMinutes = Rule { name = "<hour-of-day> minus <integer> minutes" , pattern = [ Predicate isAnHourOfDay , regex "meno" , Predicate $ isIntegerBetween 1 59 , regex "min(ut[oi]|\\.)?" ] , prod = \tokens -> case tokens of (Token Time td: _: token: _) -> do v <- getIntValue token Token Time <$> minutesBefore v td _ -> Nothing } ruleHhIntegerminutesDelPomeriggiotimeofday :: Rule ruleHhIntegerminutesDelPomeriggiotimeofday = Rule { name = "hh <integer> minutes del pomeriggio(time-of-day)" , pattern = [ Predicate isAnHourOfDay , Predicate $ isIntegerBetween 1 59 , regex "min(ut[oi]|\\.)? d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}: token: _) -> do v <- getIntValue token let h = if hours > 12 then hours else hours + 12 tt $ hourMinute False h v _ -> Nothing } ruleHhQuartDelPomeriggiotimeofday2 :: Rule ruleHhQuartDelPomeriggiotimeofday2 = Rule { name = "hh quart del pomeriggio(time-of-day)" , pattern = [ Predicate isAnHourOfDay , regex "e un quarto d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}: _) -> let h = if hours > 12 then hours else hours + 12 in tt $ hourMinute False h 15 _ -> Nothing } ruleHourofdayQuart :: Rule ruleHourofdayQuart = Rule { name = "<hour-of-day> quart" , pattern = [ Predicate isAnHourOfDay , regex "un quarto" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}: _) -> tt $ hourMinute is12H hours 15 _ -> Nothing } ruleHourofdayAndAQuart :: Rule ruleHourofdayAndAQuart = Rule { name = "<hour-of-day> and a quart" , pattern = [ Predicate isAnHourOfDay , regex "e un quarto" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}: _) -> tt $ hourMinute is12H hours 15 _ -> Nothing } ruleQuartAsHourofday :: Rule ruleQuartAsHourofday = Rule { name = "a quart to <integer> (as hour-of-day)" , pattern = [ regex "un quarto a" , Predicate isAnHourOfDay ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> Token Time <$> minutesBefore 15 td _ -> Nothing } ruleHourofdayMinusQuart :: Rule ruleHourofdayMinusQuart = Rule { name = "<hour-of-day> minus quart" , pattern = [ Predicate isAnHourOfDay , regex "meno un quarto" ] , prod = \tokens -> case tokens of (Token Time td:_) -> Token Time <$> minutesBefore 15 td _ -> Nothing } ruleHhQuartDelPomeriggiotimeofday :: Rule ruleHhQuartDelPomeriggiotimeofday = Rule { name = "hh quart del pomeriggio(time-of-day)" , pattern = [ Predicate isAnHourOfDay , regex "un quarto d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}: _) -> let h = if hours > 12 then hours else hours + 12 in tt $ hourMinute False h 15 _ -> Nothing } ruleHhHalfDelPomeriggiotimeofday2 :: Rule ruleHhHalfDelPomeriggiotimeofday2 = Rule { name = "hh half del pomeriggio(time-of-day)" , pattern = [ Predicate isAnHourOfDay , regex "e mezzo d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}: _) -> let h = if hours > 12 then hours else hours + 12 in tt $ hourMinute False h 30 _ -> Nothing } ruleHourofdayHalf :: Rule ruleHourofdayHalf = Rule { name = "<hour-of-day> half" , pattern = [ Predicate isAnHourOfDay , regex "mezzo" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}: _) -> tt $ hourMinute is12H hours 30 _ -> Nothing } ruleHourofdayAndHalf :: Rule ruleHourofdayAndHalf = Rule { name = "<hour-of-day> and half" , pattern = [ Predicate isAnHourOfDay , regex "e mezzo" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}: _) -> tt $ hourMinute is12H hours 30 _ -> Nothing } ruleHalfToIntegerAsHourofday :: Rule ruleHalfToIntegerAsHourofday = Rule { name = "half to <integer> (as hour-of-day)" , pattern = [ regex "mezzo a" , Predicate isAnHourOfDay ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> Token Time <$> minutesBefore 30 td _ -> Nothing } ruleHourofdayMinusHalf :: Rule ruleHourofdayMinusHalf = Rule { name = "<hour-of-day> minus half" , pattern = [ Predicate isAnHourOfDay , regex "meno mezzo" ] , prod = \tokens -> case tokens of (Token Time td:_) -> Token Time <$> minutesBefore 30 td _ -> Nothing } ruleHhHalfDelPomeriggiotimeofday :: Rule ruleHhHalfDelPomeriggiotimeofday = Rule { name = "hh half del pomeriggio(time-of-day)" , pattern = [ Predicate isAnHourOfDay , regex "mezzo d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}: _) -> let h = if hours > 12 then hours else hours + 12 in tt $ hourMinute False h 30 _ -> Nothing } ruleHhThreeQuarterDelPomeriggiotimeofday2 :: Rule ruleHhThreeQuarterDelPomeriggiotimeofday2 = Rule { name = "hh three quarters del pomeriggio(time-of-day)" , pattern = [ Predicate isAnHourOfDay , regex "e (3|tre) quarti? d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}: _) -> let h = if hours > 12 then hours else hours + 12 in tt $ hourMinute False h 45 _ -> Nothing } ruleHourofdayThreeQuarters :: Rule ruleHourofdayThreeQuarters = Rule { name = "<hour-of-day> three quarters" , pattern = [ Predicate isAnHourOfDay , regex "(3|tre) quarti?" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}: _) -> tt $ hourMinute is12H hours 45 _ -> Nothing } ruleHourofdayAndThreeQuarter :: Rule ruleHourofdayAndThreeQuarter = Rule { name = "<hour-of-day> and three quarters" , pattern = [ Predicate isAnHourOfDay , regex "e (3|tre) quarti?" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) is12H)}: _) -> tt $ hourMinute is12H hours 45 _ -> Nothing } ruleThreeQuarterToIntegerAsHourofday :: Rule ruleThreeQuarterToIntegerAsHourofday = Rule { name = "three quarter to <integer> (as hour-of-day)" , pattern = [ regex "(3|tre) quarti? a" , Predicate isAnHourOfDay ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> Token Time <$> minutesBefore 45 td _ -> Nothing } ruleHourofdayMinusThreeQuarter :: Rule ruleHourofdayMinusThreeQuarter = Rule { name = "<hour-of-day> minus three quarter" , pattern = [ Predicate isAnHourOfDay , regex "meno (3|tre) quarti?" ] , prod = \tokens -> case tokens of (Token Time td:_) -> Token Time <$> minutesBefore 45 td _ -> Nothing } ruleHhThreeQuarterDelPomeriggiotimeofday :: Rule ruleHhThreeQuarterDelPomeriggiotimeofday = Rule { name = "hh three quarter del pomeriggio(time-of-day)" , pattern = [ Predicate isAnHourOfDay , regex "(3|tre) quarti? d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))" ] , prod = \tokens -> case tokens of (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}: _) -> let h = if hours > 12 then hours else hours + 12 in tt $ hourMinute False h 45 _ -> Nothing } ruleHhhmmTimeofday :: Rule ruleHhhmmTimeofday = Rule { name = "hh(:|h)mm (time-of-day)" , pattern = [ regex "((?:[01]?\\d)|(?:2[0-3]))[:h]([0-5]\\d)" ] , prod = \tokens -> case tokens of (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do h <- parseInt m1 m <- parseInt m2 tt $ hourMinute False h m _ -> Nothing } ruleDalIntAlInt :: Rule ruleDalIntAlInt = Rule { name = "dal <integer> al <integer> (interval)" , pattern = [ regex "dal(?:l')?" , Predicate isDOMInteger , regex "([fs]ino )?al(l')?" , Predicate isDOMInteger ] , prod = \tokens -> case tokens of (_:token1:_:token2:_) -> do v1 <- getIntValue token1 v2 <- getIntValue token2 Token Time <$> interval TTime.Closed (dayOfMonth v1) (dayOfMonth v2) _ -> Nothing } ruleTraIlIntEIlInt :: Rule ruleTraIlIntEIlInt = Rule { name = "tra il <integer> e il <integer> (interval)" , pattern = [ regex "tra( (il|l'))?" , Predicate isDOMInteger , regex "e( (il|l'))?" , Predicate isDOMInteger ] , prod = \tokens -> case tokens of (_:token1:_:token2:_) -> do v1 <- getIntValue token1 v2 <- getIntValue token2 Token Time <$> interval TTime.Closed (dayOfMonth v1) (dayOfMonth v2) _ -> Nothing } ruleTimeofdayOra :: Rule ruleTimeofdayOra = Rule { name = "<time-of-day> ora" , pattern = [ regex "or[ea]" , Predicate isATimeOfDay ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> tt $ notLatent td _ -> Nothing } ruleNextTime2 :: Rule ruleNextTime2 = Rule { name = "next <time>" , pattern = [ dimension Time , regex "dopo|prossim[ao]" ] , prod = \tokens -> case tokens of (Token Time td:_) -> tt $ predNth 1 False td _ -> Nothing } ruleSantoStefano :: Rule ruleSantoStefano = Rule { name = "santo stefano" , pattern = [ regex "s(anto|\\.) stefano" ] , prod = \_ -> tt $ monthDay 12 26 } ruleIlTime :: Rule ruleIlTime = Rule { name = "il <time>" , pattern = [ regex "il|l'" , Predicate isNotLatent ] , prod = \tokens -> case tokens of (_:x:_) -> Just x _ -> Nothing } ruleFestaDelPap :: Rule ruleFestaDelPap = Rule { name = "festa del papà" , pattern = [ regex "festa del pap(a|à)|(festa di )?s(an|\\.) giuseppe" ] , prod = \_ -> tt $ monthDay 3 19 } ruleEntroIlDuration :: Rule ruleEntroIlDuration = Rule { name = "entro il <duration>" , pattern = [ regex "(entro|durante|per( tutt[ao])?) (il|l[a'])|in|nel(l[a'])?" , dimension TimeGrain ] , prod = \tokens -> case tokens of (_:Token TimeGrain grain:_) -> let from = cycleNth TG.Second 0 to = cycleNth grain 1 in Token Time <$> interval TTime.Open from to _ -> Nothing } ruleDimTimeAlPartofday :: Rule ruleDimTimeAlPartofday = Rule { name = "<dim time> al <part-of-day>" , pattern = [ dimension Time , regex "al|nel(la)?|in|d(i|el(la)?)" , Predicate isAPartOfDay ] , prod = \tokens -> case tokens of (Token Time td1:_:Token Time td2:_) -> Token Time <$> intersect td1 td2 _ -> Nothing } ruleSeason4 :: Rule ruleSeason4 = Rule { name = "season" , pattern = [ regex "(in )?primavera" ] , prod = \_ -> let from = monthDay 3 20 to = monthDay 6 21 in Token Time <$> interval TTime.Open from to } ruleYearLatent2 :: Rule ruleYearLatent2 = Rule { name = "year (latent)" , pattern = [ Predicate $ isIntegerBetween 2101 10000 ] , prod = \tokens -> case tokens of (token:_) -> do v <- getIntValue token tt . mkLatent $ year v _ -> Nothing } ruleNoon :: Rule ruleNoon = Rule { name = "noon" , pattern = [ regex "mezz?ogiorno" ] , prod = \_ -> tt $ hour False 12 } ruleTheDayBeforeYesterday :: Rule ruleTheDayBeforeYesterday = Rule { name = "the day before yesterday" , pattern = [ regex "(l')?altro\\s?ieri" ] , prod = \_ -> tt . cycleNth TG.Day $ - 2 } ruleNextCycle :: Rule ruleNextCycle = Rule { name = "next <cycle> " , pattern = [ regex "((il|la|[nd]el(la)?) )?prossim[oa]" , dimension TimeGrain ] , prod = \tokens -> case tokens of (_:Token TimeGrain grain:_) -> tt $ cycleNth grain 1 _ -> Nothing } ruleDaysOfWeek :: [Rule] ruleDaysOfWeek = mkRuleDaysOfWeek [ ( "Lunedi" , "luned(i|ì)|lun?\\.?" ) , ( "Martedi" , "marted(i|ì)|mar\\.?" ) , ( "Mercoledi", "mercoled(i|ì)|mer\\.?" ) , ( "Giovedi" , "gioved(i|ì)|gio\\.?" ) , ( "Venerdi" , "venerd(i|ì)|ven\\.?" ) , ( "Sabato" , "sabato|sab\\.?" ) , ( "Domenica" , "domenica|dom\\.?" ) ] ruleMonths :: [Rule] ruleMonths = mkRuleMonths [ ( "Gennaio" , "gennaio|genn?\\.?" ) , ( "Febbraio" , "febbraio|febb?\\.?" ) , ( "Marzo" , "marzo|mar\\.?" ) , ( "Aprile" , "aprile|apr\\.?" ) , ( "Maggio" , "maggio|magg?\\.?" ) , ( "Giugno" , "giugno|giu\\.?" ) , ( "Luglio" , "luglio|lug\\.?" ) , ( "Agosto" , "agosto|ago\\.?" ) , ( "Settembre", "settembre|sett?\\.?" ) , ( "Ottobre" , "ottobre|ott\\.?" ) , ( "Novembre" , "novembre|nov\\.?" ) , ( "Dicembre" , "dicembre|dic\\.?" ) ] ruleTheCycleOfTime :: Rule ruleTheCycleOfTime = Rule { name = "the <cycle> of <time>" , pattern = [ regex "il|la" , dimension TimeGrain , regex "del" , dimension Time ] , prod = \tokens -> case tokens of (_:Token TimeGrain grain:_:Token Time td:_) -> tt $ cycleNthAfter True grain 0 td _ -> Nothing } ruleLunch :: Rule ruleLunch = Rule { name = "lunch" , pattern = [ regex "(a )?pranzo" ] , prod = \_ -> let from = hour False 12 to = hour False 14 in Token Time . mkLatent . partOfDay <$> interval TTime.Open from to } 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 (m1:m2:_)):_) -> do d <- parseInt m1 m <- parseInt m2 tt $ monthDay m d _ -> Nothing } ruleGliUltimiNCycle :: Rule ruleGliUltimiNCycle = Rule { name = "gli ultimi <n> <cycle>" , pattern = [ regex "((([nd]el)?le|([nd]e)?gli) )?(scors|ultim)[ei]" , Predicate $ isIntegerBetween 2 9999 , dimension TimeGrain ] , prod = \tokens -> case tokens of (_:token:Token TimeGrain grain:_) -> do v <- getIntValue token tt $ cycleN True grain (- v) _ -> Nothing } ruleAfternoon :: Rule ruleAfternoon = Rule { name = "afternoon" , pattern = [ regex "pomeriggio?" ] , prod = \_ -> let from = hour False 12 to = hour False 19 in Token Time . mkLatent . partOfDay <$> interval TTime.Open from to } rulePartofdayOfDimTime :: Rule rulePartofdayOfDimTime = Rule { name = "<part-of-day> of <dim time>" , pattern = [ Predicate isAPartOfDay , regex "d(i|el)" , dimension Time ] , prod = \tokens -> case tokens of (Token Time td1:_:Token Time td2:_) -> Token Time <$> intersect td1 td2 _ -> Nothing } ruleDimTimeDelMattino :: Rule ruleDimTimeDelMattino = Rule { name = "<dim time> del mattino" , pattern = [ Predicate isATimeOfDay , regex "del mattino" ] , prod = \tokens -> case tokens of (Token Time td:_) -> do let from = hour False 0 to = hour False 12 td2 <- mkLatent . partOfDay <$> interval TTime.Open from to Token Time <$> intersect td td2 _ -> Nothing } ruleMidnight :: Rule ruleMidnight = Rule { name = "midnight" , pattern = [ regex "mez?zanott?e" ] , prod = \_ -> tt $ hour False 0 } ruleChristmasEve :: Rule ruleChristmasEve = Rule { name = "christmas eve" , pattern = [ regex "((al)?la )?vigig?lia( di natale)?" ] , prod = \_ -> tt $ monthDay 12 24 } ruleNthTimeAfterTime :: Rule ruleNthTimeAfterTime = Rule { name = "nth <time> after <time>" , pattern = [ dimension Ordinal , dimension Time , regex "dopo" , 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 } ruleHhhmmTimeofday2 :: Rule ruleHhhmmTimeofday2 = Rule { name = "hh(:|h)mm (time-of-day)" , pattern = [ regex "((?:0?\\d)|(?:1[0-2]))[:h]([0-5]\\d) d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))" ] , prod = \tokens -> case tokens of (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do v1 <- parseInt m1 v2 <- parseInt m2 tt $ hourMinute False (v1 + 12) v2 _ -> Nothing } ruleTimeNotte :: Rule ruleTimeNotte = Rule { name = "<time> notte" , pattern = [ dimension Time , regex "((in|nella|alla) )?nott(e|ata)" ] , prod = \tokens -> case tokens of (Token Time td:_) -> do let td1 = cycleNthAfter False TG.Day 1 td td2 <- interval TTime.Open (hour False 0) (hour False 4) Token Time <$> intersect td1 td2 _ -> Nothing } ruleStasera :: Rule ruleStasera = Rule { name = "stasera" , pattern = [ regex "stasera" ] , prod = \_ -> do let td1 = cycleNth TG.Day 0 td2 <- interval TTime.Open (hour False 18) (hour False 0) Token Time . partOfDay <$> intersect td1 td2 } ruleSeason3 :: Rule ruleSeason3 = Rule { name = "season" , pattern = [ regex "(in )?inverno" ] , prod = \_ -> let from = monthDay 12 21 to = monthDay 3 20 in Token Time <$> interval TTime.Open from to } ruleSeason :: Rule ruleSeason = Rule { name = "season" , pattern = [ regex "(in )?estate" ] , prod = \_ -> let from = monthDay 6 21 to = monthDay 9 23 in Token Time <$> interval TTime.Open from to } ruleIntegerLatentTimeofday :: Rule ruleIntegerLatentTimeofday = Rule { name = "<integer> (latent time-of-day)" , pattern = [ Predicate $ isIntegerBetween 0 24 ] , prod = \tokens -> case tokens of (token:_) -> do v <- getIntValue token tt . mkLatent $ hour False v _ -> Nothing } ruleInThePartofdayOfDimTime :: Rule ruleInThePartofdayOfDimTime = Rule { name = "in the <part-of-day> of <dim time>" , pattern = [ regex "nel(la)?" , Predicate isAPartOfDay , regex "d(i|el)" , dimension Time ] , prod = \tokens -> case tokens of (_:Token Time td1:_:Token Time td2:_) -> Token Time <$> intersect td1 td2 _ -> Nothing } ruleNewYearsEve :: Rule ruleNewYearsEve = Rule { name = "new year's eve" , pattern = [ regex "((la )?vigig?lia di capodanno|san silvestro)" ] , prod = \_ -> tt $ monthDay 12 31 } ruleFerragosto :: Rule ruleFerragosto = Rule { name = "ferragosto" , pattern = [ regex "ferragosto|assunzione" ] , prod = \_ -> tt $ monthDay 8 15 } ruleDurationAgo :: Rule ruleDurationAgo = Rule { name = "<duration> ago" , pattern = [ dimension Duration , regex "fa" ] , prod = \tokens -> case tokens of (_:Token Duration dd:_) -> tt $ durationAgo dd _ -> Nothing } ruleTimeNotte2 :: Rule ruleTimeNotte2 = Rule { name = "<time> notte" , pattern = [ regex "((nella|alla) )?nott(e|ata)( d(i|el))" , dimension Time ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> do let td1 = cycleNthAfter False TG.Day 1 td td2 <- interval TTime.Open (hour False 0) (hour False 4) Token Time <$> intersect td1 td2 _ -> Nothing } ruleTimeofdayPrecise :: Rule ruleTimeofdayPrecise = Rule { name = "<time-of-day> precise" , pattern = [ Predicate isATimeOfDay , regex "precise" ] , prod = \tokens -> case tokens of (Token Time td:_) -> tt $ notLatent td _ -> Nothing } ruleHhmmMilitaryTimeofday :: Rule ruleHhmmMilitaryTimeofday = Rule { name = "hhmm (military time-of-day)" , pattern = [ regex "((?:[01]?\\d)|(?:2[0-3]))([0-5]\\d)" ] , prod = \tokens -> case tokens of (Token RegexMatch (GroupMatch (m1:m2:_)):_) -> do h <- parseInt m1 m <- parseInt m2 tt . mkLatent $ hourMinute False h m _ -> Nothing } ruleTheCycleLast :: Rule ruleTheCycleLast = Rule { name = "the <cycle> last" , pattern = [ regex "l'|il|la|[nd]el(la)?" , dimension TimeGrain , regex "(scors|passat)[oa]" ] , prod = \tokens -> case tokens of (_:Token TimeGrain grain:_) -> tt . cycleNth grain $ - 1 _ -> Nothing } ruleFinoAlDatetimeInterval :: Rule ruleFinoAlDatetimeInterval = Rule { name = "fino al <datetime> (interval)" , pattern = [ regex "[fs]ino a(l(l[ae'])?)?" , Predicate isNotLatent ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> let now = cycleNth TG.Second 0 in Token Time <$> interval TTime.Open now td _ -> Nothing } ruleAtTimeofday :: Rule ruleAtTimeofday = Rule { name = "at <time-of-day>" , pattern = [ regex "(al)?l[e']|a" , Predicate isATimeOfDay ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> tt $ notLatent td _ -> Nothing } ruleTheNthTimeOfTime :: Rule ruleTheNthTimeOfTime = Rule { name = "the nth <time> of <time>" , pattern = [ regex "il|l[a']|[nd]el(l[a'])?" , dimension Ordinal , dimension Time , regex "di|del(l[a'])?" , 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 } ruleNthTimeOfTime :: Rule ruleNthTimeOfTime = Rule { name = "nth <time> of <time>" , pattern = [ dimension Ordinal , dimension Time , regex "di|del(l[a'])?" , 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 } ruleDalDatetimeAlDatetimeInterval :: Rule ruleDalDatetimeAlDatetimeInterval = Rule { name = "dal <datetime> al <datetime> (interval)" , pattern = [ regex "da(l(l')?)?" , Predicate isNotLatent , regex "([fs]ino )?a(l(l')?)?" , Predicate isNotLatent ] , prod = \tokens -> case tokens of (_:Token Time td1:_:Token Time td2:_) -> Token Time <$> interval TTime.Closed td1 td2 _ -> Nothing } ruleTimeofdayTimeofdayDayofmonthInterval :: Rule ruleTimeofdayTimeofdayDayofmonthInterval = Rule { name = "<time-of-day> - <time-of-day> <day-of-month> (interval)" , pattern = [ Predicate isATimeOfDay , regex "\\-" , Predicate isATimeOfDay , Predicate isNotLatent ] , prod = \tokens -> case tokens of (Token Time td1:_:Token Time td2:Token Time td3:_) -> do from <- intersect td1 td3 to <- intersect td2 td3 Token Time <$> interval TTime.Closed from to _ -> Nothing } ruleWeekend :: Rule ruleWeekend = Rule { name = "week-end" , pattern = [ regex "week[ -]?end|fine ?settimana|we" ] , prod = \_ -> tt weekend } ruleIlWeekendDelTime :: Rule ruleIlWeekendDelTime = Rule { name = "il week-end del <time>" , pattern = [ regex "il (week[ -]?end|fine ?settimana|we) del" , Predicate $ isGrainOfTime TG.Day ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> do from1 <- intersect (cycleNthAfter False TG.Week 0 td) (dayOfWeek 5) from <- intersect from1 (hour False 18) to1 <- intersect (cycleNthAfter False TG.Week 1 td) (dayOfWeek 1) to <- intersect to1 (hour False 0) Token Time <$> interval TTime.Open from to _ -> Nothing } ruleEomendOfMonth :: Rule ruleEomendOfMonth = Rule { name = "EOM|End of month" , pattern = [ regex "fine del mese" ] , prod = \_ -> tt $ cycleNth TG.Month 1 } ruleCommemorazioneDeiDefunti :: Rule ruleCommemorazioneDeiDefunti = Rule { name = "commemorazione dei defunti" , pattern = [ regex "(((giorno|commemorazione) dei|ai) )?(morti|defunti)" ] , prod = \_ -> tt $ monthDay 11 2 } ruleImmacolataConcezione :: Rule ruleImmacolataConcezione = Rule { name = "immacolata concezione" , pattern = [ regex "(all')?immacolata( concezione)?" ] , prod = \_ -> tt $ monthDay 12 8 } ruleDimTimePartofday :: Rule ruleDimTimePartofday = Rule { name = "<dim 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 } ruleTraIlDatetimeEIlDatetimeInterval :: Rule ruleTraIlDatetimeEIlDatetimeInterval = Rule { name = "tra il <datetime> e il <datetime> (interval)" , pattern = [ regex "tra( il| l')?" , Predicate isATimeOfDay , regex "e( il| l')?" , Predicate isATimeOfDay ] , prod = \tokens -> case tokens of (_:Token Time td1:_:Token Time td2:_) -> Token Time <$> interval TTime.Closed td1 td2 _ -> Nothing } ruleNthTimeAfterTime2 :: Rule ruleNthTimeAfterTime2 = Rule { name = "nth <time> after <time>" , pattern = [ regex "il|l'" , dimension Ordinal , dimension Time , regex "dopo" , 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 } ruleDopoLeTimeofday :: Rule ruleDopoLeTimeofday = Rule { name = "dopo le <time-of-day>" , pattern = [ regex "dopo( l['ea'])?|dal(l['ea'])?" , Predicate isATimeOfDay ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> tt . withDirection TTime.After $ notLatent td _ -> Nothing } ruleDopoTime :: Rule ruleDopoTime = Rule { name = "dopo <time>" , pattern = [ regex "dopo|dal?" , dimension Time ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> tt $ withDirection TTime.After td _ -> Nothing } ruleDalInt :: Rule ruleDalInt = Rule { name = "dal <integer" , pattern = [ regex "dal" , Predicate isDOMInteger ] , prod = \tokens -> case tokens of (_:token:_) -> do v <- getIntValue token tt . withDirection TTime.After $ dayOfMonth v _ -> Nothing } ruleTimeEntroLeTime :: Rule ruleTimeEntroLeTime = Rule { name = "<time> entro le <time>" , pattern = [ dimension Time , regex "entro( l[e'])?|prima d(i|ell['ea])" , Predicate isATimeOfDay ] , prod = \tokens -> case tokens of (Token Time td1:_:Token Time td2:_) -> Token Time . withDirection TTime.Before <$> intersect td1 td2 _ -> Nothing } ruleEntroTime :: Rule ruleEntroTime = Rule { name = "entro <time>" , pattern = [ regex "entro( la)?|prima d(i|ella)" , dimension Time ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> tt $ withDirection TTime.Before td _ -> Nothing } ruleEntroIlInt :: Rule ruleEntroIlInt = Rule { name = "entro il <integer>" , pattern = [ regex "entro il|prima del" , Predicate isDOMInteger ] , prod = \tokens -> case tokens of (_:token:_) -> do v <- getIntValue token tt . withDirection TTime.Before $ dayOfMonth v _ -> Nothing } ruleNextTime :: Rule ruleNextTime = Rule { name = "next <time>" , pattern = [ regex "prossim[ao]" , dimension Time ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> tt $ predNth 1 False td _ -> Nothing } ruleNthTimeOfTime3 :: Rule ruleNthTimeOfTime3 = Rule { name = "nth <time> of <time>" , pattern = [ regex "il|l'" , dimension Ordinal , dimension Time , regex "di|del(l[oa'])|in" , 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 } ruleIlCycleDopoTime :: Rule ruleIlCycleDopoTime = Rule { name = "il <cycle> dopo <time>" , pattern = [ regex "l[a']|il|[nd]el" , dimension TimeGrain , regex "dopo" , dimension Time ] , prod = \tokens -> case tokens of (_:Token TimeGrain grain:_:Token Time td:_) -> tt $ cycleNthAfter False grain 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 "((([nd]e)?i|([nd]el)?le) )?prossim[ei]" , Predicate $ isIntegerBetween 2 9999 , dimension TimeGrain ] , prod = \tokens -> case tokens of (_:token:Token TimeGrain grain:_) -> do v <- getIntValue token tt $ cycleN True grain v _ -> Nothing } ruleMorning :: Rule ruleMorning = Rule { name = "morning" , pattern = [ regex "mattin(ata|[aoe])" ] , prod = \_ -> let from = hour False 4 to = hour False 12 in Token Time . mkLatent . partOfDay <$> interval TTime.Open from to } ruleTheDayofmonth :: Rule ruleTheDayofmonth = Rule { name = "il <day-of-month>" , pattern = [ regex "il|l'" , Predicate isDOMInteger ] , prod = \tokens -> case tokens of (_:token:_) -> do v <- getIntValue token tt $ dayOfMonth v _ -> Nothing } ruleThisPartofday :: Rule ruleThisPartofday = Rule { name = "this <part-of-day>" , pattern = [ regex "(que)?st[oa]|i[nl]|(al|nel)(la)?|la" , Predicate isAPartOfDay ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> Token Time . partOfDay <$> intersect (cycleNth TG.Day 0) td _ -> Nothing } ruleThisCycle :: Rule ruleThisCycle = Rule { name = "this <cycle>" , pattern = [ regex "(in )?quest['oa]|per (il|l['a])" , dimension TimeGrain ] , prod = \tokens -> case tokens of (_:Token TimeGrain grain:_) -> tt $ cycleNth grain 0 _ -> Nothing } ruleThisTime :: Rule ruleThisTime = Rule { name = "this <time>" , pattern = [ regex "quest[oaie']" , dimension Time ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> tt $ predNth 0 False td _ -> Nothing } ruleTwoTimeTokensSeparatedByDi :: Rule ruleTwoTimeTokensSeparatedByDi = Rule { name = "two time tokens separated by `di`" , pattern = [ Predicate isNotLatent , regex "di" , Predicate isNotLatent ] , prod = \tokens -> case tokens of (Token Time td1:_:Token Time td2:_) -> Token Time <$> intersect td1 td2 _ -> Nothing } ruleTimeofdayCirca :: Rule ruleTimeofdayCirca = Rule { name = "<time-of-day> circa" , pattern = [ Predicate isATimeOfDay , regex "circa" ] , prod = \tokens -> case tokens of (Token Time td:_) -> tt $ notLatent td _ -> Nothing } ruleYearLatent :: Rule ruleYearLatent = Rule { name = "year (latent)" , pattern = [ Predicate $ isIntegerBetween (- 10000) (-1) ] , prod = \tokens -> case tokens of (token:_) -> do n <- getIntValue token tt . mkLatent $ year n _ -> Nothing } ruleYesterday :: Rule ruleYesterday = Rule { name = "yesterday" , pattern = [ regex "ieri" ] , prod = \_ -> tt . cycleNth TG.Day $ - 1 } ruleSeason2 :: Rule ruleSeason2 = Rule { name = "season" , pattern = [ regex "(in )?autunno" ] , prod = \_ -> let from = monthDay 9 23 to = monthDay 12 21 in Token Time <$> interval TTime.Open from to } ruleCircaPerLeTimeofday :: Rule ruleCircaPerLeTimeofday = Rule { name = "circa per le <time-of-day>" , pattern = [ regex "(circa )?per( le)?|circa( alle)?|verso( le)?" , Predicate isATimeOfDay ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> tt $ notLatent td _ -> Nothing } ruleVersoPartOfDay :: Rule ruleVersoPartOfDay = Rule { name = "verso <part-of-day>" , pattern = [ regex "verso( la| il)?" , Predicate isAPartOfDay ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> tt $ notLatent td _ -> Nothing } ruleChristmas :: Rule ruleChristmas = Rule { name = "christmas" , pattern = [ regex "((il )?giorno di )?natale" ] , prod = \_ -> tt $ monthDay 12 25 } ruleNight :: Rule ruleNight = Rule { name = "night" , pattern = [ regex "nott(e|ata)" ] , prod = \_ -> do let td1 = cycleNth TG.Day 1 td2 <- interval TTime.Open (hour False 0) (hour False 4) Token Time . partOfDay . mkLatent <$> intersect td1 td2 } ruleOgnissanti :: Rule ruleOgnissanti = Rule { name = "ognissanti" , pattern = [ regex "(tutti i |ognis|festa dei |([ia]l )?giorno dei )santi" ] , prod = \_ -> tt $ monthDay 11 1 } ruleIntegerDelPartOfDay :: Rule ruleIntegerDelPartOfDay = Rule { name = "<integer 0 12> del <part of day>" , pattern = [ Predicate $ isIntegerBetween 0 12 , regex "d(i|el(la)?) (pomeriggio|(sta)?(sera|notte))" ] , prod = \tokens -> case tokens of (Token Numeral NumeralData{TNumeral.value = v}:_) -> tt $ hour False (12 + floor v) _ -> Nothing } ruleOrdinalCycleOfTime :: Rule ruleOrdinalCycleOfTime = Rule { name = "<ordinal> <cycle> of <time>" , pattern = [ dimension Ordinal , dimension TimeGrain , regex "di|del(l[a'])?" , 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 } ruleGliNUltimiCycle :: Rule ruleGliNUltimiCycle = Rule { name = "gli <n> ultimi <cycle>" , pattern = [ regex "([nd]e)?i|([nd]el)?le" , Predicate $ isIntegerBetween 2 9999 , regex "(scors|ultim)[ei]" , dimension TimeGrain ] , prod = \tokens -> case tokens of (_:token:_:Token TimeGrain grain:_) -> do v <- getIntValue token tt $ cycleN True grain (- v) _ -> Nothing } ruleDalleTimeofdayAlleTimeofdayInterval :: Rule ruleDalleTimeofdayAlleTimeofdayInterval = Rule { name = "dalle <time-of-day> alle <time-of-day> (interval)" , pattern = [ regex "da(ll[ae'])?" , Predicate isATimeOfDay , regex "\\-|([fs]ino )?a(ll[ae'])?" , Predicate isATimeOfDay ] , prod = \tokens -> case tokens of (_:Token Time td1:_:Token Time td2:_) -> Token Time <$> interval TTime.Closed td1 td2 _ -> Nothing } ruleEntroLeTimeofday :: Rule ruleEntroLeTimeofday = Rule { name = "entro le <time-of-day>" , pattern = [ regex "entro( l[ea'])?|prima d(i|ell['e])" , dimension Time ] , prod = \tokens -> case tokens of (_:Token Time td:_) -> tt . withDirection TTime.Before $ notLatent td _ -> Nothing } ruleHalloweenDay :: Rule ruleHalloweenDay = Rule { name = "halloween day" , pattern = [ regex "hall?owe?en" ] , prod = \_ -> tt $ monthDay 10 31 } ruleLastDayofweekOfTime :: Rule ruleLastDayofweekOfTime = Rule { name = "last <day-of-week> of <time>" , pattern = [ regex "(([nd]el)?l')?ultim[oa]" , Predicate isADayOfWeek , regex "di|del(l[a'])?" , dimension Time ] , prod = \tokens -> case tokens of (_:Token Time td1:_:Token Time td2:_) -> tt $ predLastOf td1 td2 _ -> Nothing } ruleNameddayDayofmonth :: Rule ruleNameddayDayofmonth = Rule { name = "<named-day> <day-of-month>" , pattern = [ Predicate isADayOfWeek , Predicate isDOMInteger ] , prod = \tokens -> case tokens of (Token Time td:token:_) -> Token Time <$> intersectDOM td token _ -> Nothing } ruleLastDayofweekOfTime2 :: Rule ruleLastDayofweekOfTime2 = Rule { name = "last <day-of-week> of <time>" , pattern = [ regex "(l')ultim[oa]" , Predicate isADayOfWeek , regex "di" , dimension Time ] , prod = \tokens -> case tokens of (_:Token Time td1:_:Token Time td2:_) -> tt $ predLastOf td1 td2 _ -> 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 (m1:m2:m3:_)):_) -> do y <- parseInt m3 m <- parseInt m2 d <- parseInt m1 tt $ yearMonthDay y m d _ -> Nothing } ruleTwoTimeTokensInARow :: Rule ruleTwoTimeTokensInARow = Rule { name = "two time tokens in a row" , pattern = [ Predicate isNotLatent , Predicate isNotLatent ] , prod = \tokens -> case tokens of (Token Time td1:Token Time td2:_) -> Token Time <$> intersect td1 td2 _ -> Nothing } ruleIleNCyclePassatipassate :: Rule ruleIleNCyclePassatipassate = Rule { name = "i|le n <cycle> passati|passate" , pattern = [ regex "([nd]e)?i|([nd]el)?le" , Predicate $ isIntegerBetween 2 9999 , dimension TimeGrain , regex "(scors|passat)[ie]" ] , prod = \tokens -> case tokens of (_:token:Token TimeGrain grain:_) -> do v <- getIntValue token tt $ cycleN True grain (- v) _ -> Nothing } ruleEoyendOfYear :: Rule ruleEoyendOfYear = Rule { name = "EOY|End of year" , pattern = [ regex "fine dell' ?anno" ] , prod = \_ -> tt $ cycleNth TG.Year 1 } ruleTomorrow :: Rule ruleTomorrow = Rule { name = "tomorrow" , pattern = [ regex "domani" ] , prod = \_ -> tt $ cycleNth TG.Day 1 } ruleNextNCycle2 :: Rule ruleNextNCycle2 = Rule { name = "next n <cycle>" , pattern = [ regex "([nd]e)?i|([nd]el)?le" , Predicate $ isIntegerBetween 2 9999 , regex "prossim[ei]" , dimension TimeGrain ] , prod = \tokens -> case tokens of (_:token:_:Token TimeGrain grain:_) -> do v <- getIntValue token tt $ cycleN True grain v _ -> Nothing } ruleProssimiUnitofduration :: Rule ruleProssimiUnitofduration = Rule { name = "prossimi <unit-of-duration>" , pattern = [ regex "((([nd]e)?i|([nd]el)?le) )?prossim[ie]" , dimension TimeGrain ] , prod = \tokens -> case tokens of (_:Token TimeGrain grain:_) -> let from = cycleNth grain 1 to = cycleNth grain 3 in Token Time <$> interval TTime.Closed from to _ -> Nothing } ruleMothersDay :: Rule ruleMothersDay = Rule { name = "Mother's Day" , pattern = [ regex "festa della mamma" ] , prod = \_ -> tt $ nthDOWOfMonth 2 7 5 } ruleFestaDelLavoro :: Rule ruleFestaDelLavoro = Rule { name = "festa del lavoro" , pattern = [ regex "festa del lavoro|(festa|giorno) dei lavoratori" ] , prod = \_ -> tt $ monthDay 5 1 } ruleIntersectByDiDellaDel :: Rule ruleIntersectByDiDellaDel = Rule { name = "intersect by \"di\", \"della\", \"del\"" , pattern = [ Predicate isNotLatent , regex "di|del(la)?" , Predicate isNotLatent ] , prod = \tokens -> case tokens of (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 = \tokens -> case tokens of (Token Time td: Token RegexMatch (GroupMatch (tz:_)): _) -> Token Time <$> inTimezone (Text.toUpper tz) td _ -> Nothing } rules :: [Rule] rules = [ ruleAfternoon , ruleAtTimeofday , ruleChristmas , ruleChristmasEve , ruleCircaPerLeTimeofday , ruleCommemorazioneDeiDefunti , ruleDalDatetimeAlDatetimeInterval , ruleDalleTimeofdayAlleTimeofdayInterval , ruleDatetimeDatetimeInterval , ruleDayOfMonthSt , ruleDayofmonthNamedmonth , ruleDdddMonthInterval , ruleDdmm , ruleDdmmyyyy , ruleDimTimeAlPartofday , ruleDimTimeDelMattino , ruleDimTimePartofday , ruleDopoLeTimeofday , ruleDurationAgo , ruleEntroIlDuration , ruleEntroLeTimeofday , ruleEomendOfMonth , ruleEoyendOfYear , ruleEpifania , ruleEvening , ruleFerragosto , ruleFestaDelLavoro , ruleFestaDelPap , ruleFestaDellaLiberazione , ruleFestaDellaRepubblica , ruleFinoAlDatetimeInterval , ruleGliNUltimiCycle , ruleGliUltimiNCycle , ruleHalloweenDay , ruleHhRelativeminutesDelPomeriggiotimeofday , ruleHhRelativeminutesDelPomeriggiotimeofday2 , ruleHhhmmTimeofday , ruleHhhmmTimeofday2 , ruleHhmmMilitaryTimeofday , ruleHourofdayAndRelativeMinutes , ruleHourofdayIntegerAsRelativeMinutes , ruleHourofdayMinusIntegerAsRelativeMinutes , ruleIlCycleDopoTime , ruleIlDayofmonthDeNamedmonth , ruleIlTime , ruleIleNCyclePassatipassate , ruleInDuration , ruleInNamedmonth , ruleInThePartofdayOfDimTime , ruleInafterDuration , ruleIntegerDelPartOfDay , ruleIntegerLatentTimeofday , ruleIntersectByDiDellaDel , ruleLastCycleOfTime , ruleLastDayofweekOfTime , ruleLastDayofweekOfTime2 , ruleLastTime , ruleLeIdiDiNamedmonth , ruleLunch , ruleMidnight , ruleMorning , ruleMothersDay , ruleNameddayDayofmonth , ruleNewYearsDay , ruleNewYearsEve , ruleNextCycle , ruleNextNCycle , ruleNextNCycle2 , ruleNextTime , ruleNextTime2 , ruleNight , ruleNoon , ruleNthTimeAfterTime , ruleNthTimeAfterTime2 , ruleNthTimeOfTime , ruleNthTimeOfTime2 , ruleNthTimeOfTime3 , ruleOgnissanti , ruleOrdinalCycleOfTime , rulePartofdayOfDimTime , ruleProssimiUnitofduration , ruleRelativeMinutesToIntegerAsHourofday , ruleRightNow , ruleSantoStefano , ruleSeason , ruleSeason2 , ruleSeason3 , ruleSeason4 , ruleStamattina , ruleStanotte , ruleStasera , ruleTheCycleLast , ruleTheCycleNext , ruleTheCycleOfTime , ruleTheDayAfterTomorrow , ruleTheDayBeforeYesterday , ruleTheDayofmonth , ruleTheLastCycle , ruleTheNthTimeOfTime , ruleTheOrdinalCycleOfTime , ruleThisCycle , ruleThisDayofweek , ruleThisPartofday , ruleThisTime , ruleTimeLast , ruleTimeNotte , ruleTimeNotte2 , ruleTimeofdayCirca , ruleTimeofdayOra , ruleTimeofdayPrecise , ruleTimeofdayTimeofdayDayofmonthInterval , ruleTomorrow , ruleTraIlDatetimeEIlDatetimeInterval , ruleTwoTimeTokensInARow , ruleTwoTimeTokensSeparatedByDi , ruleUna , ruleValentinesDay , ruleWeekend , ruleYearLatent , ruleYearLatent2 , ruleYearNotLatent , ruleYesterday , ruleYyyymmdd , ruleHhThreeQuarterDelPomeriggiotimeofday , ruleHhThreeQuarterDelPomeriggiotimeofday2 , ruleHourofdayMinusThreeQuarter , ruleThreeQuarterToIntegerAsHourofday , ruleHourofdayAndThreeQuarter , ruleHourofdayThreeQuarters , ruleHhQuartDelPomeriggiotimeofday , ruleHhQuartDelPomeriggiotimeofday2 , ruleHourofdayMinusQuart , ruleQuartAsHourofday , ruleHourofdayAndAQuart , ruleHourofdayQuart , ruleHhHalfDelPomeriggiotimeofday , ruleHhHalfDelPomeriggiotimeofday2 , ruleHourofdayMinusHalf , ruleHalfToIntegerAsHourofday , ruleHourofdayAndHalf , ruleHourofdayHalf , ruleHhIntegerminutesDelPomeriggiotimeofday , ruleHhIntegerminutesDelPomeriggiotimeofday2 , ruleHourofdayMinusIntegerMinutes , ruleMinutesToIntegerAsHourofday , ruleHourofdayAndIntegerMinutes , ruleHourofdayIntegerMinutes , ruleTimezone , ruleTimeEntroLeTime , ruleImmacolataConcezione , ruleOrdinalQuarter , ruleTheOrdinalQuarter , ruleCycleOrdinalQuarterYear , ruleCycleTheOrdinalTime , ruleCycleNext , ruleDomattina , ruleVersoPartOfDay , ruleEntroIlInt , ruleEntroTime , ruleDalInt , ruleDopoTime , ruleToday , ruleDalIntAlInt , ruleTraIlIntEIlInt , ruleIlWeekendDelTime ] ++ ruleDaysOfWeek ++ ruleMonths