Localtime

Module for working with dates, times and timezones

Used over the years internally in Kraken Technologies, this module is a battle tested and well reviewed module for working with dates, times and timezones. The main API it presents is composed of a series of functions which accept a date/datetime object, and manipulate it in one form or another.

Examples

from xocto import localtime
>>> now = localtime.now()
>>> now
2022-04-20 14:57:53.045707+02:00
>>> localtime.seconds_in_the_future(n=10, dt=now)
2022-04-20 14:58:03.045707+02:00
>>> localtime.nearest_half_hour(now)
2022-04-20 15:00:00+02:00

See xocto.localtime for more details, including examples and in depth technical details.

Variables

xocto.localtime.far_future = datetime.datetime(9999, 12, 29, 23, 59, 59, 999999, tzinfo=zoneinfo.ZoneInfo(key='America/Chicago'))

datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])

The year, month and day arguments are required. tzinfo may be None, or an instance of a tzinfo subclass. The remaining arguments may be ints.

xocto.localtime.far_past = datetime.datetime(1, 1, 3, 0, 0, tzinfo=zoneinfo.ZoneInfo(key='America/Chicago'))

datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])

The year, month and day arguments are required. tzinfo may be None, or an instance of a tzinfo subclass. The remaining arguments may be ints.

xocto.localtime.UTC = zoneinfo.ZoneInfo(key='UTC')
xocto.localtime.LONDON = zoneinfo.ZoneInfo(key='Europe/London')
xocto.localtime.ONE_DAY = datetime.timedelta(days=1)

Difference between two datetime values.

timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

All arguments are optional and default to 0. Arguments may be integers or floats, and may be positive or negative.

xocto.localtime.ONE_HOUR = datetime.timedelta(seconds=3600)

Difference between two datetime values.

timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

All arguments are optional and default to 0. Arguments may be integers or floats, and may be positive or negative.

xocto.localtime.MIDNIGHT_TIME = datetime.time(0, 0)

time([hour[, minute[, second[, microsecond[, tzinfo]]]]]) –> a time object

All arguments are optional. tzinfo may be None, or an instance of a tzinfo subclass. The remaining arguments may be ints.

API Reference

xocto.localtime.as_localtime(dt: datetime, tz: tzinfo | None = None) datetime[source]

Convert a tz aware datetime to localtime.

Wrapper for the django.utils.timezone function, taking the same arguments.

xocto.localtime.as_range(_date: date | None, tz: tzinfo | None = None) Tuple[datetime, datetime][source]

Return a 2-tuple of the min and max datetimes for the given date.

This gives values that can be passed to the ORM __range filter.

xocto.localtime.as_utc(dt: datetime) datetime[source]

Wrapper for normalizing a datetime aware object into UTC.

xocto.localtime.combine(_date: date, _time: time, tz: tzinfo) datetime[source]

Return a TZ-aware datetime obtained by combining the given date and time.

It’s a TZ-aware wrapper around datetime.datetime.combine.

xocto.localtime.consolidate_into_intervals(dates: Sequence[date]) Sequence[Tuple[date, date]][source]

Given a sequence of dates, return tuples of (inclusive) boundaries of the sub-sequences where the dates are consecutive.

If a date does not form a continuous interval with any other dates - i.e. it is separated by at least a day before and after the others - it forms an interval with itself as both boundaries.

For example, if passed: [

<Date year=2020, month=1, day=1>, <Date year=2020, month=1, day=2>, <Date year=2020, month=1, day=4>, <Date year=2020, month=1, day=5>,

] it would return: [

(<Date year=2020, month=1, day=1>, <Date year=2020, month=1, day=2>), (<Date year=2020, month=1, day=4>, <Date year=2020, month=1, day=5>),

]

xocto.localtime.date(dt: datetime, tz: tzinfo | None = None) date[source]

Return the date of the given datetime in the given timezone, defaulting to local time.

Note that dt must already be timezone-aware: it cannot be naive. It may be in UTC, for example, or already in current local time, in which case the effect will be the same as calling .date() on it. If tz is not provided, the function will return the date of dt in the local time zone.

xocto.localtime.date_boundaries(_date: date | None, tz: tzinfo | None = None) Tuple[datetime, datetime][source]

Return a 2-tuple with the start and ending dt for the given date in the local timezone.

Note, be careful of using this with __range ORM queries as such queries are INCLUSIVE on the boundaries.

xocto.localtime.date_iterator(start_date: date, end_date: date) Generator[date, None, None][source]

Iterate through dates between two dates

xocto.localtime.date_of_day_before(dt: datetime, tz: tzinfo | None = None) date[source]

Return the date of the day before the datetime passed in.

That is, find the local date of the datetime passed in, subtract one day from it, and return it.

This is frequently useful when we are converting from the upper bound of a datetime range, which by convention we treat as exclusive, to the upper bound of a date range, which by convention we consider inclusive.

Note that dt must already be timezone-aware: it cannot be naive. It may be in UTC, for example, or already in current local time, in which case the effect will be the same as calling .date() on it and subtracting a day. If tz is not provided, the function will return the date before dt in the local time zone.

xocto.localtime.datetime(year: int, month: int, day: int, hour: int = 0, minute: int = 0, second: int = 0, microsecond: int = 0) datetime[source]

Return a datetime in the local timezone.

xocto.localtime.datetime_from_date(_date: date, hour: int, tz: tzinfo | None = None) datetime[source]

Return a TZ-aware datetime for the hour of the passed date.

xocto.localtime.datetime_from_epoch_timestamp(timestamp: int | float, tz: tzinfo | None = None) datetime[source]

Return a TZ-aware datetime for the passed epoch timestamp.

xocto.localtime.day_after(d: date) date[source]

Return the date of the day after the passed date.

xocto.localtime.day_before(d: date) date[source]

Return the date of the day before the passed date.

xocto.localtime.days_in_the_future(n: int, tz: tzinfo | None = None) date[source]

Return n days after the current date (in the provided or local timezone).

xocto.localtime.days_in_the_past(n: int, tz: tzinfo | None = None) date[source]

Return n days before the current date (in the provided or local timezone).

xocto.localtime.end_of_month(dt: datetime | None = None) datetime[source]

Return the start datetime of the next month for dt passed - or of next month.

xocto.localtime.first_day_of_month(dt: datetime | None = None) date[source]

Return the start date of the month for dt passed - or of current month.

xocto.localtime.is_aligned_to_midnight(range: FiniteDatetimeRange, tz: tzinfo | None = None) bool[source]

Return whether this range is aligned to localtime midnight.

xocto.localtime.is_date_within_date_range(date_in_question: date, start: date, end: date) bool[source]

Return whether a given date falls within the range of two other dates. This function assumes start < end.

xocto.localtime.is_dst(local_time: datetime) bool[source]

Indicate whether the given time (and timezone is in daylight savings time (DST or not).

Raises:

ValueError if local_time is a naive datetime.

xocto.localtime.is_future_date(_date: date) bool[source]

Test whether a date is in the future.

xocto.localtime.is_in_the_future(dt: datetime) bool[source]

Test whether a datetime is in the future.

xocto.localtime.is_in_the_past(dt: datetime) bool[source]

Test whether a datetime is in the past.

Note that we treat the current time as ‘in the past’ for the sake of this test. This means that any given datetime will always return True for either this function or is_in_the_future.

xocto.localtime.is_last_day_of_month(_date: date) bool[source]

Return True if the given date is the last day of the month.

xocto.localtime.is_local_time(dt: datetime) bool[source]

Test whether a given (timezone-aware) datetime is in local time or not.

xocto.localtime.is_localtime_midnight(dt: datetime, tz: tzinfo | None = None) bool[source]

Return whether the supplied datetime is at midnight (in the site’s local time zone).

Note, the supplied datetime, which should be timezone aware, may be in any timezone, providing it corresponds to the moment of midnight in the site’s local time zone.

xocto.localtime.is_n_days_until_end_of_month(n_days: int) bool[source]

Return whether today + n days is the first of the next month.

xocto.localtime.is_utc(dt: datetime) bool[source]

Test whether a given (timezone-aware) datetime is in UTC time or not.

xocto.localtime.is_within_the_last_week(date: date) bool[source]

Test whether a date is within a week ago of today’s dates inclusive of the earliest date.

xocto.localtime.is_within_the_last_year(date: date) bool[source]

Test whether a date is one year or less before today’s local date.

xocto.localtime.last_day_of_month(dt: datetime | None = None) date[source]

Return the last date of the month for dt passed - or of current month.

xocto.localtime.latest(_date: date | None = None, tz: tzinfo | None = None) datetime[source]

Return a TZ-aware datetime for the latest representable datetime of the passed date.

If date is None then the current date in the local timezone is used.

xocto.localtime.latest_date_for_day(start_date: date, end_date: date, day_of_month: int) date | None[source]

Given an integer day of a month, return the latest date with that day of the month, bounded by the supplied start_date and end_date. If no such date exists, return None.

xocto.localtime.make_aware_assuming_local(dt: datetime) datetime[source]

Just a wrapper for Django’s method, which will takes a naive datetime, and makes it timezone aware, assuming the current timezone if none is passed (which it isn’t from this wrapper function). It will also raise an exception if the passed datetime is already timezone-aware.

xocto.localtime.make_aware_assuming_utc(dt: datetime) datetime[source]

Return a timezone-aware datetime (in UTC) given a naive datetime.

xocto.localtime.midday(_date: date | None = None, tz: tzinfo | None = None) datetime[source]

Return a TZ-aware datetime for midday of the passed date.

If date is None then the current date in the passed timezone is used (if no timezone is supplied then we use the local timezone).

xocto.localtime.midnight(date_or_datetime: date | datetime | None = None, tz: tzinfo | None = None) datetime[source]

Return a TZ-aware datetime for midnight of the passed date.

If date is None then the current date in the passed timezone is used (if no timezone is supplied then we use the local timezone).

xocto.localtime.month_boundaries(month: int, year: int) Tuple[datetime, datetime][source]

Return the boundary datetimes of a given month.

The boundary consists of a 2-tuple of: midnight of the first day of the month and midnight of the first day of the next month.

For example:

>>> month_boundaries(1, 2020)
((datetime.datetime(2020, 1, 1, 0, 0), datetime.datetime(2020, 2, 1, 0, 0))
xocto.localtime.months_in_the_future(n: int, tz: tzinfo | None = None) date[source]

Return n months after the current date (in the provided or local timezone).

xocto.localtime.months_in_the_past(n: int, tz: tzinfo | None = None) date[source]

Return n months before the current date (in the provided or local timezone).

xocto.localtime.nearest_half_hour(dt: datetime) datetime[source]

Return the nearest half-hour datetime to the passed datetime.

xocto.localtime.next_date_with_day_of_month(date: date, day_of_month: int) date[source]

Given a starting date, return the next date with the specified day_of_month.

If the day of the month doesn’t exist in the next month, return the nearest date that does.

For example:

next_date_with_day_of_month(date=date(2020, 1, 31), day_of_month=31)

returns:

date(2020, 2, 29).

Raises:
  • TypeError – if a datetime is used for date

  • ValueError – if the day of month is invalid

Note: Python’s datetime is a subclass of date, so the type checker will not prevent passing it to this function.

xocto.localtime.next_midnight(date_or_datetime: date | datetime | None = None, tz: tzinfo | None = None) datetime[source]

Return the datetime for midnight of the following day to the date passed in.

This is intuitively what people think of as midnight.

xocto.localtime.now() datetime[source]

Return the current datetime in the local timezone.

xocto.localtime.parse_date(value: str) date[source]

Returns a datetime.date for a given ISO format date string.

xocto.localtime.parse_dt(value: str, tz: tzinfo | None = None) datetime[source]

Returns a datetime.datetime for a given ISO format date/time string.

The date/time must be naive - not include timezone information.

xocto.localtime.period_exceeds_one_year(start_at: datetime, end_at: datetime) bool[source]

Returns true if the passed period exceeds one year.

Edge cases such as leap years and daylight savings time are handled, where a simple approach using only relativedelta would not be sufficient.

xocto.localtime.quantise(dt: datetime, timedelta: timedelta, rounding: str = 'ROUND_HALF_EVEN') datetime[source]

‘Round’ a datetime to the nearest interval given by the timedelta argument.

For example:

>>>> quantise(datetime.datetime(2020, 4, 1, 23, 21), timedelta(minutes=15)) datetime.datetime(2020, 4, 1, 23, 30)

xocto.localtime.seconds_in_the_future(n: int, dt: datetime | None = None) datetime[source]

Return a datetime of the number of specifed seconds in the future.

xocto.localtime.seconds_in_the_past(n: int) datetime[source]

Return a datetime of the number of specifed seconds in the past.

xocto.localtime.start_of_month(dt: datetime | None = None) datetime[source]

Return the start datetime of the month for dt passed - or of current month.

xocto.localtime.strftime(dt: datetime, fmt: str, tz: tzinfo | None = None) str[source]

Format a tz aware datetime in localtime.

Wrapper for datetime.strftime.

xocto.localtime.system_timezone() tzlocal[source]

Get the current system timezone.

xocto.localtime.today(tz: tzinfo | None = None) date[source]

Return the current date in the provided timezone (or the local timezone if none is supplied).

xocto.localtime.tomorrow(tz: tzinfo | None = None) date[source]

Return the next date in the provided timezone (or the local timezone if none is supplied).

xocto.localtime.translate_english_month_to_spanish(month: int) str[source]
xocto.localtime.within_date_range(first_date: date, second_date: date, days: int = 3) bool[source]

Check if two dates are within a range from each other.

xocto.localtime.yesterday(tz: tzinfo | None = None) date[source]

Return the previous date in the provided timezone (or the local timezone if none is supplied).