Converters

Overview

Converter classes add support for parsing and serializing dates in a variety of formats. A subset of these are calendar converters (undate.converters.calendar), which means they support both parsing and conversion from an alternate calendar to a common Gregorian for comparison across dates.

To parse a date with a supported converter, use the Undate class method parse() and specify the date as a string with the desired format or calendar, e.g.

Undate.parse("2001-05", "EDTF")
Undate.parse("7 Heshvan 5425", "Hebrew")

For converters that support it, you can also serialize a date in a specified format with Undate class method format():

Undate.parse("Rabīʿ ath-Thānī 343", "Islamic").format("EDTF")

BaseDateConverter provides a base class for implementing date converters, which can provide support for parsing and generating dates in different formats. The converter subclass undate.converters.BaseCalendarConverter provides additional functionality needed for calendar conversion.

To add support for a new date converter:

  • Create a new file under undate/converters/
    • For converters with sufficient complexity, you may want to create a submodule; see undate.converters.edtf for an example.

  • Extend BaseDateConverter and implement parse and to_string methods as desired/appropriate for your converter

  • Add unit tests for the new converter in tests/test_converters/

  • Optionally, you may want to create a notebook to demonstrate the use and value of the new converter.

The new subclass should be loaded automatically and included in the converters returned by BaseDateConverter.available_converters()

To add support for a new calendar converter:

  • Create a new file under undate/converters/calendars/
    • For converters with sufficient complexity, you may want to create a submodule; see undate.converters.calendars.islamic for an example.

  • Extend BaseCalendarConverter and implement parse and to_string formatter methods as desired/appropriate for your converter as well as the additional methods for max_month, max_day, and conversion to_gregorian calendar.

  • Import your calendar in undate/converters/calendars/__init__.py and include in __all__`

  • Add unit tests for the new calendar logic under tests/test_converters/calendars/

  • Add the new calendar to the Calendar enum of supported calendars in undate/undate.py and confirm that the get_converter method loads your calendar converter correctly (an existing unit test should cover this).

  • Consider creating a notebook to demonstrate the use of the calendar converter.

Calendar converter subclasses are also automatically loaded and included in the list of available converters.


class undate.converters.base.BaseCalendarConverter

Base class for calendar converters, with additional methods required for calendars.

MAX_YEAR: None | int = None
MIN_YEAR: None | int = None
days_in_year(year: int) int

Number of days in the specified year in this calendar. The default implementation uses min and max month and max day methods along with Gregorian conversion method to calculate the number of days in the specified year.

first_month() int

first month in this calendar; by default, returns min_month().

last_month(year: int) int

last month in this calendar; by default, returns max_month().

max_day(year: int, month: int) int

maximum numeric day for the specified year and month in this calendar

max_month(year: int) int

Maximum numeric month for this calendar

min_month() int

Smallest numeric month for this calendar.

name: str = 'Base Calendar Converter'

Converter name. Subclasses must define a unique name.

representative_years(years: None | list[int] = None) list[int]

Returns a list of representative years within the specified list. Result should include one for each type of variant year for this calendar (e.g., leap year and non-leap year). If no years are specified, returns a list of representative years for the current calendar.

to_gregorian(year, month, day) tuple[int, int, int]

Convert a date for this calendar specified by numeric year, month, and day, into the Gregorian equivalent date. Should return a tuple of year, month, day.

class undate.converters.base.BaseDateConverter

Base class for parsing, formatting, and converting dates to handle specific formats and different calendars.

LEAP_YEAR = 0
NON_LEAP_YEAR = 0
classmethod available_converters() dict[str, type[BaseDateConverter]]

Dictionary of available converters keyed on name.

classmethod import_converters() int

Import all undate converters so that they will be included in available converters even if not explicitly imported. Only import once. returns the count of modules imported.

name: str = 'Base Converter'

Converter name. Subclasses must define a unique name.

parse(value: str)

Parse a string and return an Undate or UndateInterval. Must be implemented by subclasses.

classmethod subclasses() set[type[BaseDateConverter]]

Set of available converters classes. Includes descendant subclasses, including calendar converters, but does not include BaseCalendarConverter.

to_string(undate) str

Convert an Undate or UndateInterval to string. Must be implemented by subclasses.

undate.converters.base.GRAMMAR_FILE_PATH = PosixPath('/home/docs/checkouts/readthedocs.org/user_builds/undate-python/checkouts/latest/src/undate/converters/grammars')

Path to parser grammar files

class undate.converters.combined.OmnibusDateConverter

Combination parser that aggregates existing parser grammars. Supports EDTF, Gregorian, Hebrew, Hijri, and Christian liturgical dates where dates are unambiguous. Year-only dates are parsed as EDTF in Gregorian calendar.

Does not support serialization.

Example usage:

Undate.parse("Tammuz 4812", "omnibus")
Undate.parse("Easter 1916", "omnibus")
name: str = 'omnibus'

converter name: omnibus

parse(value: str) Undate | UndateInterval

Parse a string in a supported format and return an Undate or UndateInterval.

to_string(undate: Undate | UndateInterval) str

Not supported by this converter. Will raise ValueError

Formats

ISO8601

class undate.converters.iso8601.ISO8601DateFormat
iso_format: ClassVar[dict[str, str]] = {'day': '%d', 'month': '%m', 'year': '%Y'}

datetime strftime format for known part of date

name: str = 'ISO8601'

converter name: ISO8601

parse(value: str) Undate | UndateInterval

Parse an ISO88601 string and return an Undate or UndateInterval. Currently supports YYYY, YYYY-MM, YYYY-MM-DD, –MM-DD for single date and interval format (YYYY/YYYY in any supported single date format).

to_string(undate: Undate | UndateInterval) str

Convert an Undate or UndateInterval to ISO8601 string format.

Extended Date-Time Format (EDTF)

class undate.converters.edtf.converter.EDTFDateConverter

Converter for Extended Date/Time Format (EDTF).

Supports parsing and serializing dates and date ranges in EDTF format. Does not support all of EDTF, and only supports dates and not times.

name: str = 'EDTF'

converter name: EDTF

parse(value: str) Undate | UndateInterval

Parse a string in a supported EDTF date or date interval format and return an Undate or UndateInterval.

to_string(undate: Undate | UndateInterval) str

Convert an Undate or UndateInterval to EDTF format.

undate.converters.edtf.converter.EDTF_UNSPECIFIED_DIGIT: str = 'X'

character for unspecified digits

Calendars

Gregorian

class undate.converters.calendars.gregorian.GregorianDateConverter

Calendar converter class for Gregorian calendar.

LEAP_YEAR: int = 2024

arbitrary known leap year

NON_LEAP_YEAR: int = 2022

arbitrary known non-leap year

calendar_name: str = 'Gregorian'

calendar

max_day(year: int, month: int) int

maximum numeric day for the specified year and month in this calendar

max_month(year: int) int

maximum numeric month for the specified year in the Gregorian calendar

min_month() int

First month for the Gregorian calendar.

name: str = 'Gregorian'

converter name: Gregorian

parse(value: str) Undate

Parse a Gregorian date string of any supported precision in any supported language and return an Undate. The input date string is preserved in the label of the resulting Undate object.

representative_years(years: None | list[int] = None) list[int]

Takes a list of years and returns a subset with one leap year and one non-leap year. If no years are specified, returns a known leap year and non-leap year.

to_gregorian(year, month, day) tuple[int, int, int]

Convert to Gregorian date. This returns the specified by year, month, and day unchanged, but is provided for consistency since all calendar converters need to support conversion to Gregorian calendar for a common point of comparison.

Hebrew Anno Mundi calendar

class undate.converters.calendars.hebrew.converter.HebrewDateConverter

Converter for Hebrew Anno Mundicalendar.

Support for parsing Anno Mundi dates and converting to Undate and UndateInterval objects in the Gregorian calendar.

LEAP_YEAR: int = 4837

arbitrary known leap year; 4837 is a leap year with 385 days (maximum possible)

MIN_YEAR: int = 1

earliest possible year in the Hebrew calendar is year 1, it does not go negative

NON_LEAP_YEAR: int = 4816

arbitrary known non-leap year; 4816 is a non-leap year with 353 days (minimum possible)

days_in_year(year: int) int

the number of days in the specified year for this calendar

first_month() int

First month in this calendar. The Hebrew civil year starts in Tishri.

last_month(year: int) int

Last month in this calendar. Hebrew civil year starts in Tishri, Elul is the month before Tishri.

max_day(year: int, month: int) int

maximum numeric day for the specified year and month in this calendar

max_month(year: int) int

Maximum numeric month for this calendar. In Hebrew calendar, this is 12 or 13 depending on whether it is a leap year.

min_month() int

Smallest numeric month for this calendar.

name: str = 'Hebrew'

converter name: Hebrew

parse(value: str) Undate | UndateInterval

Parse a Hebrew date string and return an Undate or UndateInterval. The Hebrew date string is preserved in the undate label.

representative_years(years: None | list[int] = None) list[int]

Takes a list of years and returns a subset with all possible variations in number of days. If no years are specified, returns …

to_gregorian(year: int, month: int, day: int) tuple[int, int, int]

Convert a Hebrew date, specified by year, month, and day, to the Gregorian equivalent date. Returns a tuple of year, month, day.

Islamic Hijri calendar

class undate.converters.calendars.islamic.converter.IslamicDateConverter

Converter for Islamic Hijri calendar.

Support for parsing Islamic Hijri dates and converting to Undate and UndateInterval objects in the Gregorian calendar.

LEAP_YEAR: int = 1458

arbitrary known leap year

NON_LEAP_YEAR: int = 1457

arbitrary known non-leap year

max_day(year: int, month: int) int

maximum numeric day for the specified year and month in this calendar

max_month(year: int) int

maximum numeric month for this calendar

min_month() int

smallest numeric month for this calendar.

name: str = 'Islamic'

converter name: Islamic

parse(value: str) Undate | UndateInterval

Parse an Islamic/Hijri date string and return an Undate or UndateInterval. The Islamic/Hijri date string is preserved in the undate label.

representative_years(years: None | list[int] = None) list[int]

Takes a list of years and returns a subset with one leap year and one non-leap year. If no years are specified, returns a known leap year and non-leap year.

to_gregorian(year: int, month: int, day: int) tuple[int, int, int]

Convert a Hijri date, specified by year, month, and day, to the Gregorian equivalent date. Returns a tuple of year, month, day.