arconverter.arconverter

Convert dates to Absolom Reconing calendar system.

Examples:

from datetime import datetime date = datetime(2023, 12, 25) ar_date = convert(date) print(ar_date.year) # 4723

  1"""Convert dates to Absolom Reconing calendar system.
  2
  3Examples:
  4    >>> from datetime import datetime
  5    >>> date = datetime(2023, 12, 25)
  6    >>> ar_date = convert(date)
  7    >>> print(ar_date.year)  # 4723
  8"""
  9
 10from datetime import datetime
 11from typing import Final
 12
 13from arconverter.ardate import ArDate
 14from arconverter.constants import (
 15    arCommonMonths,
 16    arDays,
 17    arDayShort,
 18    arMonths,
 19    arMonthSeasons,
 20    arShortMonths,
 21)
 22
 23MIN_YEAR: Final[int] = 1970  # Unix epoch
 24MAX_YEAR: Final[int] = 2099  # Upper limit before conversion breaks
 25
 26YEAR_OFFSET: Final[int] = 2700  # Set by the Absolom Reckoning calendar (Paizo)
 27
 28
 29class ArConverterError(Exception):
 30    """Base exception for arconverter errors."""
 31
 32    pass
 33
 34
 35def validate_date(date: datetime) -> None:
 36    """Validate the input date is within acceptable ranges."""
 37    if not isinstance(date, datetime):
 38        raise ArConverterError('Input must be a datetime object')
 39
 40    if date.year < MIN_YEAR or date.year > MAX_YEAR:
 41        raise ArConverterError(f'Year must be between {MIN_YEAR} and {MAX_YEAR}')
 42
 43
 44def convert(target_date: datetime) -> ArDate:
 45    """Convert a datetime object to an Absalom Reckoning date.
 46
 47    Args:
 48        target_date: A datetime object representing the Gregorian calendar date to convert
 49
 50    Returns:
 51        ArDate: An Absalom Reckoning date object with the following attributes:
 52            - year: AR year (Gregorian + 2700)
 53            - month: Full month name
 54            - monthShort: 3-letter month abbreviation
 55            - commonMonth: Common folk month name
 56            - day: Day of month
 57            - weekday: Full weekday name
 58            - weekdayShort: 3-letter weekday abbreviation
 59            - weekdayNum: Day of week (1-7, Moonday=1)
 60            - monthNum: Month number (1-12)
 61            - season: Current season name
 62
 63    Raises:
 64        ArConverterError: If input is not a datetime object or year is out of valid range
 65
 66    Examples:
 67        >>> from datetime import datetime
 68        >>> date = datetime(2023, 7, 10)
 69        >>> ar_date = convert(date)
 70        >>> print(ar_date.long_date())
 71        'Erastus 10, 4723'
 72        >>> print(ar_date.season)
 73        'Summer'
 74    """
 75    validate_date(target_date)
 76
 77    try:
 78        # Break the year up into pieces
 79        year = target_date.year
 80        month = target_date.month
 81        day = target_date.day
 82        day_of_week = target_date.weekday() + 1
 83
 84        # Build the resulting arDate and it's properties
 85        result = ArDate()
 86        result.year = year + YEAR_OFFSET
 87        result.monthNum = month
 88        result.day = day
 89        result.month = arMonths[month]
 90        result.monthShort = arShortMonths[month]
 91        result.weekday = arDays[day_of_week]
 92        result.weekdayNum = day_of_week
 93        result.weekdayShort = arDayShort[day_of_week]
 94        result.commonMonth = arCommonMonths[month]
 95        result.season = arMonthSeasons[month]
 96
 97        return result
 98
 99    except KeyError as e:
100        raise ArConverterError(f'Invalid calendar mapping: {e}')
101    except Exception as e:
102        raise ArConverterError(f'Conversion error: {e}')
MIN_YEAR: Final[int] = 1970
MAX_YEAR: Final[int] = 2099
YEAR_OFFSET: Final[int] = 2700
class ArConverterError(builtins.Exception):
30class ArConverterError(Exception):
31    """Base exception for arconverter errors."""
32
33    pass

Base exception for arconverter errors.

def validate_date(date: datetime.datetime) -> None:
36def validate_date(date: datetime) -> None:
37    """Validate the input date is within acceptable ranges."""
38    if not isinstance(date, datetime):
39        raise ArConverterError('Input must be a datetime object')
40
41    if date.year < MIN_YEAR or date.year > MAX_YEAR:
42        raise ArConverterError(f'Year must be between {MIN_YEAR} and {MAX_YEAR}')

Validate the input date is within acceptable ranges.

def convert(target_date: datetime.datetime) -> arconverter.ardate.ArDate:
 45def convert(target_date: datetime) -> ArDate:
 46    """Convert a datetime object to an Absalom Reckoning date.
 47
 48    Args:
 49        target_date: A datetime object representing the Gregorian calendar date to convert
 50
 51    Returns:
 52        ArDate: An Absalom Reckoning date object with the following attributes:
 53            - year: AR year (Gregorian + 2700)
 54            - month: Full month name
 55            - monthShort: 3-letter month abbreviation
 56            - commonMonth: Common folk month name
 57            - day: Day of month
 58            - weekday: Full weekday name
 59            - weekdayShort: 3-letter weekday abbreviation
 60            - weekdayNum: Day of week (1-7, Moonday=1)
 61            - monthNum: Month number (1-12)
 62            - season: Current season name
 63
 64    Raises:
 65        ArConverterError: If input is not a datetime object or year is out of valid range
 66
 67    Examples:
 68        >>> from datetime import datetime
 69        >>> date = datetime(2023, 7, 10)
 70        >>> ar_date = convert(date)
 71        >>> print(ar_date.long_date())
 72        'Erastus 10, 4723'
 73        >>> print(ar_date.season)
 74        'Summer'
 75    """
 76    validate_date(target_date)
 77
 78    try:
 79        # Break the year up into pieces
 80        year = target_date.year
 81        month = target_date.month
 82        day = target_date.day
 83        day_of_week = target_date.weekday() + 1
 84
 85        # Build the resulting arDate and it's properties
 86        result = ArDate()
 87        result.year = year + YEAR_OFFSET
 88        result.monthNum = month
 89        result.day = day
 90        result.month = arMonths[month]
 91        result.monthShort = arShortMonths[month]
 92        result.weekday = arDays[day_of_week]
 93        result.weekdayNum = day_of_week
 94        result.weekdayShort = arDayShort[day_of_week]
 95        result.commonMonth = arCommonMonths[month]
 96        result.season = arMonthSeasons[month]
 97
 98        return result
 99
100    except KeyError as e:
101        raise ArConverterError(f'Invalid calendar mapping: {e}')
102    except Exception as e:
103        raise ArConverterError(f'Conversion error: {e}')

Convert a datetime object to an Absalom Reckoning date.

Args: target_date: A datetime object representing the Gregorian calendar date to convert

Returns: ArDate: An Absalom Reckoning date object with the following attributes: - year: AR year (Gregorian + 2700) - month: Full month name - monthShort: 3-letter month abbreviation - commonMonth: Common folk month name - day: Day of month - weekday: Full weekday name - weekdayShort: 3-letter weekday abbreviation - weekdayNum: Day of week (1-7, Moonday=1) - monthNum: Month number (1-12) - season: Current season name

Raises: ArConverterError: If input is not a datetime object or year is out of valid range

Examples:

from datetime import datetime date = datetime(2023, 7, 10) ar_date = convert(date) print(ar_date.long_date()) 'Erastus 10, 4723' print(ar_date.season) 'Summer'