-- 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 OverloadedStrings #-}

module Duckling.Time.NB.Corpus
  ( corpus
  ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Time.Corpus
import Duckling.Time.Types hiding (Month)
import Duckling.TimeGrain.Types hiding (add)
import Duckling.Testing.Types hiding (examples)

corpus :: Corpus
corpus = (testContext {locale = makeLocale NB Nothing}, testOptions, allExamples)

allExamples :: [Example]
allExamples = concat
  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)
             [ "nÃ¥"
             , "akkurat nÃ¥"
             ]
  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)
             [ "i dag"
             ]
  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)
             [ "i gÃ¥r"
             ]
  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)
             [ "i morgen"
             , "i morra"
             ]
  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)
             [ "mandag"
             , "man."
             , "pÃ¥ mandag"
             ]
  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)
             [ "Mandag den 18. februar"
             , "Man, 18 februar"
             ]
  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)
             [ "tirsdag"
             ]
  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)
             [ "torsdag"
             , "tors"
             , "tors."
             ]
  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)
             [ "fredag"
             , "fre"
             , "fre."
             ]
  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)
             [ "lÃ¸rdag"
             , "lÃ¸r"
             , "lÃ¸r."
             ]
  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)
             [ "sÃ¸ndag"
             , "sÃ¸n"
             , "sÃ¸n."
             ]
  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)
             [ "Den fÃ¸rste mars"
             , "1. mars"
             , "Den 1. mars"
             ]
  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)
             [ "3 mars"
             , "den tredje mars"
             , "den 3. mars"
             ]
  , examples (datetime (2013, 10, 30, 0, 0, 0) Day)
             [ "30.10"
             , "30/10"
             , "30-10"
             ]
  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)
             [ "3 mars 2015"
             , "tredje mars 2015"
             , "3. mars 2015"
             , "3-3-2015"
             , "03-03-2015"
             , "3/3/2015"
             , "3/3/15"
             , "2015-3-3"
             , "2015-03-03"
             , "2015.03.03"
             , "03/03/2015"
             , "03.03.2015"
             ]
  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)
             [ "PÃ¥ den 15."
             , "PÃ¥ den 15"
             , "Den 15."
             , "Den femtende"
             ]
  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)
             [ "den 15. februar"
             , "15. februar"
             , "februar 15"
             , "15-02"
             , "15/02"
             , "15.2"
             ]
  , examples (datetime (2013, 11, 27, 0, 0, 0) Day)
             [ "den 27. november"
             , "27. november"
             , "november 27"
             , "27-11"
             , "27/11"
             , "27.11"
             ]
  , examples (datetime (2013, 8, 8, 0, 0, 0) Day)
             [ "8 Aug"
             ]
  , examples (datetime (2014, 10, 0, 0, 0, 0) Month)
             [ "Oktober 2014"
             ]
  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)
             [ "31/10/1974"
             , "31.10.1974"
             , "31/10/74"
             , "31-10-74"
             , "31.10.74"
             , "1974/10/31"
             , "1974-10-31"
             , "1974.10.31"
             ]
  , examples (datetime (2015, 4, 14, 0, 0, 0) Day)
             [ "14april 2015"
             , "April 14, 2015"
             , "fjortende April 15"
             ]
  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)
             [ "neste fredag igjen"
             ]
  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)
             [ "neste mars"
             ]
  , examples (datetime (2014, 3, 0, 0, 0, 0) Month)
             [ "neste mars igjen"
             ]
  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)
             [ "SÃ¸ndag, 10 feb"
             , "SÃ¸ndag 10 Feb"
             ]
  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)
             [ "Ons, Feb13"
             , "Ons feb13"
             ]
  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)
             [ "Mandag, Feb 18"
             , "Man, februar 18"
             ]
  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)
             [ "denne uken"
             ]
  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)
             [ "forrige uke"
             , "sist uke"
             ]
  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)
             [ "neste uke"
             ]
  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)
             [ "forrige mÃ¥ned"
             , "sist mÃ¥ned"
             ]
  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)
             [ "neste mÃ¥ned"
             ]
  , examples (datetime (2013, 1, 1, 0, 0, 0) Quarter)
             [ "dette kvartalet"
             ]
  , examples (datetime (2013, 4, 1, 0, 0, 0) Quarter)
             [ "neste kvartal"
             ]
  , examples (datetime (2013, 7, 1, 0, 0, 0) Quarter)
             [ "tredje kvartal"
             , "3. kvartal"
             ]
  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)
             [ "4. kvartal 2018"
             , "fjerde kvartal 2018"
             ]
  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)
             [ "forrige Ã¥r"
             , "sist Ã¥r"
             ]
  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)
             [ "i fjor"
             ]
  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)
             [ "i Ã¥r"
             , "dette Ã¥r"
             ]
  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)
             [ "neste Ã¥r"
             ]
  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)
             [ "forrige sÃ¸ndag"
             , "sist sÃ¸ndag"
             , "sÃ¸ndag i forrige uke"
             ]
  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)
             [ "forrige tirsdag"
             , "sist tirsdag"
             ]
  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)
             [ "neste tirsdag"
             ]
  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)
             [ "neste onsdag"
             ]
  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)
             [ "onsdag i neste uke"
             , "onsdag neste uke"
             , "neste onsdag igjen"
             ]
  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)
             [ "neste fredag igjen"
             ]
  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)
             [ "mandag denne uken"
             ]
  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)
             [ "tirsdag denne uken"
             ]
  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)
             [ "onsdag denne uken"
             ]
  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)
             [ "i overimorgen"
             , "i overimorra"
             ]
  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)
             [ "i forigÃ¥rs"
             ]
  , examples (datetime (2013, 3, 25, 0, 0, 0) Day)
             [ "siste mandag i mars"
             , "siste mandag i mars"
             ]
  , examples (datetime (2014, 3, 30, 0, 0, 0) Day)
             [ "siste sÃ¸ndag i mars 2014"
             , "siste sÃ¸ndag i mars 2014"
             ]
  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)
             [ "tredje dag i oktober"
             , "tredje dag i Oktober"
             ]
  , examples (datetime (2014, 10, 6, 0, 0, 0) Week)
             [ "fÃ¸rste uke i oktober 2014"
             , "fÃ¸rste uke i Oktober 2014"
             ]
  , examples (datetime (2015, 10, 31, 0, 0, 0) Day)
             [ "siste dag i oktober 2015"
             , "siste dag i Oktober 2015"
             ]
  , examples (datetime (2014, 9, 22, 0, 0, 0) Week)
             [ "siste uke i september 2014"
             , "siste uke i September 2014"
             ]
  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)
             [ "fÃ¸rste tirsdag i oktober"
             , "fÃ¸rste tirsdag i Oktober"
             ]
  , examples (datetime (2014, 9, 16, 0, 0, 0) Day)
             [ "tredje tirsdag i september 2014"
             , "tredje tirsdag i September 2014"
             ]
  , examples (datetime (2014, 10, 1, 0, 0, 0) Day)
             [ "fÃ¸rste onsdag i oktober 2014"
             , "fÃ¸rste onsdag i Oktober 2014"
             ]
  , examples (datetime (2014, 10, 8, 0, 0, 0) Day)
             [ "andre onsdag i oktober 2014"
             , "andre onsdag i Oktober 2014"
             ]
  , examples (datetime (2013, 2, 13, 3, 0, 0) Hour)
             [ "klokken 3"
             , "klokka 3"
             , "kl. 3"
             ]
  , examples (datetime (2013, 2, 13, 3, 18, 0) Minute)
             [ "3:18"
             ]
  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)
             [ "klokken 15"
             , "klokka 15"
             , "kl. 15"
             , "15h"
             ]
  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)
             [ "ca. kl. 15"
             , "cirka kl. 15"
             , "omkring klokken 15"
             , "omkring klokka 15"
             ]
  , examples (datetime (2013, 2, 13, 17, 0, 0) Hour)
             [ "imorgen klokken 17 sharp"
             , "imorra klokken 17 sharp"
             , "imorgen klokka 17 presis"
             , "imorra klokka 17 presis"
             , "imorgen kl. 17 presis"
             , "imorra kl. 17 presis"
             ]
  , examples (datetime (2013, 2, 12, 15, 15, 0) Minute)
             [ "kvarter over 15"
             , "kvart over 15"
             , "15:15"
             ]
  , examples (datetime (2013, 2, 12, 15, 20, 0) Minute)
             [ "kl. 20 over 15"
             , "klokken 20 over 15"
             , "klokka 20 over 15"
             , "kl. 15:20"
             , "15:20"
             ]
  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)
             [ "15:30"
             ]
  , examples (datetime (2013, 2, 12, 15, 23, 24) Second)
             [ "15:23:24"
             ]
  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)
             [ "kvarter pÃ¥ 12"
             , "kvart pÃ¥ 12"
             , "11:45"
             ]
  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)
             [ "klokken 9 pÃ¥ lÃ¸rdag"
             , "klokka 9 pÃ¥ lÃ¸rdag"
             ]
  , examples (datetime (2014, 7, 18, 19, 0, 0) Minute)
             [ "Fre, Jul 18, 2014 19:00"
             ]
  , examples (datetime (2014, 7, 18, 0, 0, 0) Day)
             [ "Fre, Jul 18"
             , "Jul 18, Fre"
             ]
  , examples (datetime (2014, 9, 20, 19, 30, 0) Minute)
             [ "kl. 19:30, LÃ¸r, 20 sep"
             ]
  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)
             [ "om 1 sekund"
             , "om ett sekund"
             , "om et sekund"
             , "ett sekund fra nÃ¥"
             , "et sekund fra nÃ¥"
             ]
  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)
             [ "om 1 minutt"
             , "om et minutt"
             , "om ett minutt"
             ]
  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)
             [ "om 2 minutter"
             , "om to minutter"
             , "om 2 minutter mer"
             , "om to minutter mer"
             , "2 minutter fra nÃ¥"
             , "to minutter fra nÃ¥"
             ]
  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)
             [ "om 60 minutter"
             ]
  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)
             [ "om en halv time"
             ]
  , examples (datetime (2013, 2, 12, 7, 0, 0) Second)
             [ "om 2,5 time"
             , "om 2 og en halv time"
             , "om to og en halv time"
             ]
  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)
             [ "om Ã©n time"
             , "om 1 time"
             , "om 1t"
             ]
  , examples (datetime (2013, 2, 12, 6, 30, 0) Minute)
             [ "om et par timer"
             ]
  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)
             [ "om 24 timer"
             ]
  , examples (datetime (2013, 2, 13, 4, 0, 0) Hour)
             [ "om en dag"
             ]
  , examples (datetime (2016, 2, 0, 0, 0, 0) Month)
             [ "3 Ã¥r fra i dag"
             ]
  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)
             [ "om 7 dager"
             ]
  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)
             [ "om en uke"
             , "om Ã©n uke"
             ]
  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)
             [ "om ca. en halv time"
             , "om cirka en halv time"
             ]
  , examples (datetime (2013, 2, 5, 4, 0, 0) Hour)
             [ "7 dager siden"
             , "syv dager siden"
             ]
  , examples (datetime (2013, 1, 29, 4, 0, 0) Hour)
             [ "14 dager siden"
             , "fjorten dager siden"
             ]
  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)
             [ "en uke siden"
             , "Ã©n uke siden"
             , "1 uke siden"
             ]
  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)
             [ "3 uker siden"
             , "tre uker siden"
             ]
  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)
             [ "3 mÃ¥neder siden"
             , "tre mÃ¥neder siden"
             ]
  , examples (datetime (2011, 2, 0, 0, 0, 0) Month)
             [ "to Ã¥r siden"
             , "2 Ã¥r siden"
             ]
  , examples (datetime (1954, 0, 0, 0, 0, 0) Year)
             [ "1954"
             ]
  , examples (datetime (2013, 12, 24, 0, 0, 0) Day)
             [ "et Ã¥r etter julaften"
             , "ett Ã¥r etter julaften"
             ]
  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)
             [ "denne sommeren"
             , "den her sommeren"
             ]
  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)
             [ "denne vinteren"
             , "den her vinteren"
             ]
  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)
             [ "1 juledag"
             , "1. juledag"
             , "fÃ¸rste juledag"
             ]
  , examples (datetime (2013, 12, 31, 0, 0, 0) Day)
             [ "nyttÃ¥rsaften"
             ]
  , examples (datetime (2014, 1, 1, 0, 0, 0) Day)
             [ "nyttÃ¥rsdag"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)
             [ "i kveld"
             ]
  , examples (datetimeInterval ((2013, 2, 8, 18, 0, 0), (2013, 2, 11, 0, 0, 0)) Hour)
             [ "forrige helg"
             , "sist helg"
             ]
  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)
             [ "i morgen kveld"
             , "i morra kveld"
             ]
  , examples (datetimeInterval ((2013, 2, 13, 12, 0, 0), (2013, 2, 13, 14, 0, 0)) Hour)
             [ "i morgen middag"
             , "i morra middag"
             ]
  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)
             [ "i gÃ¥r kveld"
             ]
  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)
             [ "denne helgen"
             , "denne helga"
             , "i helga"
             , "i helgen"
             ]
  , examples (datetimeInterval ((2013, 2, 18, 4, 0, 0), (2013, 2, 18, 12, 0, 0)) Hour)
             [ "mandag morgen"
             , "mandag morran"
             ]
  , examples (datetimeInterval ((2013, 12, 24, 0, 0, 0), (2013, 12, 31, 0, 0, 0)) Day)
             [ "i romjulen"
             , "i romjula"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)
             [ "siste 2 sekunder"
             , "siste to sekunder"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)
             [ "neste 3 sekunder"
             , "neste tre sekunder"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)
             [ "siste 2 minutter"
             , "siste to minutter"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)
             [ "neste 3 minutter"
             , "neste tre minutter"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 3, 0, 0), (2013, 2, 12, 4, 0, 0)) Hour)
             [ "siste 1 time"
             , "seneste 1 time"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)
             [ "neste 3 timer"
             , "neste tre timer"
             ]
  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)
             [ "siste 2 dager"
             , "siste to dager"
             , "seneste 2 dager"
             ]
  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)
             [ "neste 3 dager"
             , "neste tre dager"
             ]
  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)
             [ "siste 2 uker"
             , "siste to uker"
             , "seneste to uker"
             ]
  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)
             [ "neste 3 uker"
             , "neste tre uker"
             ]
  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)
             [ "siste 2 mÃ¥neder"
             , "siste to mÃ¥neder"
             , "seneste to mÃ¥neder"
             ]
  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)
             [ "neste 3 mÃ¥neder"
             , "neste tre mÃ¥neder"
             ]
  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)
             [ "siste 2 Ã¥r"
             , "siste to Ã¥r"
             , "seneste 2 Ã¥r"
             ]
  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)
             [ "neste 3 Ã¥r"
             , "neste tre Ã¥r"
             ]
  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)
             [ "13-15 juli"
             , "13-15 Juli"
             , "13 til 15 Juli"
             , "13 juli til 15 juli"
             ]
  , examples (datetimeInterval ((2013, 8, 8, 0, 0, 0), (2013, 8, 13, 0, 0, 0)) Day)
             [ "8 Aug - 12 Aug"
             , "8 Aug - 12 aug"
             , "8 aug - 12 aug"
             , "8 august - 12 august"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 1, 0)) Minute)
             [ "9:30 - 11:00"
             , "9:30 til 11:00"
             ]
  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 11, 1, 0)) Minute)
             [ "fra 9:30 - 11:00 pÃ¥ torsdag"
             , "fra 9:30 til 11:00 pÃ¥ torsdag"
             , "mellom 9:30 og 11:00 pÃ¥ torsdag"
             , "9:30 - 11:00 pÃ¥ torsdag"
             , "9:30 til 11:00 pÃ¥ torsdag"
             , "etter 9:30 men fÃ¸r 11:00 pÃ¥ torsdag"
             , "torsdag fra 9:30 til 11:00"
             , "torsdag mellom 9:30 og 11:00"
             , "fra 9:30 til 11:00 pÃ¥ torsdag"
             ]
  , examples (datetimeInterval ((2013, 2, 14, 9, 0, 0), (2013, 2, 14, 12, 0, 0)) Hour)
             [ "torsdag fra 9 til 11"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 11, 30, 0), (2013, 2, 12, 13, 31, 0)) Minute)
             [ "11:30-13:30"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 26, 0, 0, 0)) Second)
             [ "innenfor 2 uker"
             ]
  , examples (datetimeOpenInterval Before (2013, 2, 12, 14, 0, 0) Hour)
             [ "innen kl. 14"
             , "innen klokken 14"
             , "innen klokka 14"
             ]
  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)
             [ "16h CET"
             , "kl. 16 CET"
             , "klokken 16 CET"
             , "klokka 16 CET"
             ]
  , examples (datetime (2013, 2, 14, 6, 0, 0) Minute)
             [ "torsdag kl. 8:00 GMT"
             , "torsdag kl. 8:00 gmt"
             , "torsdag klokken 8:00 GMT"
             , "torsdag klokka 8:00 GMT"
             , "torsdag klokken 8:00 gmt"
             , "torsdag klokka 8:00 gmt"
             , "torsdag 08:00 GMT"
             , "torsdag 08:00 gmt"
             ]
  , examples (datetime (2013, 2, 12, 14, 0, 0) Hour)
             [ "idag kl. 14"
             , "idag klokken 14"
             , "idag klokka 14"
             , "kl. 14"
             , "klokken 14"
             , "klokka 14"
             ]
  , examples (datetime (2013, 4, 25, 16, 0, 0) Minute)
             [ "25/4 kl. 16:00"
             , "25/4 klokken 16:00"
             , "25/4 klokka 16:00"
             , "25-04 klokken 16:00"
             , "25-04 klokka 16:00"
             , "25-4 kl. 16:00"
             ]
  , examples (datetime (2013, 2, 13, 15, 0, 0) Minute)
             [ "15:00 i morgen"
             , "15:00 i morra"
             , "kl. 15:00 i morgen"
             , "kl. 15:00 i morra"
             , "klokken 15:00 i morgen"
             , "klokken 15:00 i morra"
             , "klokka 15:00 i morgen"
             , "klokka 15:00 i morra"
             ]
  , examples (datetimeOpenInterval After (2013, 2, 12, 14, 0, 0) Hour)
             [ "etter kl. 14"
             , "etter klokken 14"
             , "etter klokka 14"
             ]
  , examples (datetimeOpenInterval After (2013, 2, 17, 4, 0, 0) Hour)
             [ "etter 5 dager"
             , "etter fem dager"
             ]
  , examples (datetime (2013, 2, 17, 4, 0, 0) Hour)
             [ "om 5 dager"
             , "om fem dager"
             ]
  , examples (datetimeOpenInterval After (2013, 2, 13, 14, 0, 0) Hour)
             [ "etter i morgen kl. 14"
             , "etter i morra kl. 14"
             , "etter i morgen klokken 14"
             , "etter i morra klokken 14"
             , "etter i morgen klokka 14"
             , "etter i morra klokka 14"
             , "i morgen etter kl. 14"
             , "i morra etter kl. 14"
             , "i morgen etter klokken 14"
             , "i morra etter klokken 14"
             , "i morgen etter klokka 14"
             , "i morra etter klokka 14"
             ]
  , examples (datetimeOpenInterval Before (2013, 2, 12, 11, 0, 0) Hour)
             [ "fÃ¸r kl. 11"
             , "fÃ¸r klokken 11"
             , "fÃ¸r klokka 11"
             ]
  , examples (datetimeOpenInterval Before (2013, 2, 13, 11, 0, 0) Hour)
             [ "i morgen fÃ¸r kl. 11"
             , "i morra fÃ¸r kl. 11"
             , "i morgen fÃ¸r klokken 11"
             , "i morra fÃ¸r klokken 11"
             , "i morgen fÃ¸r klokka 11"
             , "i morra fÃ¸r klokka 11"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 19, 0, 0)) Hour)
             [ "om ettermiddagen"
             ]
  , examples (datetime (2013, 2, 12, 13, 30, 0) Minute)
             [ "kl. 13:30"
             , "klokken 13:30"
             , "klokka 13:30"
             ]
  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)
             [ "om 15 minutter"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 13, 0, 0), (2013, 2, 12, 17, 0, 0)) Hour)
             [ "etter frokost"
             ]
  , examples (datetime (2013, 2, 12, 10, 30, 0) Minute)
             [ "10:30"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 4, 0, 0), (2013, 2, 12, 12, 0, 0)) Hour)
             [ "denne morgen"
             , "denne morran"
             ]
  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)
             [ "neste mandag"
             ]
  , examples (datetime (2014, 2, 9, 0, 0, 0) Day)
             [ "morsdag"
             ]
  , examples (datetime (2013, 11, 10, 0, 0, 0) Day)
             [ "farsdag"
             ]
  ]


-- 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 NoRebindableSyntax #-}
{-# LANGUAGE OverloadedStrings #-}

module Duckling.Time.NB.Rules
  ( rules
  ) where

import Data.Text (Text)
import Prelude

import Duckling.Dimensions.Types
import Duckling.Duration.Helpers (isGrain)
import Duckling.Numeral.Helpers (parseInt)
import Duckling.Ordinal.Types (OrdinalData(..))
import Duckling.Regex.Types
import Duckling.Time.Helpers
import Duckling.Time.Types (TimeData(..))
import Duckling.Types
import qualified Data.Text as Text
import qualified Duckling.Ordinal.Types as TOrdinal
import qualified Duckling.Time.Types as TTime
import qualified Duckling.TimeGrain.Types as TG

ruleTheDayAfterTomorrow :: Rule
ruleTheDayAfterTomorrow = Rule
  { name = "the day after tomorrow"
  , pattern =
    [ regex "i overimorgen|i overimorra"
    ]
  , prod = \_ -> tt $ cycleNth TG.Day 2
  }

ruleRelativeMinutesTotillbeforeIntegerHourofday :: Rule
ruleRelativeMinutesTotillbeforeIntegerHourofday = Rule
  { name = "relative minutes to|till|before <integer> (hour-of-day)"
  , pattern =
    [ Predicate $ isIntegerBetween 1 59
    , regex "pÃ¥"
    , Predicate isAnHourOfDay
    ]
  , prod = \tokens -> case tokens of
      (token:_:Token Time td:_) -> do
        n <- getIntValue token
        Token Time <$> minutesBefore n td
      _ -> Nothing
  }

ruleRelativeMinutesAfterpastIntegerHourofday :: Rule
ruleRelativeMinutesAfterpastIntegerHourofday = Rule
  { name = "relative minutes after|past <integer> (hour-of-day)"
  , pattern =
    [ Predicate $ isIntegerBetween 1 59
    , regex "over"
    , Predicate isAnHourOfDay
    ]
  , prod = \tokens -> case tokens of
      (token:
       _:
       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:
       _) -> do
        n <- getIntValue token
        tt $ hourMinute True hours 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) _)}:
       token:
       _) -> do
        n <- getIntValue token
        tt $ hourMinute True hours n
      _ -> Nothing
  }

ruleQuarterTotillbeforeIntegerHourofday :: Rule
ruleQuarterTotillbeforeIntegerHourofday = Rule
  { name = "quarter to|till|before <integer> (hour-of-day)"
  , pattern =
    [ regex "(et)? ?(kvart)(er)? *pÃ¥"
    , Predicate isAnHourOfDay
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td:_) -> Token Time <$> minutesBefore 15 td
      _ -> Nothing
  }

ruleQuarterAfterpastIntegerHourofday :: Rule
ruleQuarterAfterpastIntegerHourofday = Rule
  { name = "quarter after|past <integer> (hour-of-day)"
  , pattern =
    [ regex "(et)? ?(kvart)(er)? *over"
    , Predicate isAnHourOfDay
    ]
  , prod = \tokens -> case tokens of
      (_:
       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:
       _) -> tt $ hourMinute True hours 15
      _ -> Nothing
  }

ruleHourofdayQuarter :: Rule
ruleHourofdayQuarter = Rule
  { name = "<hour-of-day> quarter (as relative minutes)"
  , pattern =
    [ Predicate isAnHourOfDay
    , regex "(et)? ?(kvart)(er)?"
    ]
  , prod = \tokens -> case tokens of
      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:_) ->
        tt $ hourMinute True hours 15
      _ -> Nothing
  }

ruleHalfTotillbeforeIntegerHourofday :: Rule
ruleHalfTotillbeforeIntegerHourofday = Rule
  { name = "half to|till|before <integer> (hour-of-day)"
  , pattern =
    [ regex "halv time *pÃ¥|halvtime *pÃ¥|halv"
    , Predicate isAnHourOfDay
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td:_) -> Token Time <$> minutesBefore 30 td
      _ -> Nothing
  }

ruleHalfAfterpastIntegerHourofday :: Rule
ruleHalfAfterpastIntegerHourofday = Rule
  { name = "half after|past <integer> (hour-of-day)"
  , pattern =
    [ regex "halv time *over"
    , Predicate isAnHourOfDay
    ]
  , prod = \tokens -> case tokens of
      (_:
       Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:
       _) -> tt $ hourMinute True hours 30
      _ -> Nothing
  }

ruleHourofdayHalf :: Rule
ruleHourofdayHalf = Rule
  { name = "<hour-of-day> half (as relative minutes)"
  , pattern =
    [ Predicate isAnHourOfDay
    , regex "halv time"
    ]
  , prod = \tokens -> case tokens of
      (Token Time TimeData {TTime.form = Just (TTime.TimeOfDay (Just hours) _)}:_) ->
        tt $ hourMinute True hours 30
      _ -> Nothing
  }

ruleConstitutionDay :: Rule
ruleConstitutionDay = Rule
  { name = "constitution day"
  , pattern =
    [ regex "grunnlovsdag(en)"
    ]
  , prod = \_ -> tt $ monthDay 5 17
  }

ruleValentinesDay :: Rule
ruleValentinesDay = Rule
  { name = "valentine's day"
  , pattern =
    [ regex "valentine'?s?( dag)?"
    ]
  , prod = \_ -> tt $ monthDay 2 14
  }

ruleTheOrdinalCycleOfTime :: Rule
ruleTheOrdinalCycleOfTime = Rule
  { name = "the <ordinal> <cycle> of <time>"
  , pattern =
    [ regex "den"
    , dimension Ordinal
    , dimension TimeGrain
    , regex "av|i|fra"
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->
        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td
      _ -> Nothing
  }

ruleNthTimeOfTime2 :: Rule
ruleNthTimeOfTime2 = Rule
  { name = "nth <time> of <time>"
  , pattern =
    [ regex "den"
    , dimension Ordinal
    , dimension Time
    , regex "af|i"
    , 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
  }

ruleNewYearsDay :: Rule
ruleNewYearsDay = Rule
  { name = "new year's day"
  , pattern =
    [ regex "nyttÃ¥rsdag"
    ]
  , prod = \_ -> tt $ monthDay 1 1
  }

ruleLastTime :: Rule
ruleLastTime = Rule
  { name = "last <time>"
  , pattern =
    [ regex "(siste?|forrige|seneste)"
    , dimension Time
    ]
  , 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 "\\-|til|tilogmed"
    , 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 "kveld(en)?"
    ]
  , prod = \_ ->
      let from = hour False 18
          to = hour False 0
      in Token Time . mkLatent . partOfDay <$>
           interval TTime.Open from to
  }

ruleTheDayofmonthNonOrdinal :: Rule
ruleTheDayofmonthNonOrdinal = Rule
  { name = "the <day-of-month> (non ordinal)"
  , pattern =
    [ regex "den"
    , Predicate isDOMInteger
    ]
  , prod = \tokens -> case tokens of
      (_:token:_) -> do
        v <- getIntValue token
        tt . mkLatent $ dayOfMonth v
      _ -> Nothing
  }

ruleCycleAfterTime :: Rule
ruleCycleAfterTime = Rule
  { name = "<cycle> after <time>"
  , pattern =
    [ dimension TimeGrain
    , regex "etter"
    , 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 "om"
    , dimension Duration
    ]
  , prod = \tokens -> case tokens of
      (_:Token Duration dd:_) ->
        tt $ inDuration dd
      _ -> Nothing
  }

ruleNow :: Rule
ruleNow = Rule
  { name = "now"
  , pattern =
    [ regex "akkurat nÃ¥|nÃ¥|(i )?dette Ã¸yeblikk"
    ]
  , prod = \_ -> tt now
  }

ruleLastCycleOfTime :: Rule
ruleLastCycleOfTime = Rule
  { name = "last <cycle> of <time>"
  , pattern =
    [ regex "siste"
    , dimension TimeGrain
    , regex "av|i"
    , 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 "fra"
    , dimension Time
    , regex "\\-|til|tilogmed"
    , 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 =
    [ regex "([012]?\\d|30|31)(ter|\\.)?"
    , regex "\\-|til"
    , regex "([012]?\\d|30|31)(ter|\\.)?"
    , Predicate isAMonth
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (d1:_)):
       _:
       Token RegexMatch (GroupMatch (d2:_)):
       Token Time td:
       _) -> do
        dd1 <- parseInt d1
        dd2 <- parseInt d2
        dom1 <- intersect (dayOfMonth dd1) td
        dom2 <- intersect (dayOfMonth dd2) td
        Token Time <$> interval TTime.Closed dom1 dom2
      _ -> Nothing
  }

ruleTheCycleAfterTime :: Rule
ruleTheCycleAfterTime = Rule
  { name = "the <cycle> after <time>"
  , pattern =
    [ dimension TimeGrain
    , regex "(en|tet|et)? etter"
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (Token TimeGrain grain:_:Token Time td:_) ->
        tt $ cycleNthAfter False grain 1 td
      _ -> Nothing
  }

ruleTheCycleBeforeTime :: Rule
ruleTheCycleBeforeTime = Rule
  { name = "the <cycle> before <time>"
  , pattern =
    [ dimension TimeGrain
    , regex "(en|tet|et)? fÃ¸r"
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (Token TimeGrain grain:_:Token Time td:_) ->
        tt $ cycleNthAfter False grain (-1) td
      _ -> Nothing
  }

ruleYearLatent2 :: Rule
ruleYearLatent2 = Rule
  { name = "year (latent)"
  , pattern =
    [ Predicate $ isIntegerBetween 2101 10000
    ]
  , prod = \tokens -> case tokens of
      (token:_) -> do
        n <- getIntValue token
        tt . mkLatent $ year n
      _ -> Nothing
  }

ruleTimeAfterNext :: Rule
ruleTimeAfterNext = Rule
  { name = "<time> after next"
  , pattern =
    [ regex "neste"
    , dimension Time
    , regex "igjen"
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td:_) ->
        tt $ predNth 1 True td
      _ -> Nothing
  }

ruleTheIdesOfNamedmonth :: Rule
ruleTheIdesOfNamedmonth = Rule
  { name = "the ides of <named-month>"
  , pattern =
    [ regex "midten af"
    , Predicate isAMonth
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td@TimeData {TTime.form = Just (TTime.Month m)}:_) ->
        Token Time <$>
          intersect (dayOfMonth $ if elem m [3, 5, 7, 10] then 15 else 13) td
      _ -> Nothing
  }

ruleNoon :: Rule
ruleNoon = Rule
  { name = "noon"
  , pattern =
    [ regex "middag|(kl(\\.|okken)?)? tolv"
    ]
  , prod = \_ -> tt $ hour False 12
  }

ruleToday :: Rule
ruleToday = Rule
  { name = "today"
  , pattern =
    [ regex "i dag|idag"
    ]
  , prod = \_ -> tt today
  }

ruleThisnextDayofweek :: Rule
ruleThisnextDayofweek = Rule
  { name = "this|next <day-of-week>"
  , pattern =
    [ regex "(kommende|neste)"
    , Predicate isADayOfWeek
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td:_) ->
        tt $ predNth 0 True td
      _ -> Nothing
  }

ruleTheDayBeforeYesterday :: Rule
ruleTheDayBeforeYesterday = Rule
  { name = "the day before yesterday"
  , pattern =
    [ regex "i forigÃ¥rs"
    ]
  , prod = \_ -> tt . cycleNth TG.Day $ - 2
  }

ruleBetweenTimeofdayAndTimeofdayInterval :: Rule
ruleBetweenTimeofdayAndTimeofdayInterval = Rule
  { name = "between <time-of-day> and <time-of-day> (interval)"
  , pattern =
    [ regex "mellom"
    , Predicate isATimeOfDay
    , regex "og"
    , 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 "neste|kommende"
    , dimension TimeGrain
    ]
  , prod = \tokens -> case tokens of
      (_:Token TimeGrain grain:_) ->
        tt $ cycleNth grain 1
      _ -> Nothing
  }

ruleDaysOfWeek :: [Rule]
ruleDaysOfWeek = mkRuleDaysOfWeek
  [ ( "Mandag"  , "mandag|man\\.?"    )
  , ( "Tirsdag" , "tirsdag|tirs?\\.?" )
  , ( "Onsdag"  , "onsdag|ons\\.?"    )
  , ( "Torsdag" , "torsdag|tors?\\.?" )
  , ( "Fredag"  , "fredag|fre\\.?"    )
  , ( "LÃ¸rdag"  , "lÃ¸rdag|lÃ¸r\\.?"    )
  , ( "SÃ¸ndag"  , "sÃ¸ndag|sÃ¸n\\.?"    )
  ]

ruleMonths :: [Rule]
ruleMonths = mkRuleMonths
  [ ( "Januar"   , "januar|jan\\.?"      )
  , ( "Februar"  , "februar|feb\\.?"     )
  , ( "Mars"     , "mars|mar\\.?"        )
  , ( "April"    , "april|apr\\.?"       )
  , ( "Mai"      , "mai"                 )
  , ( "Juni"     , "juni|jun\\.?"        )
  , ( "Juli"     , "juli|jul\\.?"        )
  , ( "August"   , "august|aug\\.?"      )
  , ( "September", "september|sept?\\.?" )
  , ( "Oktober"  , "oktober|okt\\.?"     )
  , ( "November" , "november|nov\\.?"    )
  , ( "Desember" , "desember|des\\.?"    )
  ]

ruleTheCycleOfTime :: Rule
ruleTheCycleOfTime = Rule
  { name = "the <cycle> of <time>"
  , pattern =
    [ dimension TimeGrain
    , regex "(en|tet|et)? av"
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (Token TimeGrain grain:_:Token Time td:_) ->
        tt $ cycleNthAfter True grain 0 td
      _ -> Nothing
  }

ruleTimeofdayApproximately :: Rule
ruleTimeofdayApproximately = Rule
  { name = "<time-of-day> approximately"
  , pattern =
    [ Predicate isATimeOfDay
    , regex "(cirka|ca\\.|-?ish)"
    ]
  , prod = \tokens -> case tokens of
      (Token Time td:_) -> tt $ notLatent td
      _ -> Nothing
  }

ruleOnDate :: Rule
ruleOnDate = Rule
  { name = "on <date>"
  , pattern =
    [ regex "den|pÃ¥"
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td:_) -> tt $ notLatent td
      _ -> Nothing
  }

ruleDurationFromNow :: Rule
ruleDurationFromNow = Rule
  { name = "<duration> from now"
  , pattern =
    [ dimension Duration
    , regex "fra (i dag|idag|nÃ¥)"
    ]
  , prod = \tokens -> case tokens of
      (Token Duration dd:_) ->
        tt $ inDuration dd
      _ -> Nothing
  }

ruleLunch :: Rule
ruleLunch = Rule
  { name = "lunch"
  , pattern =
    [ regex "(til )?middag"
    ]
  , prod = \_ ->
      let from = hour False 12
          to = hour False 14
      in Token Time . mkLatent . partOfDay <$>
           interval TTime.Open from to
  }

ruleLastCycle :: Rule
ruleLastCycle = Rule
  { name = "last <cycle>"
  , pattern =
    [ regex "siste?|seneste|forrige"
    , 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]\\b|1[0-2])"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (dd:mm:_)):_) -> do
        m <- parseInt mm
        d <- parseInt dd
        tt $ monthDay m d
      _ -> Nothing
  }

ruleAfternoon :: Rule
ruleAfternoon = Rule
  { name = "afternoon"
  , pattern =
    [ regex "ettermiddag(en)?"
    ]
  , prod = \_ ->
      let from = hour False 12
          to = hour False 19
      in Token Time . mkLatent . partOfDay <$>
           interval TTime.Open from to
  }

ruleTimeBeforeLast :: Rule
ruleTimeBeforeLast = Rule
  { name = "<time> before last"
  , pattern =
    [ regex "siste"
    , dimension Time
    , regex "igjen"
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td:_) ->
        tt $ predNth (-2) False td
      _ -> Nothing
  }

ruleNamedmonthDayofmonthOrdinal :: Rule
ruleNamedmonthDayofmonthOrdinal = Rule
  { name = "<named-month> <day-of-month> (ordinal)"
  , pattern =
    [ Predicate isAMonth
    , Predicate isDOMOrdinal
    ]
  , prod = \tokens -> case tokens of
      (Token Time td:token:_) -> Token Time <$> intersectDOM td token
      _ -> Nothing
  }

ruleChristmasEve :: Rule
ruleChristmasEve = Rule
  { name = "christmas eve"
  , pattern =
    [ regex "julaften?"
    ]
  , prod = \_ -> tt $ monthDay 12 24
  }

ruleInduringThePartofday :: Rule
ruleInduringThePartofday = Rule
  { name = "in|during the <part-of-day>"
  , pattern =
    [ regex "om|i"
    , 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 "etter"
    , 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 "etter"
    , 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
        v <- getIntValue token
        tt . mkLatent $ hour False v
      _ -> Nothing
  }

ruleDayofmonthOrdinalOfNamedmonth :: Rule
ruleDayofmonthOrdinalOfNamedmonth = Rule
  { name = "<day-of-month> (ordinal) of <named-month>"
  , pattern =
    [ Predicate isDOMOrdinal
    , regex "av|i"
    , 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 "(etter|fra)"
    , Predicate isATimeOfDay
    , regex "((men )?fÃ¸r)|\\-|tilogmed|til"
    , 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 "presis( kl.| klokken | klokka)?"
    , Predicate isATimeOfDay
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td:_) -> tt $ notLatent td
      _ -> Nothing
  }

ruleInduringThePartofday2 :: Rule
ruleInduringThePartofday2 = Rule
  { name = "in|during the <part-of-day>"
  , pattern =
    [ regex "om|i"
    , Predicate isAPartOfDay
    , regex "en|ten"
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td:_) ->
        tt $ notLatent td
      _ -> Nothing
  }

ruleSeason :: Rule
ruleSeason = Rule
  { name = "season"
  , pattern =
    [ regex "sommer(en)"
    ]
  , prod = \_ ->
      let from = monthDay 6 21
          to = monthDay 9 23
      in Token Time <$> interval TTime.Open from to
  }

ruleBetweenDatetimeAndDatetimeInterval :: Rule
ruleBetweenDatetimeAndDatetimeInterval = Rule
  { name = "between <datetime> and <datetime> (interval)"
  , pattern =
    [ regex "mellom"
    , dimension Time
    , regex "og"
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td1:_:Token Time td2:_) ->
        Token Time <$> interval TTime.Closed td1 td2
      _ -> Nothing
  }

ruleNewYearsEve :: Rule
ruleNewYearsEve = Rule
  { name = "new year's eve"
  , pattern =
    [ regex "nyttÃ¥rsaften?"
    ]
  , prod = \_ -> tt $ monthDay 12 31
  }

ruleDurationAgo :: Rule
ruleDurationAgo = Rule
  { name = "<duration> ago"
  , pattern =
    [ dimension Duration
    , regex "siden"
    ]
  , prod = \tokens -> case tokens of
      (Token Duration dd:_) ->
        tt $ durationAgo dd
      _ -> Nothing
  }

ruleByTheEndOfTime :: Rule
ruleByTheEndOfTime = Rule
  { name = "by the end of <time>"
  , pattern =
    [ regex "i slutten av"
    , 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 "etter jobb"
    ]
  , prod = \_ -> do
      td2 <- interval TTime.Open (hour False 17) (hour False 21)
      Token Time . partOfDay <$> intersect today td2
  }

ruleLastNCycle :: Rule
ruleLastNCycle = Rule
  { name = "last n <cycle>"
  , pattern =
    [ regex "siste?|seneste|forrige"
    , Predicate $ isIntegerBetween 1 9999
    , dimension TimeGrain
    ]
  , prod = \tokens -> case tokens of
      (_:token:Token TimeGrain grain:_) -> do
        v <- getIntValue token
        tt $ cycleN True grain (- v)
      _ -> Nothing
  }

ruleChristmasDays :: Rule
ruleChristmasDays = Rule
  { name = "christmas days"
  , pattern =
    [ regex "romjul(a|en)"
    ]
  , prod = \_ ->
      Token Time <$> interval TTime.Open (monthDay 12 24) (monthDay 12 30)
  }

ruleTimeofdaySharp :: Rule
ruleTimeofdaySharp = Rule
  { name = "<time-of-day> sharp"
  , pattern =
    [ Predicate isATimeOfDay
    , regex "(sharp|presis)"
    ]
  , prod = \tokens -> case tokens of
      (Token Time td:_) -> tt $ notLatent td
      _ -> Nothing
  }

ruleWithinDuration :: Rule
ruleWithinDuration = Rule
  { name = "within <duration>"
  , pattern =
    [ regex "innenfor"
    , 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 "midnatt|EOD"
    ]
  , 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 "(omkring|cirka|ca\\.)( kl\\.| klokken | klokka)?"
    , 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 "(engang )?innen|fÃ¸r|opptil"
    , dimension Time
    ]
  , 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 "klokken|klokka|kl.|@"
    , 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 "av|i"
    , 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 td1:Token Time td2:_) ->
        Token Time <$> intersect td1 td2
      _ -> Nothing
  }

ruleWeekend :: Rule
ruleWeekend = Rule
  { name = "week-end"
  , pattern =
    [ regex "((week(\\s|-)?end)|helg)(en|a)?"
    ]
  , prod = \_ -> tt weekend
  }

ruleEomendOfMonth :: Rule
ruleEomendOfMonth = Rule
  { name = "EOM|End of month"
  , pattern =
    [ regex "EOM"
    ]
  , prod = \_ -> tt $ cycleNth TG.Month 1
  }

ruleLastYear :: Rule
ruleLastYear = Rule
  { name = "Last year"
  , pattern =
    [ regex "i fjor"
    ]
  , prod = \_ -> tt . cycleNth TG.Year $ - 1
  }

ruleNthTimeAfterTime2 :: Rule
ruleNthTimeAfterTime2 = Rule
  { name = "nth <time> after <time>"
  , pattern =
    [ regex "den"
    , dimension Ordinal
    , dimension Time
    , regex "etter"
    , 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
  }

ruleNextTime :: Rule
ruleNextTime = Rule
  { name = "next <time>"
  , pattern =
    [ regex "neste|kommende"
    , Predicate isNotLatent
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td:_) ->
        tt $ predNth 0 True td
      _ -> Nothing
  }

ruleOrdinalQuarterYear :: Rule
ruleOrdinalQuarterYear = Rule
  { name = "<ordinal> quarter <year>"
  , pattern =
    [ dimension Ordinal
    , Predicate $ isGrain TG.Quarter
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (Token Ordinal od:_:Token Time td:_) ->
        tt $ cycleNthAfter False TG.Quarter (TOrdinal.value od - 1) td
      _ -> Nothing
  }

ruleYyyymmdd :: Rule
ruleYyyymmdd = Rule
  { name = "yyyy-mm-dd"
  , pattern =
    [ regex "(\\d{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
  }

ruleTheOrdinalCycleAfterTime :: Rule
ruleTheOrdinalCycleAfterTime = Rule
  { name = "the <ordinal> <cycle> after <time>"
  , pattern =
    [ regex "den"
    , dimension Ordinal
    , dimension TimeGrain
    , regex "etter"
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (_:Token Ordinal od:Token TimeGrain grain:_:Token Time td:_) ->
        tt $ cycleNthAfter True grain (TOrdinal.value od - 1) td
      _ -> Nothing
  }

ruleIntersectByOfFromS :: Rule
ruleIntersectByOfFromS = Rule
  { name = "intersect by \"of\", \"from\", \"'s\""
  , pattern =
    [ Predicate isNotLatent
    , regex "i"
    , Predicate isNotLatent
    ]
  , prod = \tokens -> case tokens of
      (Token Time td1:_:Token Time td2:_) ->
        Token Time <$> intersect td1 td2
      _ -> Nothing
  }

ruleNextNCycle :: Rule
ruleNextNCycle = Rule
  { name = "next n <cycle>"
  , pattern =
    [ regex "neste"
    , Predicate $ isIntegerBetween 1 9999
    , dimension TimeGrain
    ]
  , prod = \tokens -> case tokens of
      (_:token:Token TimeGrain grain:_) -> do
        v <- getIntValue token
        tt $ cycleN True grain v
      _ -> Nothing
  }

ruleADuration :: Rule
ruleADuration = Rule
  { name = "a <duration>"
  , pattern =
    [ regex "(om )?en|ett|Ã©n|et"
    , dimension Duration
    ]
  , prod = \tokens -> case tokens of
      (_:Token Duration dd:_) ->
        tt $ inDuration dd
      _ -> Nothing
  }

ruleMorning :: Rule
ruleMorning = Rule
  { name = "morning"
  , pattern =
    [ regex "morgen(en)?|morran"
    ]
  , prod = \_ ->
      let from = hour False 4
          to = hour False 12
      in Token Time . mkLatent . partOfDay <$>
           interval TTime.Open from to
  }

ruleThisPartofday :: Rule
ruleThisPartofday = Rule
  { name = "this <part-of-day>"
  , pattern =
    [ regex "i|denne"
    , Predicate isAPartOfDay
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td:_) -> Token Time . partOfDay <$> intersect today td
      _ -> Nothing
  }

ruleThisCycle :: Rule
ruleThisCycle = Rule
  { name = "this <cycle>"
  , pattern =
    [ regex "denne|dette|i|nÃ¥vÃ¦rende"
    , dimension TimeGrain
    ]
  , prod = \tokens -> case tokens of
      (_:Token TimeGrain grain:_) ->
        tt $ cycleNth grain 0
      _ -> Nothing
  }

ruleThisTime :: Rule
ruleThisTime = Rule
  { name = "this <time>"
  , pattern =
    [ regex "(denne|dette|i|den her)"
    , dimension Time
    ]
  , 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 "av|i"
    , Predicate isAMonth
    ]
  , prod = \tokens -> case tokens of
      (token:_:Token Time td:_) -> Token Time <$> intersectDOM td token
      _ -> Nothing
  }

ruleAfterLunch :: Rule
ruleAfterLunch = Rule
  { name = "after lunch"
  , pattern =
    [ regex "etter (frokost|middag|lunsj|lunch)"
    ]
  , prod = \_ -> do
      td2 <- interval TTime.Open (hour False 13) (hour False 17)
      Token Time . partOfDay <$> intersect today td2
  }

ruleOnANamedday :: Rule
ruleOnANamedday = Rule
  { name = "on a named-day"
  , pattern =
    [ regex "pÃ¥ en"
    , Predicate isADayOfWeek
    ]
  , prod = \tokens -> case tokens of
      (_:x:_) -> Just x
      _ -> Nothing
  }

ruleYearLatent :: Rule
ruleYearLatent = Rule
  { name = "year (latent)"
  , pattern =
    [ Predicate $ 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 "i gÃ¥r|igÃ¥r"
    ]
  , prod = \_ -> tt . cycleNth TG.Day $ - 1
  }

ruleSeason2 :: Rule
ruleSeason2 = Rule
  { name = "season"
  , pattern =
    [ regex "vinter(en)"
    ]
  , prod = \_ ->
      let from = monthDay 12 21
          to = monthDay 3 20
      in Token Time <$> interval TTime.Open from to
  }

ruleAfterTimeofday :: Rule
ruleAfterTimeofday = Rule
  { name = "after <time-of-day>"
  , pattern =
    [ regex "(engang )?etter"
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td:_) ->
        tt $ withDirection TTime.After td
      _ -> Nothing
  }

ruleChristmas :: Rule
ruleChristmas = Rule
  { name = "christmas"
  , pattern =
    [ regex "((1\\.?)|fÃ¸rste)? ?juledag"
    ]
  , prod = \_ -> tt $ monthDay 12 25
  }

ruleNight :: Rule
ruleNight = Rule
  { name = "night"
  , pattern =
    [ regex "natt(en)?"
    ]
  , prod = \_ ->
      let from = hour False 0
          to = hour False 4
      in Token Time . mkLatent . partOfDay <$>
           interval TTime.Open from to
  }

ruleDayofmonthOrdinal :: Rule
ruleDayofmonthOrdinal = Rule
  { name = "<day-of-month> (ordinal)"
  , pattern =
    [ Predicate isDOMOrdinal
    ]
  , prod = \tokens -> case tokens of
      (Token Ordinal OrdinalData{TOrdinal.value = v}:_) ->
        tt . mkLatent $ dayOfMonth v
      _ -> Nothing
  }

ruleOrdinalCycleAfterTime :: Rule
ruleOrdinalCycleAfterTime = Rule
  { name = "<ordinal> <cycle> after <time>"
  , pattern =
    [ dimension Ordinal
    , dimension TimeGrain
    , regex "etter"
    , 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 "av|i|fra"
    , 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
  }

ruleHhmm :: Rule
ruleHhmm = Rule
  { name = "hh:mm"
  , pattern =
    [ regex "((?:[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 $ hourMinute False h m
      _ -> Nothing
  }

rule2400 :: Rule
rule2400 = Rule
  { name = "24:00"
  , pattern =
    [ regex "24[.:]00"
    ]
  , prod = \_ -> tt $ hourMinute False 24 00
  }

ruleDmm :: Rule
ruleDmm = Rule
  { name = "d/mm"
  , pattern =
    [ regex "([1-9])[\\/\\.\\-]([1-9]\\b|1[0-2]\\b)"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (dd:mm:_)):_) -> do
        d <- parseInt dd
        m <- parseInt mm
        tt $ monthDay m d
      _ -> Nothing
  }

ruleDDm :: Rule
ruleDDm = Rule
  { name = "dd/m"
  , pattern =
    [ regex "([0-2]\\d|3[01])[\\/\\.\\-]([1-9])"
    ]
  , prod = \tokens -> case tokens of
      (Token RegexMatch (GroupMatch (dd:mm:_)):_) -> do
        d <- parseInt dd
        m <- parseInt mm
        tt $ monthDay m d
      _ -> Nothing
  }

ruleDdDotMm :: Rule
ruleDdDotMm = Rule
  { name = "dd.mm"
  , pattern =
    [ regex "(2[5-9]|3[01])\\.(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
  }

ruleTonight :: Rule
ruleTonight = Rule
  { name = "tonight"
  , pattern =
    [ regex "i kveld"
    ]
  , prod = \_ -> do
      td2 <- interval TTime.Open (hour False 18) (hour False 0)
      Token Time . partOfDay <$> intersect today td2
  }

ruleYear :: Rule
ruleYear = Rule
  { name = "year"
  , pattern =
    [ Predicate $ isIntegerBetween 1000 2100
    ]
  , prod = \tokens -> case tokens of
      (token:_) -> do
        n <- getIntValue token
        tt $ year n
      _ -> Nothing
  }

ruleHalloweenDay :: Rule
ruleHalloweenDay = Rule
  { name = "halloween day"
  , pattern =
    [ regex "hall?owe?en"
    ]
  , prod = \_ -> tt $ monthDay 10 31
  }

ruleNamedmonthDayofmonthNonOrdinal :: Rule
ruleNamedmonthDayofmonthNonOrdinal = Rule
  { name = "<named-month> <day-of-month> (non ordinal)"
  , pattern =
    [ Predicate isAMonth
    , Predicate isDOMInteger
    ]
  , prod = \tokens -> case tokens of
      (Token Time td:token:_) -> Token Time <$> intersectDOM td token
      _ -> Nothing
  }

ruleAbsorptionOfAfterNamedDay :: Rule
ruleAbsorptionOfAfterNamedDay = Rule
  { name = "absorption of , after named day"
  , pattern =
    [ Predicate isADayOfWeek
    , regex ","
    ]
  , prod = \tokens -> case tokens of
      (x:_) -> Just x
      _ -> Nothing
  }

ruleLastDayofweekOfTime :: Rule
ruleLastDayofweekOfTime = Rule
  { name = "last <day-of-week> of <time>"
  , pattern =
    [ regex "siste"
    , Predicate isADayOfWeek
    , regex "av|i"
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (_:Token Time td1:_:Token Time td2:_) ->
        tt $ predLastOf td1 td2
      _ -> Nothing
  }

ruleFathersDay :: Rule
ruleFathersDay = Rule
  { name = "Father's Day"
  , pattern =
    [ regex "farsdag"
    ]
  , prod = \_ -> tt $ nthDOWOfMonth 2 7 11
  }

ruleCycleBeforeTime :: Rule
ruleCycleBeforeTime = Rule
  { name = "<cycle> before <time>"
  , pattern =
    [ dimension TimeGrain
    , regex "fÃ¸r"
    , 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 "\\-|tilogmed|til"
    , 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 "etter"
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (Token Duration dd:_:Token Time td:_) ->
        tt $ durationAfter dd td
      _ -> Nothing
  }

ruleOrdinalQuarter :: Rule
ruleOrdinalQuarter = Rule
  { name = "<ordinal> quarter"
  , pattern =
    [ dimension Ordinal
    , Predicate $ isGrain TG.Quarter
    ]
  , prod = \tokens -> case tokens of
      (token:_) -> do
        n <- getIntValue token
        tt . cycleNthAfter True TG.Quarter (n - 1) $
          cycleNth TG.Year 0
      _ -> Nothing
  }

ruleTheDayofmonthOrdinal :: Rule
ruleTheDayofmonthOrdinal = Rule
  { name = "the <day-of-month> (ordinal)"
  , pattern =
    [ regex "den"
    , Predicate isDOMOrdinal
    ]
  , prod = \tokens -> case tokens of
      (_:Token Ordinal OrdinalData{TOrdinal.value = v}:_) ->
        tt $ dayOfMonth v
      _ -> Nothing
  }

ruleDurationBeforeTime :: Rule
ruleDurationBeforeTime = Rule
  { name = "<duration> before <time>"
  , pattern =
    [ dimension Duration
    , regex "fÃ¸r"
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (Token Duration dd:_:Token Time td:_) ->
        tt $ durationBefore dd td
      _ -> Nothing
  }

rulePartofdayOfTime :: Rule
rulePartofdayOfTime = Rule
  { name = "<part-of-day> of <time>"
  , pattern =
    [ Predicate isAPartOfDay
    , regex "(en |ten )?den"
    , dimension Time
    ]
  , prod = \tokens -> case tokens of
      (Token Time td1:_:Token Time td2:_) ->
        Token Time <$> intersect td1 td2
      _ -> Nothing
  }

ruleEoyendOfYear :: Rule
ruleEoyendOfYear = Rule
  { name = "EOY|End of year"
  , pattern =
    [ regex "EOY"
    ]
  , prod = \_ -> tt $ cycleNth TG.Year 1
  }

ruleTomorrow :: Rule
ruleTomorrow = Rule
  { name = "tomorrow"
  , pattern =
    [ regex "i morgen|imorgen|i morra|imorra"
    ]
  , prod = \_ -> tt $ cycleNth TG.Day 1
  }

ruleMothersDay :: Rule
ruleMothersDay = Rule
  { name = "Mother's Day"
  , pattern =
    [ regex "morsdag"
    ]
  , prod = \_ -> tt $ nthDOWOfMonth 2 7 2
  }

ruleTimeofdayOclock :: Rule
ruleTimeofdayOclock = Rule
  { name = "<time-of-day> o'clock"
  , pattern =
    [ Predicate isATimeOfDay
    , regex "h"
    ]
  , prod = \tokens -> case tokens of
      (Token Time td:_) ->
        tt $ notLatent td
      _ -> Nothing
  }

ruleDayofmonthordinalNamedmonthYear :: Rule
ruleDayofmonthordinalNamedmonthYear = Rule
  { name = "<day-of-month>(ordinal) <named-month> year"
  , pattern =
    [ Predicate isDOMOrdinal
    , Predicate isAMonth
    , regex "(\\d{2,4})"
    ]
  , prod = \tokens -> case tokens of
      (token:
       Token Time td:
       Token RegexMatch (GroupMatch (match:_)):
       _) -> do
         y <- parseInt match
         dom <- intersectDOM td token
         Token Time <$> intersect dom (year y)
      _ -> 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 False h m s
      _ -> Nothing
  }

ruleTimezone :: Rule
ruleTimezone = Rule
  { name = "<time> timezone"
  , pattern =
    [ Predicate $ and . sequence [isNotLatent, isATimeOfDay]
    , regex "\\b(YEKT|YEKST|YAKT|YAKST|WITA|WIT|WIB|WGT|WGST|WFT|WET|WEST|WAT|WAST|VUT|VLAT|VLAST|VET|UZT|UYT|UYST|UTC|ULAT|TVT|TMT|TLT|TKT|TJT|TFT|TAHT|SST|SRT|SGT|SCT|SBT|SAST|SAMT|RET|PYT|PYST|PWT|PST|PONT|PMST|PMDT|PKT|PHT|PHOT|PGT|PETT|PETST|PET|PDT|OMST|OMSST|NZST|NZDT|NUT|NST|NPT|NOVT|NOVST|NFT|NDT|NCT|MYT|MVT|MUT|MST|MSK|MSD|MMT|MHT|MDT|MAWT|MART|MAGT|MAGST|LINT|LHST|LHDT|KUYT|KST|KRAT|KRAST|KGT|JST|IST|IRST|IRKT|IRKST|IRDT|IOT|IDT|ICT|HOVT|HKT|GYT|GST|GMT|GILT|GFT|GET|GAMT|GALT|FNT|FKT|FKST|FJT|FJST|EST|EGT|EGST|EET|EEST|EDT|ECT|EAT|EAST|EASST|DAVT|ChST|CXT|CVT|CST|COT|CLT|CLST|CKT|CHAST|CHADT|CET|CEST|CDT|CCT|CAT|CAST|BTT|BST|BRT|BRST|BOT|BNT|AZT|AZST|AZOT|AZOST|AWST|AWDT|AST|ART|AQTT|ANAT|ANAST|AMT|AMST|ALMT|AKST|AKDT|AFT|AEST|AEDT|ADT|ACST|ACDT)\\b"
    ]
  , prod = \tokens -> case tokens of
      (Token Time td:
       Token RegexMatch (GroupMatch (tz:_)):
       _) -> Token Time <$> inTimezone (Text.toUpper tz) td
      _ -> Nothing
  }

rules :: [Rule]
rules =
  [ ruleADuration
  , ruleAboutTimeofday
  , ruleAbsorptionOfAfterNamedDay
  , ruleAfterDuration
  , ruleAfterLunch
  , ruleAfterTimeofday
  , ruleAfterWork
  , ruleAfternoon
  , ruleAtTimeofday
  , ruleBetweenDatetimeAndDatetimeInterval
  , ruleBetweenTimeofdayAndTimeofdayInterval
  , ruleByTheEndOfTime
  , ruleChristmas
  , ruleChristmasEve
  , ruleChristmasDays
  , ruleConstitutionDay
  , ruleCycleAfterTime
  , ruleCycleBeforeTime
  , ruleDatetimeDatetimeInterval
  , ruleDayofmonthNonOrdinalNamedmonth
  , ruleDayofmonthNonOrdinalOfNamedmonth
  , ruleDayofmonthOrdinal
  , ruleDayofmonthOrdinalOfNamedmonth
  , ruleDayofmonthordinalNamedmonth
  , ruleDayofmonthordinalNamedmonthYear
  , ruleDdmm
  , ruleDdmmyyyy
  , ruleDurationAfterTime
  , ruleDurationAgo
  , ruleDurationBeforeTime
  , ruleDurationFromNow
  , ruleEomendOfMonth
  , ruleEoyendOfYear
  , ruleEvening
  , ruleExactlyTimeofday
  , ruleFathersDay
  , ruleFromDatetimeDatetimeInterval
  , ruleFromTimeofdayTimeofdayInterval
  , ruleHalloweenDay
  , ruleHhmm
  , ruleHhmmss
  , ruleHourofdayIntegerAsRelativeMinutes
  , ruleHourofdayQuarter
  , ruleHourofdayHalf
  , ruleInDuration
  , ruleInduringThePartofday
  , ruleInduringThePartofday2
  , ruleIntersect
  , ruleIntersectBy
  , ruleIntersectByOfFromS
  , ruleLastCycle
  , ruleLastCycleOfTime
  , ruleLastDayofweekOfTime
  , ruleLastNCycle
  , ruleLastTime
  , ruleLastYear
  , ruleLunch
  , ruleMidnighteodendOfDay
  , ruleMonthDdddInterval
  , ruleMorning
  , ruleMothersDay
  , ruleNamedmonthDayofmonthNonOrdinal
  , ruleNamedmonthDayofmonthOrdinal
  , ruleNewYearsDay
  , ruleNewYearsEve
  , ruleNextCycle
  , ruleNextNCycle
  , ruleNextTime
  , ruleNight
  , ruleNoon
  , ruleNow
  , ruleNthTimeAfterTime
  , ruleNthTimeAfterTime2
  , ruleNthTimeOfTime
  , ruleNthTimeOfTime2
  , ruleOnANamedday
  , ruleOnDate
  , ruleOrdinalCycleAfterTime
  , ruleOrdinalCycleOfTime
  , ruleOrdinalQuarter
  , ruleOrdinalQuarterYear
  , rulePartofdayOfTime
  , ruleRelativeMinutesAfterpastIntegerHourofday
  , ruleRelativeMinutesTotillbeforeIntegerHourofday
  , ruleHalfAfterpastIntegerHourofday
  , ruleHalfTotillbeforeIntegerHourofday
  , ruleQuarterAfterpastIntegerHourofday
  , ruleQuarterTotillbeforeIntegerHourofday
  , ruleSeason
  , ruleSeason2
  , ruleTheCycleAfterTime
  , ruleTheCycleBeforeTime
  , ruleTheCycleOfTime
  , ruleTheDayAfterTomorrow
  , ruleTheDayBeforeYesterday
  , ruleTheDayofmonthNonOrdinal
  , ruleTheDayofmonthOrdinal
  , ruleTheIdesOfNamedmonth
  , ruleTheOrdinalCycleAfterTime
  , ruleTheOrdinalCycleOfTime
  , ruleThisCycle
  , ruleThisPartofday
  , ruleThisTime
  , ruleThisnextDayofweek
  , ruleTimeAfterNext
  , ruleTimeBeforeLast
  , ruleTimePartofday
  , ruleTimeofdayApproximately
  , ruleTimeofdayLatent
  , ruleTimeofdayOclock
  , ruleTimeofdaySharp
  , ruleTimeofdayTimeofdayInterval
  , ruleToday
  , ruleTomorrow
  , ruleTonight
  , ruleUntilTimeofday
  , ruleValentinesDay
  , ruleWeekend
  , ruleWithinDuration
  , ruleYear
  , ruleYearLatent
  , ruleYearLatent2
  , ruleYesterday
  , ruleYyyymmdd
  , ruleTimezone
  , rule2400
  , ruleDmm
  , ruleDDm
  , ruleDdDotMm
  ]
  ++ ruleDaysOfWeek
  ++ ruleMonths


-- 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 OverloadedStrings #-}

module Duckling.Time.NL.Corpus
  ( corpus
  , defaultCorpus
  , latentCorpus
  , negativeCorpus
  ) where

import Data.String
import Prelude

import Duckling.Locale
import Duckling.Resolve
import Duckling.Testing.Types hiding (examples)
import Duckling.Time.Corpus
import Duckling.Time.Types hiding (Month)
import Duckling.TimeGrain.Types hiding (add)

context :: Context
context = testContext {locale = makeLocale NL Nothing}

corpus :: Corpus
corpus = (context, testOptions, allExamples)

defaultCorpus :: Corpus
defaultCorpus = (context, testOptions, allExamples ++ custom)
  where
    custom = concat
      [ examples (datetimeHoliday (2013, 12, 5, 0, 0, 0) Day "Sinterklaas")
                 [ "Sinterklaas"
                 , "Pakjesavond"
                 , "Sinterklaasavond"
                 ]
      ]

latentCorpus :: Corpus
latentCorpus = (context, testOptions {withLatent = True}, xs)
  where
    xs = concat
      [ examples (datetimeOpenInterval Before (2013, 2, 12, 8, 0, 0) Hour)
                 [ "voor 8"
                 ]
      ]

negativeCorpus :: NegativeCorpus
negativeCorpus = (context, testOptions, examples)
  where
    examples =
      [ "een hotel"
      , "twee aanbiedingen"
      , "komende 5 agendapunten"
      , "d"
      , "do"
      , "di"
      , "woe"
      , "vr"
      , "zat"
      , "zo"
      , "zon"
      ]

allExamples :: [Example]
allExamples = concat
  [ examples (datetime (2013, 2, 12, 4, 30, 0) Second)
             [ "nu"
             , "direct"
             , "zojuist"
             ]
  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)
             [ "vandaag"
             , "op deze dag"
             ]
  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)
             [ "gisteren"
             ]
  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)
             [ "morgen"
             ]
  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)
             [ "maandag"
             , "ma."
             , "volgende week maandag"
             , "komende maandag"
             , "aanstaande maandag"
             ]
  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)
             [ "Maandag, 18 Feb"
             , "maandag, 18 februari"
             ]
  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)
             [ "dinsdag"
             , "di."
             ]
  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)
             [ "donderdag"
             , "do."
             ]
  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)
             [ "vrijdag"
             , "vr."
             ]
  , examples (datetime (2013, 2, 16, 0, 0, 0) Day)
             [ "zaterdag"
             , "za."
             , "zat."
             ]
  , examples (datetime (2013, 2, 17, 0, 0, 0) Day)
             [ "zondag"
             , "zo."
             , "zon."
             ]
  , examples (datetime (2013, 3, 1, 0, 0, 0) Day)
             [ "1 maart"
             , "op de eerste"
             ]
  , examples (datetime (2013, 3, 3, 0, 0, 0) Day)
             [ "3 maart"
             ]
  , examples (datetime (2015, 3, 3, 0, 0, 0) Day)
             [ "3 maart 2015"
             ]
  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)
             [ "op de 15de"
             ]
  , examples (datetime (2013, 2, 15, 0, 0, 0) Day)
             [ "15 februari"
             , "februari 15"
             , "op de 15de februari"
             , "15-2"
             , "op 15-2"
             ]
  , examples (datetime (2013, 8, 8, 0, 0, 0) Day)
             [ "Aug 8"
             , "8 augustus"
             ]
  , examples (datetime (2014, 10, 0, 0, 0, 0) Month)
             [ "Oktober 2014"
             ]
  , examples (datetime (1974, 10, 31, 0, 0, 0) Day)
             [ "31.10.1974"
             , "31.10.74"
             , "31-10-1974"
             , "31-10-74"
             ]
  , examples (datetime (2015, 4, 14, 0, 0, 0) Day)
             [ "14 april 2015"
             , "April 14, 2015"
             ]
  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)
             [ "volgende week dinsdag"
             ]
  , examples (datetime (2013, 2, 22, 0, 0, 0) Day)
             [ "volgende week vrijdag"
             ]
  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)
             [ "maart"
             ]
  , examples (datetime (2014, 3, 0, 0, 0, 0) Month)
             [ "volgend jaar maart"
             ]
  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)
             [ "zondag, feb 10"
             ]
  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)
             [ "woensdag, 13 februari"
             ]
  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)
             [ "Maandag feb 18"
             , "Maandag 18 februari"
             ]
  , examples (datetime (2013, 2, 11, 0, 0, 0) Week)
             [ "Deze week"
             ]
  , examples (datetime (2013, 2, 4, 0, 0, 0) Week)
             [ "vorige week"
             ]
  , examples (datetime (2013, 2, 18, 0, 0, 0) Week)
             [ "volgende week"
             ]
  , examples (datetime (2013, 1, 0, 0, 0, 0) Month)
             [ "vorige maand"
             ]
  , examples (datetime (2013, 3, 0, 0, 0, 0) Month)
             [ "volgende maand"
             ]
  , examples (datetime (2013, 1, 1, 0, 0, 0) Quarter)
             [ "dit kwartaal"
             ]
  , examples (datetime (2013, 4, 1, 0, 0, 0) Quarter)
             [ "volgende kwartaal"
             ]
  , examples (datetime (2013, 7, 1, 0, 0, 0) Quarter)
             [ "derde kwartaal"
             ]
  , examples (datetime (2018, 10, 1, 0, 0, 0) Quarter)
             [ "4de kwartaal 2018"
             ]
  , examples (datetime (2012, 0, 0, 0, 0, 0) Year)
             [ "vorig jaar"
             ]
  , examples (datetime (2013, 0, 0, 0, 0, 0) Year)
             [ "dit jaar"
             ]
  , examples (datetime (2014, 0, 0, 0, 0, 0) Year)
             [ "volgend jaar"
             ]
  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)
             [ "afgelopen zondag"
             , "vorige week zondag"
             ]
  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)
             [ "vorige dinsdag"
             , "afgelopen dinsdag"
             ]
  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)
             [ "dinsdag over een week"
             ]
  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)
             [ "komende woensdag"
             , "woensdag"
             , "woe."
             ]
  , examples (datetime (2013, 2, 20, 0, 0, 0) Day)
             [ "volgende week woensdag"
             ]
  , examples (datetime (2013, 2, 11, 0, 0, 0) Day)
             [ "deze week maandag"
             ]
  , examples (datetime (2013, 2, 12, 0, 0, 0) Day)
             [ "dinsdag deze week"
             ]
  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)
             [ "deze week woensdag"
             ]
  , examples (datetime (2013, 2, 14, 0, 0, 0) Day)
             [ "overmorgen"
             ]
  , examples (datetime (2013, 2, 10, 0, 0, 0) Day)
             [ "eergisteren"
             ]
  , examples (datetime (2013, 3, 25, 0, 0, 0) Day)
             [ "laatste maandag in maart"
             ]
  , examples (datetime (2014, 3, 30, 0, 0, 0) Day)
             [ "laatste zondag van maart 2014"
             ]
  , examples (datetime (2013, 10, 3, 0, 0, 0) Day)
             [ "derde dag in oktober"
             ]
  , examples (datetime (2014, 10, 6, 0, 0, 0) Week)
             [ "eerste week in oktober 2014"
             ]
  , examples (datetime (2015, 10, 31, 0, 0, 0) Day)
             [ "laatste dag van oktober 2015"
             ]
  , examples (datetime (2014, 9, 22, 0, 0, 0) Week)
             [ "laatste week van september 2014"
             ]
  , examples (datetime (2013, 10, 1, 0, 0, 0) Day)
             [ "eerste dinsdag in oktober"
             ]
  , examples (datetime (2014, 9, 16, 0, 0, 0) Day)
             [ "derde dinsdag in september 2014"
             ]
  , examples (datetime (2014, 10, 1, 0, 0, 0) Day)
             [ "eerste woensdag in oktober 2014"
             ]
  , examples (datetime (2014, 10, 8, 0, 0, 0) Day)
             [ "tweede woensdag in oktober 2014"
             ]
  , examples (datetime (2015, 1, 13, 0, 0, 0) Day)
             [ "derde dinsdag na kerst 2014"
             ]
  , examples (datetime (2013, 2, 12, 4, 0, 0) Hour)
             [ "4 uur in de morgen"
             , "4 uur in de nacht"
             , "4 uur in de ochtend"
             , "4 uur 's ochtends"
             ]
  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)
             [ "3 uur"
             , "om drie uur"
             ]
  , examples (datetime (2013, 2, 12, 3, 18, 0) Minute)
             [ "3:18 in de ochtend"
             , "3:18 's morgens"
             ]
  , examples (datetime (2013, 2, 13, 3, 18, 0) Minute)
             [ "3:18"
             ]
  , examples (datetime (2013, 2, 12, 15, 0, 0) Hour)
             [ "drie uur 's middags"
             , "15 uur"
             , "om drie uur"
             , "rond drie uur"
             , "rond 3 uur 's middags"
             , "om ongeveer drie uur"
             , "ca. 15h"
             , "om circa 15u"
             ]
  , examples (datetime (2013, 4, 1, 18, 0, 0) Hour)
             [ "op 01-04 tegen 18 uur"
             , "op 1 april tegen zes uur 's avonds"
             ]
  , examples (datetime (2013, 2, 13, 17, 0, 0) Hour)
             [ "stipt om 17 uur morgen"
             ]
  , examples (datetime (2013, 2, 12, 14, 15, 0) Minute)
             [ "rond kwart over 2"
             , "kwart over twee uur"
             , "14 uur 15"
             , "15 over 14"
             , "2 uur 15 's middags"
             , "14:15"
             ]
  , examples (datetime (2013, 2, 12, 15, 20, 0) Minute)
             [ "15:20"
             , "10 voor half 4"
             , "10 minuten voor half 4"
             , "3 uur 20 's middags"
             , "twintig over 3"
             ]
  , examples (datetime (2013, 2, 12, 15, 30, 0) Minute)
             [ "om half vier"
             , "15:30"
             , "half vier 's middags"
             , "half 4"
             ]
  , examples (datetime (2013, 2, 13, 3, 30, 0) Minute)
             [ "3:30"
             ]
  , examples (datetime (2013, 2, 12, 11, 45, 0) Minute)
             [ "kwart voor 12"
             , "11:45"
             , "15 minuten voor 12"
             ]
  , examples (datetime (2013, 2, 12, 20, 0, 0) Hour)
             [ "8 uur 's avonds"
             , "vanavond om 8 uur"
             ]
  , examples (datetime (2013, 2, 12, 20, 0, 0) Minute)
             [ "vandaag om 20:00"
             ]
  , examples (datetime (2013, 9, 20, 19, 30, 0) Minute)
             [ "om 19:30 op vr. 20 sept."
             ]
  , examples (datetime (2013, 2, 16, 9, 0, 0) Hour)
             [ "op zaterdag om 9 uur 's morgens"
             ]
  , examples (datetime (2014, 7, 18, 19, 0, 0) Hour)
             [ "Vrij. 18 juli 2014 7 uur 's avonds"
             ]
  , examples (datetime (2014, 7, 18, 0, 0, 0) Day)
             [ "Vr., 18 Juli 2014"
             , "Vrijdag, 18-07-14"
             , "Vrijdag, 18/07/2014"
             , "18de juli 2014"
             ]
  , examples (datetime (2013, 2, 12, 4, 30, 1) Second)
             [ "over een seconde"
             ]
  , examples (datetime (2013, 2, 12, 4, 31, 0) Second)
             [ "in een minuut"
             , "over een minuut"
             ]
  , examples (datetime (2013, 2, 12, 4, 32, 0) Second)
             [ "in 2 minuten"
             ]
  , examples (datetime (2013, 2, 12, 5, 30, 0) Second)
             [ "in 60 minuten"
             ]
  , examples (datetime (2013, 2, 12, 5, 0, 0) Second)
             [ "in 30 minuten"
             ]
  , examples (datetime (2013, 2, 12, 7, 0, 0) Second)
             [ "in 2,5 uur"
             , "in twee en een half uur"
             ]
  , examples (datetime (2013, 2, 12, 5, 30, 0) Minute)
             [ "over een uur"
             , "in een uur"
             ]
  , examples (datetime (2013, 2, 12, 6, 30, 0) Minute)
             [ "over twee uur"
             , "in een paar uur"
             ]
  , examples (datetime (2013, 2, 13, 4, 30, 0) Minute)
             [ "over 24 uur"
             ]
  , examples (datetime (2013, 2, 13, 0, 0, 0) Day)
             [ "morgen"
             ]
  , examples (datetime (2016, 2, 0, 0, 0, 0) Month)
             [ "in 3 jaar"
             ]
  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)
             [ "in 7 dagen"
             ]
  , examples (datetime (2013, 2, 19, 0, 0, 0) Day)
             [ "in 1 week"
             , "over een week"
             ]
  , examples (datetime (2013, 2, 5, 4, 0, 0) Hour)
             [ "7 dagen geleden"
             ]
  , examples (datetime (2013, 1, 29, 4, 0, 0) Hour)
             [ "14 dagen geleden"
             ]
  , examples (datetime (2013, 1, 29, 0, 0, 0) Day)
             [ "twee weken geleden"
             ]
  , examples (datetime (2013, 2, 5, 0, 0, 0) Day)
             [ "een week geleden"
             ]
  , examples (datetime (2013, 1, 22, 0, 0, 0) Day)
             [ "drie weken geleden"
             ]
  , examples (datetime (2012, 11, 12, 0, 0, 0) Day)
             [ "drie maanden geleden"
             ]
  , examples (datetime (2011, 2, 0, 0, 0, 0) Month)
             [ "twee jaar geleden"
             ]
  , examples (datetime (2013, 2, 19, 4, 0, 0) Hour)
             [ "over 7 dagen"
             ]
  , examples (datetime (2013, 12, 25, 0, 0, 0) Day)
             [ "een jaar na kerst"
             ]
  , examples (datetimeInterval ((2013, 6, 21, 0, 0, 0), (2013, 9, 24, 0, 0, 0)) Day)
             [ "deze zomer"
             ]
  , examples (datetimeInterval ((2012, 12, 21, 0, 0, 0), (2013, 3, 21, 0, 0, 0)) Day)
             [ "deze winter"
             ]
  , examples (datetimeHoliday (2013, 12, 25, 0, 0, 0) Day "Kerstmis")
             [ "kerst"
             , "kerstmis"
             ]
  , examples (datetimeHoliday (2013, 12, 31, 0, 0, 0) Day "Oudjaar")
             [ "oudjaar"
             , "oudejaarsavond"
             ]
  , examples (datetimeHoliday (2014, 1, 1, 0, 0, 0) Day "Nieuwjaarsdag")
             [ "nieuwjaarsdag"
             , "nieuwjaar"
             ]
  , examples (datetimeHoliday (2013, 2, 14, 0, 0, 0) Day "Valentijnsdag")
             [ "Valentijnsdag"
             ]
  , examples (datetimeHoliday (2013, 5, 12, 0, 0, 0) Day "Moederdag")
             [ "moederdag"
             ]
  , examples (datetimeHoliday (2013, 6, 16, 0, 0, 0) Day "Vaderdag")
             [ "vaderdag"
             ]
  , examples (datetimeHoliday (2013, 10, 31, 0, 0, 0) Day "Halloween")
             [ "Halloween"
             ]
  , examples (datetimeHoliday (2013, 11, 1, 0, 0, 0) Day "Allerheiligen")
             [ "Allerheiligen"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 18, 0, 0), (2013, 2, 13, 0, 0, 0)) Hour)
             [ "vanavond"
             , "deze avond"
             , "vandaag avond"
             ]
  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)
             [ "morgenavond"
             ]
  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)
             [ "gisteravond"
             , "gisterenavond"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 0, 0, 0), (2013, 2, 12, 12, 0, 0)) Hour)
             [ "vanmorgen"
             ]
  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 13, 12, 0, 0)) Hour)
             [ "morgenochtend"
             ]
  , examples (datetimeInterval ((2013, 2, 11, 0, 0, 0), (2013, 2, 11, 12, 0, 0)) Hour)
             [ "gisterenochtend"
             ]
  , examples (datetimeInterval ((2013, 2, 13, 18, 0, 0), (2013, 2, 14, 0, 0, 0)) Hour)
             [ "morgennacht"
             ]
  , examples (datetimeInterval ((2013, 2, 11, 18, 0, 0), (2013, 2, 12, 0, 0, 0)) Hour)
             [ "gisterennacht"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 12, 0, 0), (2013, 2, 12, 18, 0, 0)) Hour)
             [ "vanmiddag"
             , "deze namiddag"
             , "vandaag namiddag"
             ]
  , examples (datetimeInterval ((2013, 2, 13, 12, 0, 0), (2013, 2, 13, 18, 0, 0)) Hour)
             [ "morgenmiddag"
             , "morgen 's middags"
             , "morgen namiddag"
             ]
  , examples (datetimeInterval ((2013, 2, 11, 12, 0, 0), (2013, 2, 11, 18, 0, 0)) Hour)
             [ "gisterenmiddag"
             , "gistermiddag"
             , "gisterennamiddag"
             ]
  , examples (datetimeInterval ((2013, 2, 15, 18, 0, 0), (2013, 2, 18, 0, 0, 0)) Hour)
             [ "dit weekend"
             , "komend weekend"
             ]
  , examples (datetimeInterval ((2013, 2, 15, 0, 0, 0), (2013, 2, 15, 12, 0, 0)) Hour)
             [ "15 februari 's morgens"
             , "15 februari in de morgen"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 4, 29, 58), (2013, 2, 12, 4, 30, 0)) Second)
             [ "afgelopen 2 seconden"
             , "vorige 2 secondes"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 1), (2013, 2, 12, 4, 30, 4)) Second)
             [ "komende drie secondes"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 4, 28, 0), (2013, 2, 12, 4, 30, 0)) Minute)
             [ "afgelopen 2 minuten"
             , "afgelopen twee minuten"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 4, 31, 0), (2013, 2, 12, 4, 34, 0)) Minute)
             [ "komende 3 minuten"
             , "volgende drie minuten"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 5, 0, 0), (2013, 2, 12, 8, 0, 0)) Hour)
             [ "komende 3 uur"
             , "volgende 3 uur"
             ]
  , examples (datetimeInterval ((2013, 2, 10, 0, 0, 0), (2013, 2, 12, 0, 0, 0)) Day)
             [ "afgelopen 2 dagen"
             , "vorige 2 dagen"
             ]
  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 16, 0, 0, 0)) Day)
             [ "komende 3 dagen"
             , "komende drie dagen"
             ]
  , examples (datetimeInterval ((2013, 2, 13, 0, 0, 0), (2013, 2, 15, 0, 0, 0)) Day)
             [ "komende paar dagen"
             ]
  , examples (datetimeInterval ((2013, 1, 28, 0, 0, 0), (2013, 2, 11, 0, 0, 0)) Week)
             [ "vorige 2 weken"
             , "afgelopen twee weken"
             ]
  , examples (datetimeInterval ((2013, 2, 18, 0, 0, 0), (2013, 3, 11, 0, 0, 0)) Week)
             [ "komende 3 weken"
             ]
  , examples (datetimeInterval ((2012, 12, 0, 0, 0, 0), (2013, 2, 0, 0, 0, 0)) Month)
             [ "vorige 2 maanden"
             , "afgelopen twee maanden"
             ]
  , examples (datetimeInterval ((2013, 3, 0, 0, 0, 0), (2013, 6, 0, 0, 0, 0)) Month)
             [ "komende 3 maanden"
             , "volgende drie maanden"
             ]
  , examples (datetimeInterval ((2011, 0, 0, 0, 0, 0), (2013, 0, 0, 0, 0, 0)) Year)
             [ "vorige 2 jaren"
             , "afgelopen twee jaar"
             ]
  , examples (datetimeInterval ((2014, 0, 0, 0, 0, 0), (2017, 0, 0, 0, 0, 0)) Year)
             [ "komende 3 jaren"
             , "volgende drie jaar"
             ]
  , examples (datetimeInterval ((2013, 7, 13, 0, 0, 0), (2013, 7, 16, 0, 0, 0)) Day)
             [ "13 - 15 juli"
             , "13 t/m 15 juli"
             , "13 - 15 juli"
             , "juli 13 - juli 15"
             , "13 tot en met 15 juli"
             ]
  , examples (datetimeInterval ((2013, 8, 8, 0, 0, 0), (2013, 8, 13, 0, 0, 0)) Day)
             [ "aug 8 - aug 12"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 9, 30, 0), (2013, 2, 12, 11, 1, 0)) Minute)
             [ "9:30 - 11:00"
             ]
  , examples (datetimeInterval ((2013, 2, 14, 9, 30, 0), (2013, 2, 14, 11, 1, 0)) Minute)
             [ "op donderdag om 9:30 - 11:00"
             , "op donderdag tussen 9:30 en 11:00"
             , "donderdag 9:30 - 11:00"
             , "op donderdag na 9:30 maar voor 11:00"
             , "donderdag van 9:30 tot 11:00"
             ]
  , examples (datetimeInterval ((2013, 2, 14, 9, 0, 0), (2013, 2, 14, 12, 0, 0)) Hour)
             [ "donderdag ochtend van 9 tot 11"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 11, 30, 0), (2013, 2, 12, 13, 31, 0)) Minute)
             [ "11:30-13:30"
             ]
  , examples (datetime (2013, 9, 21, 1, 30, 0) Minute)
             [ "1:30 am Za. 21 sept"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 4, 30, 0), (2013, 2, 26, 0, 0, 0)) Second)
             [ "binnen 2 weken"
             ]
  , examples (datetimeOpenInterval Before (2013, 2, 12, 14, 0, 0) Hour)
             [ "tot 2 uur 's middags"
             ]
  , examples (datetimeOpenInterval Before (2013, 3, 1, 0, 0, 0) Month)
             [ "tot het einde van de maand"
             ]
  , examples (datetime (2013, 2, 12, 13, 0, 0) Minute)
             [ "16 uur CET"
             ]
  , examples (datetime (2013, 2, 14, 6, 0, 0) Minute)
             [ "donderdag 8:00 GMT"
             , "donderdag 8:00 gmt"
             ]
  , examples (datetime (2013, 2, 12, 14, 0, 0) Hour)
             [ "vandaag om 14 uur"
             , "om 2 uur"
             ]
  , examples (datetime (2013, 2, 13, 15, 0, 0) Hour)
             [ "morgen om 15 uur"
             ]
  , examples (datetimeOpenInterval After (2013, 2, 12, 14, 0, 0) Hour)
             [ "vanaf 14u"
             , "op zijn vroegst om 14 uur"
             , "twee uur op zijn vroegst"
             ]
  , examples (datetimeOpenInterval Before (2013, 2, 12, 11, 0, 0) Hour)
             [ "tot 11 uur"
             , "tot 11h 's morgens"
             , "tot 11 am in de ochtend"
             , "op zijn laatst om 11 uur"
             , "11 uur op zijn laatst"
             ]
  , examples (datetime (2013, 2, 12, 13, 30, 0) Minute)
             [ "om 13:30 in de middag"
             , "vanmiddag om 1 uur 30"
             , "13:30"
             ]
  , examples (datetime (2013, 2, 12, 4, 45, 0) Second)
             [ "in 15 minuten"
             , "over een kwartier"
             ]
  , examples (datetimeInterval ((2013, 2, 12, 13, 0, 0), (2013, 2, 12, 17, 0, 0)) Hour)
             [ "na de lunch"
             ]
  , examples (datetime (2013, 2, 12, 10, 30, 0) Minute)
             [ "10:30"
             ]
  , examples (datetime (2013, 2, 18, 0, 0, 0) Day)
             [ "komende maandag"
             , "aanstaande maandag"
             ]
  , examples (datetime (2013, 12, 10, 0, 0, 0) Day)
             [ "10-12"
             ]
Â  , examples (datetimeInterval ((2013, 2, 12, 18, 30, 0), (2013, 2, 12, 19, 1, 0)) Minute)
             [ "18:30u - 19:00u"
             , "18:30h tot 19:00h"
             ]
  , examples (datetimeInterval ((2013, 10, 14, 0, 0, 0), (2013, 10, 16, 0, 0, 0)) Day)
             [ "14/10 - 15/10"
             , "van 14/10/2013 tot 15/10/2013"
             ]
  , examples (datetimeInterval ((2018, 10, 14, 0, 0, 0), (2018, 10, 16, 0, 0, 0)) Day)
             [ "14 t/m 15 oktober 2018"
             ]
  , examples (datetime (2013, 10, 10, 0, 0, 0) Day)
             [ "op 10-10"
             , "op 10.10"
             , "10/10"
             ]
  , examples (datetime (2013, 2, 12, 10, 10, 0) Minute)
             [ "om 10:10"
             , "op 10:10"
             ]
  , examples (datetime (2013, 2, 12, 17, 10, 0) Minute)
             [ "17h10"
             , "17u10"
             ]
  , examples (datetimeHoliday (2018, 4, 27, 0, 0, 0) Day "Koningsdag")
           [ "Koningsdag 2018"
           , "koningsdag 2018"
           , "king's day 2018"
           , "King's Day 2018"
           ]
  , examples (datetimeHoliday (2014, 4, 26, 0, 0, 0) Day "Koningsdag")
           [ "Koningsdag 2014"
           , "koningsdag 2014"
           , "King's Day 2014"
           , "king's day 2014"
           ]
  ]