normit.time

The normit.time module provides utilities for normalizing time expressions in text.

class normit.time.After(interval, shift, n=1, interval_included=False, span=None)

Moves the input Interval later by the specified Shift the specified number of times. For example, “a month later” written on 13 Sep 1595 would be represented as:

After(Interval.of(1595, 9, 13), Period(MONTH, 1))

Similarly, “three Aprils after” written on Sat 23 Jan 1993 would be represented as:

After(Interval.of(1993, 1, 23), Repeating(MONTH, YEAR, value=4), n=3)

By default, the resulting interval must not start before the end of the input interval, but when the Shift is a Repeating, interval_included=True will allow the resulting interval to start as early as the start of the input interval.

Parameters:
  • interval (Interval)

  • shift (Shift)

  • n (int)

  • interval_included (bool)

  • span ((<class 'int'>, <class 'int'>))

interval_included: bool = False
n: int = 1
span: (<class 'int'>, <class 'int'>) = None
class normit.time.Afternoon(unit=HOUR, range=DAY, value=12, n_units=6, span=None, *, rrule_kwargs=<factory>)

The repeating interval for meteorological afternoons, i.e., 12:00 until 18:00

Parameters:
  • unit (Unit)

  • range (Unit)

  • value (int)

  • n_units (int)

  • span ((<class 'int'>, <class 'int'>))

  • rrule_kwargs (dict)

n_units: int = 6
range: Unit = (6, 'days')
unit: Unit = (5, 'hours')
value: int = 12
exception normit.time.AnaforaXMLParsingError(entity, trigger_span)

An exception thrown when from_xml is unable to parse a valid Shift, Interval, or Intervals from an Anafora XML

Parameters:
  • entity (Element)

  • trigger_span ((<class 'int'>, <class 'int'>))

class normit.time.Before(interval, shift, n=1, interval_included=False, span=None)

Moves the input Interval earlier by the specified Shift the specified number of times. For example, “a year ago” written on 13 Sep 1595 would be represented as:

Before(Interval.of(1595, 9, 13), Period(YEAR, 1))

Similarly, “two Tuesdays before” written on Sat 23 Jan 1993 would be represented as:

Before(Interval.of(1993, 1, 23), Repeating(DAY, WEEK, value=1), n=2)

By default, the resulting interval must end by the start of the input interval, but when the Shift is a Repeating, interval_included=True will allow the resulting interval to end as late as the end of the input interval.

Parameters:
  • interval (Interval)

  • shift (Shift)

  • n (int)

  • interval_included (bool)

  • span ((<class 'int'>, <class 'int'>))

interval_included: bool = False
n: int = 1
span: (<class 'int'>, <class 'int'>) = None
class normit.time.Between(start_interval, end_interval, start_included=False, end_included=False, span=None)

Selects the interval between a start and an end interval. For example, “since 1994” written on 09 Jan 2007 and interpreted as [1995-01-01T00:00:00, 2007-01-09T00:00:00) would be represented as:

Between(Year(1994), Interval.of(2007, 1, 9))

If start_included=False, starts from the end of start_interval, otherwise, starts from the start. If end_included=False, ends at the start of end_interval, otherwise ends at the end. So “since 1994” written on 09 Jan 2007 and interpreted as [1994-01-01T00:00:00, 2007-01-10T00:00:00) would be represented as:

Between(Year(1994), Interval.of(2007, 1, 9),
        start_included=True, end_included=True)
Parameters:
  • start_interval (Interval)

  • end_interval (Interval)

  • start_included (bool)

  • end_included (bool)

  • span ((<class 'int'>, <class 'int'>))

end: datetime | None
end_included: bool = False
end_interval: Interval
span: (<class 'int'>, <class 'int'>) = None
start: datetime | None
start_included: bool = False
start_interval: Interval
class normit.time.Day(unit=HOUR, range=DAY, value=6, n_units=12, span=None, *, rrule_kwargs=<factory>)

The repeating interval for meteorological daytime, i.e., 06:00 until 06:00

Parameters:
  • unit (Unit)

  • range (Unit)

  • value (int)

  • n_units (int)

  • span ((<class 'int'>, <class 'int'>))

  • rrule_kwargs (dict)

n_units: int = 12
range: Unit = (6, 'days')
unit: Unit = (5, 'hours')
value: int = 6
class normit.time.Evening(unit=HOUR, range=DAY, value=18, n_units=6, span=None, *, rrule_kwargs=<factory>)

The repeating interval for meteorological evenings, i.e., 18:00 until 00:00

Parameters:
  • unit (Unit)

  • range (Unit)

  • value (int)

  • n_units (int)

  • span ((<class 'int'>, <class 'int'>))

  • rrule_kwargs (dict)

n_units: int = 6
range: Unit = (6, 'days')
unit: Unit = (5, 'hours')
value: int = 18
class normit.time.EveryNth(shift, n, span=None)

A repeating interval that retains only every nth interval of another repeating interval. For example, “every other Friday” would be represented as:

EveryNth(Repeating(DAY, WEEK, value=4), n=2)
Parameters:
  • shift (Shift)

  • n (int)

  • span ((<class 'int'>, <class 'int'>))

n: int
shift: Shift
span: (<class 'int'>, <class 'int'>) = None
class normit.time.Fall(unit=MONTH, range=YEAR, value=9, n_units=3, span=None, *, rrule_kwargs=<factory>)

The repeating interval for meteorological falls in the Northern Hemisphere, i.e., September, October, and November

Parameters:
  • unit (Unit)

  • range (Unit)

  • value (int)

  • n_units (int)

  • span ((<class 'int'>, <class 'int'>))

  • rrule_kwargs (dict)

n_units: int = 3
range: Unit = (10, 'years')
unit: Unit = (8, 'months')
value: int = 9
class normit.time.Intersection(intervals, span=None)

Selects the interval in which all given intervals overlap. For example, “Earlier that day” in the context of “We met at 6:00 on 24 Jan 1979. Earlier that day…” would be interpreted as [1979-01-24T00:00:00, 1979-01-24T06:00:00) and represented as:

Intersection([Last(Interval.of(1979, 1, 24, 6), None),
              Interval.of(1979, 1, 24)])
Parameters:
end: datetime | None
intervals: Iterable[Interval]
span: (<class 'int'>, <class 'int'>) = None
start: datetime | None
class normit.time.Interval(start, end)

An interval on the timeline, defined by a starting point (inclusive) and an ending point (exclusive). For example, the expression “1990”, interpreted as the entire year on the timeline, would be represented as:

Interval(start=datetime.datetime.fromisoformat("1990-01-01T00:00:00"),
         end=datetime.datetime.fromisoformat("1991-01-01T00:00:00"))

See the fromisoformat() and of() methods for more concise ways of constructing Intervals.

Parameters:
end: datetime | None
classmethod fromisoformat(string)

Creates an Interval from two dates in ISO 8601 format. For example, “May 1362” may be represented as:

Interval.fromisoformat("1362-03-01T00:00:00 1362-04-01T00:00:00")

The supported formats are the same as datetime.datetime.fromisoformat(), so “May 1362” may be more concisely written as:

Interval.fromisoformat("1362-03-01 1362-04-01")
Parameters:

string (str) – A string containing a starting point and an ending point in ISO 8601 format.

Returns:

An Interval from the starting point to the ending point.

is_defined()
Return type:

bool

isoformat()
Return type:

str

classmethod of(*args)

Creates an Interval that aligns to exactly one calendar unit. For example, “1990” may be represented as:

Interval.of(1990)

And “1 Apr 1918” may be represented as:

Interval.of(1998, 4, 1)
Parameters:

args (int) – A starting point specified by any prefix of the list of time units: year, month, day, hour, minute, second, and microsecond.

Returns:

An Interval that starts from the given starting point, and ends after the smallest time unit specified.

start: datetime | None
class normit.time.Intervals

A collection of intervals on the timeline.

isoformats()
Return type:

list[str]

class normit.time.Last(interval, shift, interval_included=False, span=None)

The closest preceding interval matching the specified Shift. For example, “over the past four days” when spoken on 1 Nov 2024 would be represented as:

Last(Interval.of(2024, 11, 1), Period(DAY, 4))

Similarly, “the previous summer” when spoken on 14 Feb 1912 would be represented as:

Last(Interval.of(1912, 2, 14), Summer())

By default, the resulting interval must end by the start of the input interval, but interval_included=True will allow the resulting interval to end as late as the end of the input interval. For example, if text written on Tue 8 Nov 2016 wrote “arrived on Tuesday” with the intention of “arrived today” (a common practice in news articles), it would be represented as:

Last(Interval.of(2016, 11, 8),
     Repeating(DAY, WEEK, value=1),
     interval_included=True)
Parameters:
  • interval (Interval)

  • shift (Shift)

  • interval_included (bool)

  • span ((<class 'int'>, <class 'int'>))

interval_included: bool = False
span: (<class 'int'>, <class 'int'>) = None
class normit.time.LastN(interval, shift, n, interval_included=False, base_class=<class 'normit.time.Last'>, span=None)

Repeats the Last operation n times. For example, “the previous two summers” when written on 29 May 1264 would be represented as:

LastN(Interval.of(1264, 5, 29), Summer(), n=2)
Parameters:
  • interval (Interval)

  • shift (Shift)

  • n (int)

  • interval_included (bool)

  • base_class (type)

  • span ((<class 'int'>, <class 'int'>))

base_class

alias of Last

span: (<class 'int'>, <class 'int'>) = None
class normit.time.Midnight(unit=MINUTE, range=None, rrule_kwargs=<factory>, span=None, *, value=None, n_units=1)

The repeating interval for midnights, i.e., 00:00 until 00:01

Parameters:
  • unit (Unit)

  • range (Unit)

  • rrule_kwargs (dict)

  • span ((<class 'int'>, <class 'int'>))

  • value (int)

  • n_units (int)

rrule_kwargs: dict
unit: Unit = (4, 'minutes')
class normit.time.Morning(unit=HOUR, range=DAY, value=6, n_units=6, span=None, *, rrule_kwargs=<factory>)

The repeating interval for meteorological mornings, i.e., 06:00 until 12:00

Parameters:
  • unit (Unit)

  • range (Unit)

  • value (int)

  • n_units (int)

  • span ((<class 'int'>, <class 'int'>))

  • rrule_kwargs (dict)

n_units: int = 6
range: Unit = (6, 'days')
unit: Unit = (5, 'hours')
value: int = 6
class normit.time.Next(interval, shift, interval_included=False, span=None)

The closest following interval matching the specified Shift. For example, “the next three hours” when spoken on 1 Nov 2024 would be represented as:

Next(Interval.of(2024, 11, 1), Period(HOUR, 3))

Similarly, “the coming week” when spoken on 14 Feb 1912 would be represented as:

Next(Interval.of(1912, 2, 14), Repeating(WEEK))

By default, the resulting interval must not start before the end of the input interval, but interval_included=True will allow the resulting interval to start as early as the start of the input interval.

Parameters:
  • interval (Interval)

  • shift (Shift)

  • interval_included (bool)

  • span ((<class 'int'>, <class 'int'>))

interval_included: bool = False
span: (<class 'int'>, <class 'int'>) = None
class normit.time.NextN(interval, shift, n, interval_included=False, base_class=<class 'normit.time.Next'>, span=None)

Repeats the Next operation n times. For example, “the next six Fridays” when written on Sat 22 Dec 1714 would be represented as:

NextN(Interval.of(1714, 12, 22), Repeating(DAY, WEEK, value=4), n=6)
Parameters:
  • interval (Interval)

  • shift (Shift)

  • n (int)

  • interval_included (bool)

  • base_class (type)

  • span ((<class 'int'>, <class 'int'>))

base_class

alias of Next

span: (<class 'int'>, <class 'int'>) = None
class normit.time.Night(unit=HOUR, range=DAY, value=0, n_units=6, span=None, *, rrule_kwargs=<factory>)

The repeating interval for meteorological nights, i.e., 00:00 until 06:00

Parameters:
  • unit (Unit)

  • range (Unit)

  • value (int)

  • n_units (int)

  • span ((<class 'int'>, <class 'int'>))

  • rrule_kwargs (dict)

n_units: int = 6
range: Unit = (6, 'days')
unit: Unit = (5, 'hours')
value: int = 0
class normit.time.Noon(unit=MINUTE, range=None, rrule_kwargs=<factory>, span=None, *, value=None, n_units=1)

The repeating interval for noons, i.e., 12:00 until 12:01

Parameters:
  • unit (Unit)

  • range (Unit)

  • rrule_kwargs (dict)

  • span ((<class 'int'>, <class 'int'>))

  • value (int)

  • n_units (int)

rrule_kwargs: dict
unit: Unit = (4, 'minutes')
class normit.time.Nth(interval, shift, index, from_end=False, span=None)

Selects the nth repetition of a Shift starting from one end of the Interval. For example, “second hour of the meeting” for a meeting at 09:30-12:30 on 30 Mar 2007 would be represented as:

Nth(Interval.fromisoformat("2007-03-30T09:30 2007-03-30T12:30"),
    Period(HOUR, 1),
    index=2)

Similarly, “fiftieth day of 2016” would be represented as:

Nth(Year(2016), Repeating(DAY), index=50)

By default, Nth will start from the start and count forward in time, but with from_end=True Nth will instead start from the end and count backward in time. For example, “third-to-last Sunday of 2024” would be represented as:

Nth(Year(2024), Repeating(DAY, WEEK, value=6), index=3, from_end=True)
Parameters:
  • interval (Interval)

  • shift (Shift)

  • index (int)

  • from_end (bool)

  • span ((<class 'int'>, <class 'int'>))

from_end: bool = False
index: int
span: (<class 'int'>, <class 'int'>) = None
class normit.time.NthN(interval, shift, index, n, from_end=False, span=None)

Selects a specified number of nth repetitions of a Shift starting from one end of the Interval. For example, “the second six Mondays of 1997” would be represented as:

NthN(Year(1997), Repeating(DAY, WEEK, value=0), index=2, n=6)
Parameters:
from_end: bool = False
index: int
interval: Interval
n: int
shift: Shift
span: (<class 'int'>, <class 'int'>) = None
class normit.time.Period(unit, n, span=None)

An amount of time, expressed as counts of standard time units. For example, “three months” would be represented as:

Period(MONTH, 3)

Note that periods are independent of the timeline. For example, given only the period expression “10 weeks”, it is impossible to assign time points of the form XXXX-XX-XXTXX:XX:XX to its start and end.

Parameters:
  • unit (Unit)

  • n (int | None)

  • span ((<class 'int'>, <class 'int'>))

n: int | None
span: (<class 'int'>, <class 'int'>) = None
unit: Unit
class normit.time.PeriodSum(periods, span=None)

A period whose duration is the sum of two or more periods. For example, “two years and a day” would be represented as:

PeriodSum([Period(YEAR, 2), Period(DAY, 1)])
Parameters:
  • periods (list[Period])

  • span ((<class 'int'>, <class 'int'>))

periods: list[Period]
span: (<class 'int'>, <class 'int'>) = None
class normit.time.Repeating(unit, range=None, span=None, *, value=None, n_units=1, rrule_kwargs=<factory>)

A Repeating identifies intervals that are named by the calendar system and repeat along the timeline. For example, the set of all months of year “February” would be represented as:

Repeating(MONTH, YEAR, value=2)

While the set of all generic calendar “day” would be represented as:

Repeating(DAY)

Note that for days of the week, the value follows dateutil in assigning Monday as 0, Tuesday as 1, etc. So the set of all days of the week “Thursday” would be represented as:

Repeating(DAY, WEEK, value=3)
Parameters:
  • unit (Unit)

  • range (Unit)

  • span ((<class 'int'>, <class 'int'>))

  • value (int)

  • n_units (int)

  • rrule_kwargs (dict)

n_units: int = 1
range: Unit = None
rrule_kwargs: dict
span: (<class 'int'>, <class 'int'>) = None
unit: Unit
value: int = None
class normit.time.RepeatingIntersection(shifts, span=None)

A repeating interval that is the intersection of two or more repeating intervals. For example, “Saturdays in March” would be represented as:

RepeatingIntersection([Repeating(DAY, WEEK, value=5),
                       Repeating(MONTH, YEAR, value=3)])
Parameters:
shifts: Iterable[Repeating]
span: (<class 'int'>, <class 'int'>) = None
class normit.time.Shift

An object that can be added or subtracted from a time point yielding an Interval

unit: Unit
class normit.time.ShiftUnion(shifts, span=None)

The union of two or more time shifts (periods, repeating intervals, etc.). For example, the set of all days of the week “Mondays and Fridays” would be represented as:

ShiftUnion([Repeating(DAY, WEEK, value=0),
            Repeating(DAY, WEEK, value=4)])
Parameters:
shifts: Iterable[Shift]
span: (<class 'int'>, <class 'int'>) = None
class normit.time.Spring(unit=MONTH, range=YEAR, value=3, n_units=3, span=None, *, rrule_kwargs=<factory>)

The repeating interval for meteorological springs in the Northern Hemisphere, i.e., March, April, and May

Parameters:
  • unit (Unit)

  • range (Unit)

  • value (int)

  • n_units (int)

  • span ((<class 'int'>, <class 'int'>))

  • rrule_kwargs (dict)

n_units: int = 3
range: Unit = (10, 'years')
unit: Unit = (8, 'months')
value: int = 3
class normit.time.Summer(unit=MONTH, range=YEAR, value=6, n_units=3, span=None, *, rrule_kwargs=<factory>)

The repeating interval for meteorological summers in the Northern Hemisphere, i.e., June, July, and August

Parameters:
  • unit (Unit)

  • range (Unit)

  • value (int)

  • n_units (int)

  • span ((<class 'int'>, <class 'int'>))

  • rrule_kwargs (dict)

n_units: int = 3
range: Unit = (10, 'years')
unit: Unit = (8, 'months')
value: int = 6
class normit.time.These(interval, shift, span=None)

Finds the Shift range containing this interval, then finds the Shift units within that range. For example, “Tuesdays and Thursdays in January 2025” would be represented as:

These(Interval.of(2025, 1),
      ShiftUnion([Repeating(DAY, WEEK, value=1),
                  Repeating(DAY, WEEK, value=3)]))
Parameters:
  • interval (Interval)

  • shift (Shift)

  • span ((<class 'int'>, <class 'int'>))

interval: Interval
shift: Shift
span: (<class 'int'>, <class 'int'>) = None
class normit.time.This(interval, shift, span=None)

For period Shifts, creates an interval of the given length centered at the given interval. For example, “these six days” spoken on 29 Apr 1176 would be interpreted as [1176-04-26T12:00:00, 1176-05-02T12:00:00) and represented as:

This(Interval.of(1176, 4, 29), Period(DAY, 6))

For repeating Shifts, finds the Shift range containing this interval, then finds the Shift unit within that range. For example, “this January” spoken on 10 Nov 1037 would be interpreted as [1037-01-01T00:00:00, 1037-02-01T00:00:00) and represented as:

This(Interval.of(1037, 11, 10), Repeating(MONTH, YEAR, value=1))
Parameters:
  • interval (Interval)

  • shift (Shift)

  • span ((<class 'int'>, <class 'int'>))

end: datetime | None
interval: Interval
shift: Shift
span: (<class 'int'>, <class 'int'>) = None
start: datetime | None
class normit.time.Unit(value, names=<not given>, *values, module=None, qualname=None, type=None, start=1, boundary=None)

A named unit of time.

Note that the values of this enum are also available at the module level. So, for example, normit.time.SECOND is an alias for normit.time.Unit.SECOND.

CENTURY = (13, None)
DAY = (6, 'days')
DECADE = (11, None)
HOUR = (5, 'hours')
MICROSECOND = (1, 'microseconds')
MILLISECOND = (2, None)
MINUTE = (4, 'minutes')
MONTH = (8, 'months')
QUARTER_CENTURY = (12, None)
QUARTER_YEAR = (9, None)
SECOND = (3, 'seconds')
WEEK = (7, 'weeks')
YEAR = (10, 'years')
expand(interval, n=1)

Expands an interval to the width of a number of repetitions of this unit.

Parameters:
  • interval (Interval) – The interval to expand

  • n (int) – The number of repetitions

Returns:

The expanded interval

Return type:

Interval

relativedelta(n)

Constructs a dateutil.relativedelta.relativedelta object representing of a number of repetitions of this unit. :param n: The number of repetitions :return: The constructed relativedelta

Return type:

relativedelta

truncate(dt)

Sets all units smaller than this one in the datetime to zero.

Parameters:

dt (datetime) – The datetime to truncate

Returns:

The truncated datetime

Return type:

datetime

class normit.time.Weekend(unit=DAY, range=None, n_units=2, rrule_kwargs=<factory>, span=None, *, value=None)

The repeating interval for weekends, i.e., Saturdays and Sundays

Parameters:
  • unit (Unit)

  • range (Unit)

  • n_units (int)

  • rrule_kwargs (dict)

  • span ((<class 'int'>, <class 'int'>))

  • value (int)

n_units: int = 2
rrule_kwargs: dict
unit: Unit = (6, 'days')
class normit.time.Winter(unit=MONTH, range=YEAR, value=12, n_units=3, span=None, *, rrule_kwargs=<factory>)

The repeating interval for meteorological winters in the Northern Hemisphere, i.e., December, January, and February

Parameters:
  • unit (Unit)

  • range (Unit)

  • value (int)

  • n_units (int)

  • span ((<class 'int'>, <class 'int'>))

  • rrule_kwargs (dict)

n_units: int = 3
range: Unit = (10, 'years')
unit: Unit = (8, 'months')
value: int = 12
class normit.time.Year(digits, n_missing_digits=0, span=None)

The interval from the first second of a year (inclusive) to the first second of the next year (exclusive). For example, the year-long interval “2014” would be represented as:

Year(2014)

Year can also be used to identify decades and centuries by indicating how many digits are missing. For example, the 10-year-long interval “the 1980s” would be represented as:

Year(198, n_missing_digits=1)
Parameters:
  • digits (int)

  • n_missing_digits (int)

  • span ((<class 'int'>, <class 'int'>))

digits: int
end: datetime | None
n_missing_digits: int = 0
span: (<class 'int'>, <class 'int'>) = None
start: datetime | None
class normit.time.YearSuffix(interval, digits, n_missing_digits=0, span=None)

A year-long interval created from the year of another interval and a suffix of digits to replace in that year. For example, the year “96” in the context of a document written in 1993 would be represented as:

YearSuffix(Year(1993), last_digits=96)

YearSuffix can also be used to modify decades and centuries by indicating how many digits are missing. For example, the 10-year-long interval “the 70s” in the context of a document written in 1864 be represented as:

YearSuffix(Year(1864), 7, n_missing_digits=1)
Parameters:
  • interval (Interval)

  • digits (int)

  • n_missing_digits (int)

  • span ((<class 'int'>, <class 'int'>))

digits: int
end: datetime | None
interval: Interval
n_missing_digits: int = 0
span: (<class 'int'>, <class 'int'>) = None
start: datetime | None
normit.time.flatten(shift_or_interval)

Flattens any nested RepeatingIntersection objects.

Parameters:

shift_or_interval (Shift | Interval) – The object to flatten

Returns:

A copy with any nested RepeatingIntersection replaced with a single nested RepeatingIntersection.

Return type:

Shift | Interval

normit.time.from_xml(elem, known_intervals=None)

Reads Intervals and Shifts from SCATE Anafora XML.

Parameters:
  • elem (Element) – The root <data> element of a SCATE Anafora XML document.

  • known_intervals (dict[(<class 'int'>, <class 'int'>), Interval]) – A mapping from character offset spans to Intervals, representing intervals that are already known before parsing begins. The document creation time should be specified with the span (None, None).

Returns:

Intervals and Shifts corresponding to the XML definitions.

Return type:

list[Shift | Interval | Intervals]