summaryrefslogtreecommitdiffstats
path: root/pendulum
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2023-12-17 14:36:26 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2023-12-17 14:36:33 +0000
commit665666d6f4213da8db57ebb480947b7caf1fe382 (patch)
tree0cac5d322dfe861a6de62b04fb916cef6dbe4510 /pendulum
parentReleasing debian version 3.0.0~a1-2. (diff)
downloadpendulum-665666d6f4213da8db57ebb480947b7caf1fe382.tar.xz
pendulum-665666d6f4213da8db57ebb480947b7caf1fe382.zip
Merging upstream version 3.0.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'pendulum')
-rw-r--r--pendulum/__init__.py363
-rw-r--r--pendulum/__version__.py1
-rw-r--r--pendulum/_extensions/__init__.py0
-rw-r--r--pendulum/_extensions/_helpers.c931
-rw-r--r--pendulum/_extensions/_helpers.pyi31
-rw-r--r--pendulum/_extensions/helpers.py364
-rw-r--r--pendulum/constants.py109
-rw-r--r--pendulum/date.py760
-rw-r--r--pendulum/datetime.py1381
-rw-r--r--pendulum/duration.py502
-rw-r--r--pendulum/exceptions.py8
-rw-r--r--pendulum/formatting/__init__.py5
-rw-r--r--pendulum/formatting/difference_formatter.py146
-rw-r--r--pendulum/formatting/formatter.py683
-rw-r--r--pendulum/helpers.py223
-rw-r--r--pendulum/interval.py448
-rw-r--r--pendulum/locales/__init__.py0
-rw-r--r--pendulum/locales/cs/__init__.py0
-rw-r--r--pendulum/locales/cs/custom.py23
-rw-r--r--pendulum/locales/cs/locale.py266
-rw-r--r--pendulum/locales/da/__init__.py0
-rw-r--r--pendulum/locales/da/custom.py18
-rw-r--r--pendulum/locales/da/locale.py147
-rw-r--r--pendulum/locales/de/__init__.py0
-rw-r--r--pendulum/locales/de/custom.py36
-rw-r--r--pendulum/locales/de/locale.py144
-rw-r--r--pendulum/locales/en/__init__.py0
-rw-r--r--pendulum/locales/en/custom.py23
-rw-r--r--pendulum/locales/en/locale.py150
-rw-r--r--pendulum/locales/es/__init__.py0
-rw-r--r--pendulum/locales/es/custom.py23
-rw-r--r--pendulum/locales/es/locale.py141
-rw-r--r--pendulum/locales/fa/__init__.py0
-rw-r--r--pendulum/locales/fa/custom.py18
-rw-r--r--pendulum/locales/fa/locale.py135
-rw-r--r--pendulum/locales/fo/__init__.py0
-rw-r--r--pendulum/locales/fo/custom.py20
-rw-r--r--pendulum/locales/fo/locale.py132
-rw-r--r--pendulum/locales/fr/__init__.py0
-rw-r--r--pendulum/locales/fr/custom.py23
-rw-r--r--pendulum/locales/fr/locale.py133
-rw-r--r--pendulum/locales/he/__init__.py0
-rw-r--r--pendulum/locales/he/custom.py23
-rw-r--r--pendulum/locales/he/locale.py269
-rw-r--r--pendulum/locales/id/__init__.py0
-rw-r--r--pendulum/locales/id/custom.py19
-rw-r--r--pendulum/locales/id/locale.py141
-rw-r--r--pendulum/locales/it/__init__.py0
-rw-r--r--pendulum/locales/it/custom.py24
-rw-r--r--pendulum/locales/it/locale.py145
-rw-r--r--pendulum/locales/ja/__init__.py0
-rw-r--r--pendulum/locales/ja/custom.py21
-rw-r--r--pendulum/locales/ja/locale.py194
-rw-r--r--pendulum/locales/ko/__init__.py0
-rw-r--r--pendulum/locales/ko/custom.py18
-rw-r--r--pendulum/locales/ko/locale.py105
-rw-r--r--pendulum/locales/locale.py102
-rw-r--r--pendulum/locales/lt/__init__.py0
-rw-r--r--pendulum/locales/lt/custom.py118
-rw-r--r--pendulum/locales/lt/locale.py255
-rw-r--r--pendulum/locales/nb/__init__.py0
-rw-r--r--pendulum/locales/nb/custom.py20
-rw-r--r--pendulum/locales/nb/locale.py150
-rw-r--r--pendulum/locales/nl/__init__.py0
-rw-r--r--pendulum/locales/nl/custom.py23
-rw-r--r--pendulum/locales/nl/locale.py134
-rw-r--r--pendulum/locales/nn/__init__.py0
-rw-r--r--pendulum/locales/nn/custom.py20
-rw-r--r--pendulum/locales/nn/locale.py141
-rw-r--r--pendulum/locales/pl/__init__.py0
-rw-r--r--pendulum/locales/pl/custom.py21
-rw-r--r--pendulum/locales/pl/locale.py279
-rw-r--r--pendulum/locales/pt_br/__init__.py0
-rw-r--r--pendulum/locales/pt_br/custom.py18
-rw-r--r--pendulum/locales/pt_br/locale.py143
-rw-r--r--pendulum/locales/ru/__init__.py0
-rw-r--r--pendulum/locales/ru/custom.py20
-rw-r--r--pendulum/locales/ru/locale.py270
-rw-r--r--pendulum/locales/sk/__init__.py0
-rw-r--r--pendulum/locales/sk/custom.py20
-rw-r--r--pendulum/locales/sk/locale.py266
-rw-r--r--pendulum/locales/sv/__init__.py0
-rw-r--r--pendulum/locales/sv/custom.py20
-rw-r--r--pendulum/locales/sv/locale.py222
-rw-r--r--pendulum/locales/zh/__init__.py0
-rw-r--r--pendulum/locales/zh/custom.py18
-rw-r--r--pendulum/locales/zh/locale.py113
-rw-r--r--pendulum/mixins/__init__.py0
-rw-r--r--pendulum/mixins/default.py36
-rw-r--r--pendulum/parser.py124
-rw-r--r--pendulum/parsing/__init__.py233
-rw-r--r--pendulum/parsing/_iso8601.c1361
-rw-r--r--pendulum/parsing/_iso8601.pyi22
-rw-r--r--pendulum/parsing/exceptions/__init__.py6
-rw-r--r--pendulum/parsing/iso8601.py454
-rw-r--r--pendulum/py.typed0
-rw-r--r--pendulum/testing/__init__.py0
-rw-r--r--pendulum/testing/traveller.py139
-rw-r--r--pendulum/time.py303
-rw-r--r--pendulum/tz/__init__.py80
-rw-r--r--pendulum/tz/data/__init__.py0
-rw-r--r--pendulum/tz/data/windows.py139
-rw-r--r--pendulum/tz/exceptions.py32
-rw-r--r--pendulum/tz/local_timezone.py260
-rw-r--r--pendulum/tz/timezone.py217
-rw-r--r--pendulum/utils/__init__.py0
-rw-r--r--pendulum/utils/_compat.py13
107 files changed, 0 insertions, 14138 deletions
diff --git a/pendulum/__init__.py b/pendulum/__init__.py
deleted file mode 100644
index 4491244..0000000
--- a/pendulum/__init__.py
+++ /dev/null
@@ -1,363 +0,0 @@
-from __future__ import annotations
-
-import datetime as _datetime
-
-from typing import Union
-from typing import cast
-
-from pendulum.__version__ import __version__
-from pendulum.constants import DAYS_PER_WEEK
-from pendulum.constants import FRIDAY
-from pendulum.constants import HOURS_PER_DAY
-from pendulum.constants import MINUTES_PER_HOUR
-from pendulum.constants import MONDAY
-from pendulum.constants import MONTHS_PER_YEAR
-from pendulum.constants import SATURDAY
-from pendulum.constants import SECONDS_PER_DAY
-from pendulum.constants import SECONDS_PER_HOUR
-from pendulum.constants import SECONDS_PER_MINUTE
-from pendulum.constants import SUNDAY
-from pendulum.constants import THURSDAY
-from pendulum.constants import TUESDAY
-from pendulum.constants import WEDNESDAY
-from pendulum.constants import WEEKS_PER_YEAR
-from pendulum.constants import YEARS_PER_CENTURY
-from pendulum.constants import YEARS_PER_DECADE
-from pendulum.date import Date
-from pendulum.datetime import DateTime
-from pendulum.duration import Duration
-from pendulum.formatting import Formatter
-from pendulum.helpers import format_diff
-from pendulum.helpers import get_locale
-from pendulum.helpers import locale
-from pendulum.helpers import set_locale
-from pendulum.helpers import week_ends_at
-from pendulum.helpers import week_starts_at
-from pendulum.interval import Interval
-from pendulum.parser import parse
-from pendulum.testing.traveller import Traveller
-from pendulum.time import Time
-from pendulum.tz import UTC
-from pendulum.tz import local_timezone
-from pendulum.tz import set_local_timezone
-from pendulum.tz import test_local_timezone
-from pendulum.tz import timezone
-from pendulum.tz import timezones
-from pendulum.tz.timezone import FixedTimezone
-from pendulum.tz.timezone import Timezone
-
-_TEST_NOW: DateTime | None = None
-_LOCALE = "en"
-_WEEK_STARTS_AT = MONDAY
-_WEEK_ENDS_AT = SUNDAY
-
-_formatter = Formatter()
-
-
-def _safe_timezone(
- obj: str | float | _datetime.tzinfo | Timezone | FixedTimezone | None,
- dt: _datetime.datetime | None = None,
-) -> Timezone | FixedTimezone:
- """
- Creates a timezone instance
- from a string, Timezone, TimezoneInfo or integer offset.
- """
- if isinstance(obj, (Timezone, FixedTimezone)):
- return obj
-
- if obj is None or obj == "local":
- return local_timezone()
-
- if isinstance(obj, (int, float)):
- obj = int(obj * 60 * 60)
- elif isinstance(obj, _datetime.tzinfo):
- # zoneinfo
- if hasattr(obj, "key"):
- obj = obj.key # type: ignore
- # pytz
- elif hasattr(obj, "localize"):
- obj = obj.zone # type: ignore
- elif obj.tzname(None) == "UTC":
- return UTC
- else:
- offset = obj.utcoffset(dt)
-
- if offset is None:
- offset = _datetime.timedelta(0)
-
- obj = int(offset.total_seconds())
-
- obj = cast(Union[str, int], obj)
-
- return timezone(obj)
-
-
-# Public API
-def datetime(
- year: int,
- month: int,
- day: int,
- hour: int = 0,
- minute: int = 0,
- second: int = 0,
- microsecond: int = 0,
- tz: str | float | Timezone | FixedTimezone | _datetime.tzinfo | None = UTC,
- fold: int = 1,
- raise_on_unknown_times: bool = False,
-) -> DateTime:
- """
- Creates a new DateTime instance from a specific date and time.
- """
- return DateTime.create(
- year,
- month,
- day,
- hour=hour,
- minute=minute,
- second=second,
- microsecond=microsecond,
- tz=tz,
- fold=fold,
- raise_on_unknown_times=raise_on_unknown_times,
- )
-
-
-def local(
- year: int,
- month: int,
- day: int,
- hour: int = 0,
- minute: int = 0,
- second: int = 0,
- microsecond: int = 0,
-) -> DateTime:
- """
- Return a DateTime in the local timezone.
- """
- return datetime(
- year, month, day, hour, minute, second, microsecond, tz=local_timezone()
- )
-
-
-def naive(
- year: int,
- month: int,
- day: int,
- hour: int = 0,
- minute: int = 0,
- second: int = 0,
- microsecond: int = 0,
- fold: int = 1,
-) -> DateTime:
- """
- Return a naive DateTime.
- """
- return DateTime(year, month, day, hour, minute, second, microsecond, fold=fold)
-
-
-def date(year: int, month: int, day: int) -> Date:
- """
- Create a new Date instance.
- """
- return Date(year, month, day)
-
-
-def time(hour: int, minute: int = 0, second: int = 0, microsecond: int = 0) -> Time:
- """
- Create a new Time instance.
- """
- return Time(hour, minute, second, microsecond)
-
-
-def instance(
- dt: _datetime.datetime,
- tz: str | Timezone | FixedTimezone | _datetime.tzinfo | None = UTC,
-) -> DateTime:
- """
- Create a DateTime instance from a datetime one.
- """
- if not isinstance(dt, _datetime.datetime):
- raise ValueError("instance() only accepts datetime objects.")
-
- if isinstance(dt, DateTime):
- return dt
-
- tz = dt.tzinfo or tz
-
- if tz is not None:
- tz = _safe_timezone(tz, dt=dt)
-
- return datetime(
- dt.year,
- dt.month,
- dt.day,
- dt.hour,
- dt.minute,
- dt.second,
- dt.microsecond,
- tz=cast(Union[str, int, Timezone, FixedTimezone, None], tz),
- )
-
-
-def now(tz: str | Timezone | None = None) -> DateTime:
- """
- Get a DateTime instance for the current date and time.
- """
- return DateTime.now(tz)
-
-
-def today(tz: str | Timezone = "local") -> DateTime:
- """
- Create a DateTime instance for today.
- """
- return now(tz).start_of("day")
-
-
-def tomorrow(tz: str | Timezone = "local") -> DateTime:
- """
- Create a DateTime instance for today.
- """
- return today(tz).add(days=1)
-
-
-def yesterday(tz: str | Timezone = "local") -> DateTime:
- """
- Create a DateTime instance for today.
- """
- return today(tz).subtract(days=1)
-
-
-def from_format(
- string: str,
- fmt: str,
- tz: str | Timezone = UTC,
- locale: str | None = None,
-) -> DateTime:
- """
- Creates a DateTime instance from a specific format.
- """
- parts = _formatter.parse(string, fmt, now(tz=tz), locale=locale)
- if parts["tz"] is None:
- parts["tz"] = tz
-
- return datetime(**parts)
-
-
-def from_timestamp(timestamp: int | float, tz: str | Timezone = UTC) -> DateTime:
- """
- Create a DateTime instance from a timestamp.
- """
- dt = _datetime.datetime.utcfromtimestamp(timestamp)
-
- dt = datetime(
- dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond
- )
-
- if tz is not UTC or tz != "UTC":
- dt = dt.in_timezone(tz)
-
- return dt
-
-
-def duration(
- days: float = 0,
- seconds: float = 0,
- microseconds: float = 0,
- milliseconds: float = 0,
- minutes: float = 0,
- hours: float = 0,
- weeks: float = 0,
- years: float = 0,
- months: float = 0,
-) -> Duration:
- """
- Create a Duration instance.
- """
- return Duration(
- days=days,
- seconds=seconds,
- microseconds=microseconds,
- milliseconds=milliseconds,
- minutes=minutes,
- hours=hours,
- weeks=weeks,
- years=years,
- months=months,
- )
-
-
-def interval(start: DateTime, end: DateTime, absolute: bool = False) -> Interval:
- """
- Create an Interval instance.
- """
- return Interval(start, end, absolute=absolute)
-
-
-# Testing
-
-_traveller = Traveller(DateTime)
-
-freeze = _traveller.freeze
-travel = _traveller.travel
-travel_to = _traveller.travel_to
-travel_back = _traveller.travel_back
-
-__all__ = [
- "__version__",
- "DAYS_PER_WEEK",
- "FRIDAY",
- "HOURS_PER_DAY",
- "MINUTES_PER_HOUR",
- "MONDAY",
- "MONTHS_PER_YEAR",
- "SATURDAY",
- "SECONDS_PER_DAY",
- "SECONDS_PER_HOUR",
- "SECONDS_PER_MINUTE",
- "SUNDAY",
- "THURSDAY",
- "TUESDAY",
- "WEDNESDAY",
- "WEEKS_PER_YEAR",
- "YEARS_PER_CENTURY",
- "YEARS_PER_DECADE",
- "Date",
- "DateTime",
- "Duration",
- "Formatter",
- "date",
- "datetime",
- "duration",
- "format_diff",
- "freeze",
- "from_format",
- "from_timestamp",
- "get_locale",
- "instance",
- "interval",
- "local",
- "locale",
- "naive",
- "now",
- "set_locale",
- "week_ends_at",
- "week_starts_at",
- "parse",
- "Interval",
- "Time",
- "UTC",
- "local_timezone",
- "set_local_timezone",
- "test_local_timezone",
- "time",
- "timezone",
- "timezones",
- "today",
- "tomorrow",
- "travel",
- "travel_back",
- "travel_to",
- "FixedTimezone",
- "Timezone",
- "yesterday",
-]
diff --git a/pendulum/__version__.py b/pendulum/__version__.py
deleted file mode 100644
index 29e86a8..0000000
--- a/pendulum/__version__.py
+++ /dev/null
@@ -1 +0,0 @@
-__version__ = "3.0.0a"
diff --git a/pendulum/_extensions/__init__.py b/pendulum/_extensions/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/_extensions/__init__.py
+++ /dev/null
diff --git a/pendulum/_extensions/_helpers.c b/pendulum/_extensions/_helpers.c
deleted file mode 100644
index a3114d9..0000000
--- a/pendulum/_extensions/_helpers.c
+++ /dev/null
@@ -1,931 +0,0 @@
-/* ------------------------------------------------------------------------- */
-
-#include <Python.h>
-#include <datetime.h>
-#include <structmember.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-/* ------------------------------------------------------------------------- */
-
-#define EPOCH_YEAR 1970
-
-#define DAYS_PER_N_YEAR 365
-#define DAYS_PER_L_YEAR 366
-
-#define USECS_PER_SEC 1000000
-
-#define SECS_PER_MIN 60
-#define SECS_PER_HOUR (60 * SECS_PER_MIN)
-#define SECS_PER_DAY (SECS_PER_HOUR * 24)
-
-// 400-year chunks always have 146097 days (20871 weeks).
-#define DAYS_PER_400_YEARS 146097L
-#define SECS_PER_400_YEARS ((int64_t)DAYS_PER_400_YEARS * (int64_t)SECS_PER_DAY)
-
-// The number of seconds in an aligned 100-year chunk, for those that
-// do not begin with a leap year and those that do respectively.
-const int64_t SECS_PER_100_YEARS[2] = {
- (uint64_t)(76L * DAYS_PER_N_YEAR + 24L * DAYS_PER_L_YEAR) * SECS_PER_DAY,
- (uint64_t)(75L * DAYS_PER_N_YEAR + 25L * DAYS_PER_L_YEAR) * SECS_PER_DAY};
-
-// The number of seconds in an aligned 4-year chunk, for those that
-// do not begin with a leap year and those that do respectively.
-const int32_t SECS_PER_4_YEARS[2] = {
- (4 * DAYS_PER_N_YEAR + 0 * DAYS_PER_L_YEAR) * SECS_PER_DAY,
- (3 * DAYS_PER_N_YEAR + 1 * DAYS_PER_L_YEAR) * SECS_PER_DAY};
-
-// The number of seconds in non-leap and leap years respectively.
-const int32_t SECS_PER_YEAR[2] = {
- DAYS_PER_N_YEAR * SECS_PER_DAY,
- DAYS_PER_L_YEAR *SECS_PER_DAY};
-
-#define MONTHS_PER_YEAR 12
-
-// The month lengths in non-leap and leap years respectively.
-const int32_t DAYS_PER_MONTHS[2][13] = {
- {-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
- {-1, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
-
-// The day offsets of the beginning of each (1-based) month in non-leap
-// and leap years respectively.
-// For example, in a leap year there are 335 days before December.
-const int32_t MONTHS_OFFSETS[2][14] = {
- {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
- {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}};
-
-const int DAY_OF_WEEK_TABLE[12] = {
- 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
-
-#define TM_SUNDAY 0
-#define TM_MONDAY 1
-#define TM_TUESDAY 2
-#define TM_WEDNESDAY 3
-#define TM_THURSDAY 4
-#define TM_FRIDAY 5
-#define TM_SATURDAY 6
-
-#define TM_JANUARY 0
-#define TM_FEBRUARY 1
-#define TM_MARCH 2
-#define TM_APRIL 3
-#define TM_MAY 4
-#define TM_JUNE 5
-#define TM_JULY 6
-#define TM_AUGUST 7
-#define TM_SEPTEMBER 8
-#define TM_OCTOBER 9
-#define TM_NOVEMBER 10
-#define TM_DECEMBER 11
-
-/* ------------------------------------------------------------------------- */
-
-int _p(int y)
-{
- return y + y / 4 - y / 100 + y / 400;
-}
-
-int _is_leap(int year)
-{
- return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
-}
-
-int _is_long_year(int year)
-{
- return (_p(year) % 7 == 4) || (_p(year - 1) % 7 == 3);
-}
-
-int _week_day(int year, int month, int day)
-{
- int y;
- int w;
-
- y = year - (month < 3);
-
- w = (_p(y) + DAY_OF_WEEK_TABLE[month - 1] + day) % 7;
-
- if (!w)
- {
- w = 7;
- }
-
- return w;
-}
-
-int _days_in_year(int year)
-{
- if (_is_leap(year))
- {
- return DAYS_PER_L_YEAR;
- }
-
- return DAYS_PER_N_YEAR;
-}
-
-int _day_number(int year, int month, int day)
-{
- month = (month + 9) % 12;
- year = year - month / 10;
-
- return (
- 365 * year + year / 4 - year / 100 + year / 400 + (month * 306 + 5) / 10 + (day - 1));
-}
-
-int _get_offset(PyObject *dt)
-{
- PyObject *tzinfo;
- PyObject *offset;
-
- tzinfo = ((PyDateTime_DateTime *)(dt))->tzinfo;
-
- if (tzinfo != Py_None)
- {
- offset = PyObject_CallMethod(tzinfo, "utcoffset", "O", dt);
-
- return PyDateTime_DELTA_GET_DAYS(offset) * SECS_PER_DAY + PyDateTime_DELTA_GET_SECONDS(offset);
- }
-
- return 0;
-}
-
-int _has_tzinfo(PyObject *dt)
-{
- return ((_PyDateTime_BaseTZInfo *)(dt))->hastzinfo;
-}
-
-char *_get_tz_name(PyObject *dt)
-{
- PyObject *tzinfo;
- char *tz = "";
-
- tzinfo = ((PyDateTime_DateTime *)(dt))->tzinfo;
-
- if (tzinfo != Py_None)
- {
- if (PyObject_HasAttrString(tzinfo, "key"))
- {
- // zoneinfo timezone
- tz = (char *)PyUnicode_AsUTF8(
- PyObject_GetAttrString(tzinfo, "name"));
- }
- else if (PyObject_HasAttrString(tzinfo, "name"))
- {
- // Pendulum timezone
- tz = (char *)PyUnicode_AsUTF8(
- PyObject_GetAttrString(tzinfo, "name"));
- }
- else if (PyObject_HasAttrString(tzinfo, "zone"))
- {
- // pytz timezone
- tz = (char *)PyUnicode_AsUTF8(
- PyObject_GetAttrString(tzinfo, "zone"));
- }
- }
-
- return tz;
-}
-
-/* ------------------------ Custom Types ------------------------------- */
-
-/*
- * class Diff():
- */
-typedef struct
-{
- PyObject_HEAD int years;
- int months;
- int days;
- int hours;
- int minutes;
- int seconds;
- int microseconds;
- int total_days;
-} Diff;
-
-/*
- * def __init__(self, years, months, days, hours, minutes, seconds, microseconds, total_days):
- * self.years = years
- * # ...
-*/
-static int Diff_init(Diff *self, PyObject *args, PyObject *kwargs)
-{
- int years;
- int months;
- int days;
- int hours;
- int minutes;
- int seconds;
- int microseconds;
- int total_days;
-
- if (!PyArg_ParseTuple(args, "iiiiiii", &years, &months, &days, &hours, &minutes, &seconds, &microseconds, &total_days))
- return -1;
-
- self->years = years;
- self->months = months;
- self->days = days;
- self->hours = hours;
- self->minutes = minutes;
- self->seconds = seconds;
- self->microseconds = microseconds;
- self->total_days = total_days;
-
- return 0;
-}
-
-/*
- * def __repr__(self):
- * return '{} years {} months {} days {} hours {} minutes {} seconds {} microseconds'.format(
- * self.years, self.months, self.days, self.minutes, self.hours, self.seconds, self.microseconds
- * )
- */
-static PyObject *Diff_repr(Diff *self)
-{
- return PyUnicode_FromFormat(
- "%d years %d months %d days %d hours %d minutes %d seconds %d microseconds",
- self->years,
- self->months,
- self->days,
- self->hours,
- self->minutes,
- self->seconds,
- self->microseconds);
-}
-
-/*
- * Instantiate new Diff_type object
- * Skip overhead of calling PyObject_New and PyObject_Init.
- * Directly allocate object.
- */
-static PyObject *new_diff_ex(int years, int months, int days, int hours, int minutes, int seconds, int microseconds, int total_days, PyTypeObject *type)
-{
- Diff *self = (Diff *)(type->tp_alloc(type, 0));
-
- if (self != NULL)
- {
- self->years = years;
- self->months = months;
- self->days = days;
- self->hours = hours;
- self->minutes = minutes;
- self->seconds = seconds;
- self->microseconds = microseconds;
- self->total_days = total_days;
- }
-
- return (PyObject *)self;
-}
-
-/*
- * Class member / class attributes
- */
-static PyMemberDef Diff_members[] = {
- {"years", T_INT, offsetof(Diff, years), 0, "years in diff"},
- {"months", T_INT, offsetof(Diff, months), 0, "months in diff"},
- {"days", T_INT, offsetof(Diff, days), 0, "days in diff"},
- {"hours", T_INT, offsetof(Diff, hours), 0, "hours in diff"},
- {"minutes", T_INT, offsetof(Diff, minutes), 0, "minutes in diff"},
- {"seconds", T_INT, offsetof(Diff, seconds), 0, "seconds in diff"},
- {"microseconds", T_INT, offsetof(Diff, microseconds), 0, "microseconds in diff"},
- {"total_days", T_INT, offsetof(Diff, total_days), 0, "total days in diff"},
- {NULL}};
-
-static PyTypeObject Diff_type = {
- PyVarObject_HEAD_INIT(NULL, 0) "PreciseDiff", /* tp_name */
- sizeof(Diff), /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_as_async */
- (reprfunc)Diff_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)Diff_repr, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
- "Precise difference between two datetime objects", /* tp_doc */
-};
-
-#define new_diff(years, months, days, hours, minutes, seconds, microseconds, total_days) new_diff_ex(years, months, days, hours, minutes, seconds, microseconds, total_days, &Diff_type)
-
-/* -------------------------- Functions --------------------------*/
-
-PyObject *is_leap(PyObject *self, PyObject *args)
-{
- PyObject *leap;
- int year;
-
- if (!PyArg_ParseTuple(args, "i", &year))
- {
- PyErr_SetString(
- PyExc_ValueError, "Invalid parameters");
- return NULL;
- }
-
- leap = PyBool_FromLong(_is_leap(year));
-
- return leap;
-}
-
-PyObject *is_long_year(PyObject *self, PyObject *args)
-{
- PyObject *is_long;
- int year;
-
- if (!PyArg_ParseTuple(args, "i", &year))
- {
- PyErr_SetString(
- PyExc_ValueError, "Invalid parameters");
- return NULL;
- }
-
- is_long = PyBool_FromLong(_is_long_year(year));
-
- return is_long;
-}
-
-PyObject *week_day(PyObject *self, PyObject *args)
-{
- PyObject *wd;
- int year;
- int month;
- int day;
-
- if (!PyArg_ParseTuple(args, "iii", &year, &month, &day))
- {
- PyErr_SetString(
- PyExc_ValueError, "Invalid parameters");
- return NULL;
- }
-
- wd = PyLong_FromLong(_week_day(year, month, day));
-
- return wd;
-}
-
-PyObject *days_in_year(PyObject *self, PyObject *args)
-{
- PyObject *ndays;
- int year;
-
- if (!PyArg_ParseTuple(args, "i", &year))
- {
- PyErr_SetString(
- PyExc_ValueError, "Invalid parameters");
- return NULL;
- }
-
- ndays = PyLong_FromLong(_days_in_year(year));
-
- return ndays;
-}
-
-PyObject *timestamp(PyObject *self, PyObject *args)
-{
- int64_t result;
- PyObject *dt;
-
- if (!PyArg_ParseTuple(args, "O", &dt))
- {
- PyErr_SetString(
- PyExc_ValueError, "Invalid parameters");
- return NULL;
- }
-
- int year = (double)PyDateTime_GET_YEAR(dt);
- int month = PyDateTime_GET_MONTH(dt);
- int day = PyDateTime_GET_DAY(dt);
- int hour = PyDateTime_DATE_GET_HOUR(dt);
- int minute = PyDateTime_DATE_GET_MINUTE(dt);
- int second = PyDateTime_DATE_GET_SECOND(dt);
-
- result = (year - 1970) * 365 + MONTHS_OFFSETS[0][month];
- result += (int)floor((double)(year - 1968) / 4);
- result -= (year - 1900) / 100;
- result += (year - 1600) / 400;
-
- if (_is_leap(year) && month < 3)
- {
- result -= 1;
- }
-
- result += day - 1;
- result *= 24;
- result += hour;
- result *= 60;
- result += minute;
- result *= 60;
- result += second;
-
- return PyLong_FromSsize_t(result);
-}
-
-PyObject *local_time(PyObject *self, PyObject *args)
-{
- double unix_time;
- int32_t utc_offset;
- int32_t year;
- int32_t microsecond;
- int64_t seconds;
- int32_t leap_year;
- int64_t sec_per_100years;
- int64_t sec_per_4years;
- int32_t sec_per_year;
- int32_t month;
- int32_t day;
- int32_t month_offset;
- int32_t hour;
- int32_t minute;
- int32_t second;
-
- if (!PyArg_ParseTuple(args, "dii", &unix_time, &utc_offset, &microsecond))
- {
- PyErr_SetString(
- PyExc_ValueError, "Invalid parameters");
- return NULL;
- }
-
- year = EPOCH_YEAR;
- seconds = (int64_t)floor(unix_time);
-
- // Shift to a base year that is 400-year aligned.
- if (seconds >= 0)
- {
- seconds -= 10957L * SECS_PER_DAY;
- year += 30; // == 2000;
- }
- else
- {
- seconds += (int64_t)(146097L - 10957L) * SECS_PER_DAY;
- year -= 370; // == 1600;
- }
-
- seconds += utc_offset;
-
- // Handle years in chunks of 400/100/4/1
- year += 400 * (seconds / SECS_PER_400_YEARS);
- seconds %= SECS_PER_400_YEARS;
- if (seconds < 0)
- {
- seconds += SECS_PER_400_YEARS;
- year -= 400;
- }
-
- leap_year = 1; // 4-century aligned
-
- sec_per_100years = SECS_PER_100_YEARS[leap_year];
-
- while (seconds >= sec_per_100years)
- {
- seconds -= sec_per_100years;
- year += 100;
- leap_year = 0; // 1-century, non 4-century aligned
- sec_per_100years = SECS_PER_100_YEARS[leap_year];
- }
-
- sec_per_4years = SECS_PER_4_YEARS[leap_year];
- while (seconds >= sec_per_4years)
- {
- seconds -= sec_per_4years;
- year += 4;
- leap_year = 1; // 4-year, non century aligned
- sec_per_4years = SECS_PER_4_YEARS[leap_year];
- }
-
- sec_per_year = SECS_PER_YEAR[leap_year];
- while (seconds >= sec_per_year)
- {
- seconds -= sec_per_year;
- year += 1;
- leap_year = 0; // non 4-year aligned
- sec_per_year = SECS_PER_YEAR[leap_year];
- }
-
- // Handle months and days
- month = TM_DECEMBER + 1;
- day = seconds / SECS_PER_DAY + 1;
- seconds %= SECS_PER_DAY;
- while (month != TM_JANUARY + 1)
- {
- month_offset = MONTHS_OFFSETS[leap_year][month];
- if (day > month_offset)
- {
- day -= month_offset;
- break;
- }
-
- month -= 1;
- }
-
- // Handle hours, minutes and seconds
- hour = seconds / SECS_PER_HOUR;
- seconds %= SECS_PER_HOUR;
- minute = seconds / SECS_PER_MIN;
- second = seconds % SECS_PER_MIN;
-
- return Py_BuildValue("NNNNNNN",
- PyLong_FromLong(year),
- PyLong_FromLong(month),
- PyLong_FromLong(day),
- PyLong_FromLong(hour),
- PyLong_FromLong(minute),
- PyLong_FromLong(second),
- PyLong_FromLong(microsecond));
-}
-
-// Calculate a precise difference between two datetimes.
-PyObject *precise_diff(PyObject *self, PyObject *args)
-{
- PyObject *dt1;
- PyObject *dt2;
-
- if (!PyArg_ParseTuple(args, "OO", &dt1, &dt2))
- {
- PyErr_SetString(
- PyExc_ValueError, "Invalid parameters");
- return NULL;
- }
-
- int year_diff = 0;
- int month_diff = 0;
- int day_diff = 0;
- int hour_diff = 0;
- int minute_diff = 0;
- int second_diff = 0;
- int microsecond_diff = 0;
- int sign = 1;
- int year;
- int month;
- int leap;
- int days_in_last_month;
- int days_in_month;
- int dt1_year = PyDateTime_GET_YEAR(dt1);
- int dt2_year = PyDateTime_GET_YEAR(dt2);
- int dt1_month = PyDateTime_GET_MONTH(dt1);
- int dt2_month = PyDateTime_GET_MONTH(dt2);
- int dt1_day = PyDateTime_GET_DAY(dt1);
- int dt2_day = PyDateTime_GET_DAY(dt2);
- int dt1_hour = 0;
- int dt2_hour = 0;
- int dt1_minute = 0;
- int dt2_minute = 0;
- int dt1_second = 0;
- int dt2_second = 0;
- int dt1_microsecond = 0;
- int dt2_microsecond = 0;
- int dt1_total_seconds = 0;
- int dt2_total_seconds = 0;
- int dt1_offset = 0;
- int dt2_offset = 0;
- int dt1_is_datetime = PyDateTime_Check(dt1);
- int dt2_is_datetime = PyDateTime_Check(dt2);
- char *tz1 = "";
- char *tz2 = "";
- int in_same_tz = 0;
- int total_days = (_day_number(dt2_year, dt2_month, dt2_day) - _day_number(dt1_year, dt1_month, dt1_day));
-
- // If both dates are datetimes, we check
- // If we are in the same timezone
- if (dt1_is_datetime && dt2_is_datetime)
- {
- if (_has_tzinfo(dt1))
- {
- tz1 = _get_tz_name(dt1);
- dt1_offset = _get_offset(dt1);
- }
-
- if (_has_tzinfo(dt2))
- {
- tz2 = _get_tz_name(dt2);
- dt2_offset = _get_offset(dt2);
- }
-
- in_same_tz = tz1 == tz2 && strncmp(tz1, "", 1);
- }
-
- // If we have datetimes (and not only dates)
- // we get the information we need
- if (dt1_is_datetime)
- {
- dt1_hour = PyDateTime_DATE_GET_HOUR(dt1);
- dt1_minute = PyDateTime_DATE_GET_MINUTE(dt1);
- dt1_second = PyDateTime_DATE_GET_SECOND(dt1);
- dt1_microsecond = PyDateTime_DATE_GET_MICROSECOND(dt1);
-
- if ((!in_same_tz && dt1_offset != 0) || total_days == 0)
- {
- dt1_hour -= dt1_offset / SECS_PER_HOUR;
- dt1_offset %= SECS_PER_HOUR;
- dt1_minute -= dt1_offset / SECS_PER_MIN;
- dt1_offset %= SECS_PER_MIN;
- dt1_second -= dt1_offset;
-
- if (dt1_second < 0)
- {
- dt1_second += 60;
- dt1_minute -= 1;
- }
- else if (dt1_second > 60)
- {
- dt1_second -= 60;
- dt1_minute += 1;
- }
-
- if (dt1_minute < 0)
- {
- dt1_minute += 60;
- dt1_hour -= 1;
- }
- else if (dt1_minute > 60)
- {
- dt1_minute -= 60;
- dt1_hour += 1;
- }
-
- if (dt1_hour < 0)
- {
- dt1_hour += 24;
- dt1_day -= 1;
- }
- else if (dt1_hour > 24)
- {
- dt1_hour -= 24;
- dt1_day += 1;
- }
- }
-
- dt1_total_seconds = (dt1_hour * SECS_PER_HOUR + dt1_minute * SECS_PER_MIN + dt1_second);
- }
-
- if (dt2_is_datetime)
- {
- dt2_hour = PyDateTime_DATE_GET_HOUR(dt2);
- dt2_minute = PyDateTime_DATE_GET_MINUTE(dt2);
- dt2_second = PyDateTime_DATE_GET_SECOND(dt2);
- dt2_microsecond = PyDateTime_DATE_GET_MICROSECOND(dt2);
-
- if ((!in_same_tz && dt2_offset != 0) || total_days == 0)
- {
- dt2_hour -= dt2_offset / SECS_PER_HOUR;
- dt2_offset %= SECS_PER_HOUR;
- dt2_minute -= dt2_offset / SECS_PER_MIN;
- dt2_offset %= SECS_PER_MIN;
- dt2_second -= dt2_offset;
-
- if (dt2_second < 0)
- {
- dt2_second += 60;
- dt2_minute -= 1;
- }
- else if (dt2_second > 60)
- {
- dt2_second -= 60;
- dt2_minute += 1;
- }
-
- if (dt2_minute < 0)
- {
- dt2_minute += 60;
- dt2_hour -= 1;
- }
- else if (dt2_minute > 60)
- {
- dt2_minute -= 60;
- dt2_hour += 1;
- }
-
- if (dt2_hour < 0)
- {
- dt2_hour += 24;
- dt2_day -= 1;
- }
- else if (dt2_hour > 24)
- {
- dt2_hour -= 24;
- dt2_day += 1;
- }
- }
-
- dt2_total_seconds = (dt2_hour * SECS_PER_HOUR + dt2_minute * SECS_PER_MIN + dt2_second);
- }
-
- // Direct comparison between two datetimes does not work
- // so we need to check by properties
- int dt1_gt_dt2 = (dt1_year > dt2_year || (dt1_year == dt2_year && dt1_month > dt2_month) || (dt1_year == dt2_year && dt1_month == dt2_month && dt1_day > dt2_day) || (dt1_year == dt2_year && dt1_month == dt2_month && dt1_day == dt2_day && dt1_total_seconds > dt2_total_seconds) || (dt1_year == dt2_year && dt1_month == dt2_month && dt1_day == dt2_day && dt1_total_seconds == dt2_total_seconds && dt1_microsecond > dt2_microsecond));
-
- if (dt1_gt_dt2)
- {
- PyObject *temp;
- temp = dt1;
- dt1 = dt2;
- dt2 = temp;
- sign = -1;
-
- // Retrieving properties
- dt1_year = PyDateTime_GET_YEAR(dt1);
- dt2_year = PyDateTime_GET_YEAR(dt2);
- dt1_month = PyDateTime_GET_MONTH(dt1);
- dt2_month = PyDateTime_GET_MONTH(dt2);
- dt1_day = PyDateTime_GET_DAY(dt1);
- dt2_day = PyDateTime_GET_DAY(dt2);
-
- if (dt2_is_datetime)
- {
- dt1_hour = PyDateTime_DATE_GET_HOUR(dt1);
- dt1_minute = PyDateTime_DATE_GET_MINUTE(dt1);
- dt1_second = PyDateTime_DATE_GET_SECOND(dt1);
- dt1_microsecond = PyDateTime_DATE_GET_MICROSECOND(dt1);
- }
-
- if (dt1_is_datetime)
- {
- dt2_hour = PyDateTime_DATE_GET_HOUR(dt2);
- dt2_minute = PyDateTime_DATE_GET_MINUTE(dt2);
- dt2_second = PyDateTime_DATE_GET_SECOND(dt2);
- dt2_microsecond = PyDateTime_DATE_GET_MICROSECOND(dt2);
- }
-
- total_days = (_day_number(dt2_year, dt2_month, dt2_day) - _day_number(dt1_year, dt1_month, dt1_day));
- }
-
- year_diff = dt2_year - dt1_year;
- month_diff = dt2_month - dt1_month;
- day_diff = dt2_day - dt1_day;
- hour_diff = dt2_hour - dt1_hour;
- minute_diff = dt2_minute - dt1_minute;
- second_diff = dt2_second - dt1_second;
- microsecond_diff = dt2_microsecond - dt1_microsecond;
-
- if (microsecond_diff < 0)
- {
- microsecond_diff += 1e6;
- second_diff -= 1;
- }
-
- if (second_diff < 0)
- {
- second_diff += 60;
- minute_diff -= 1;
- }
-
- if (minute_diff < 0)
- {
- minute_diff += 60;
- hour_diff -= 1;
- }
-
- if (hour_diff < 0)
- {
- hour_diff += 24;
- day_diff -= 1;
- }
-
- if (day_diff < 0)
- {
- // If we have a difference in days,
- // we have to check if they represent months
- year = dt2_year;
- month = dt2_month;
-
- if (month == 1)
- {
- month = 12;
- year -= 1;
- }
- else
- {
- month -= 1;
- }
-
- leap = _is_leap(year);
-
- days_in_last_month = DAYS_PER_MONTHS[leap][month];
- days_in_month = DAYS_PER_MONTHS[_is_leap(dt2_year)][dt2_month];
-
- if (day_diff < days_in_month - days_in_last_month)
- {
- // We don't have a full month, we calculate days
- if (days_in_last_month < dt1_day)
- {
- day_diff += dt1_day;
- }
- else
- {
- day_diff += days_in_last_month;
- }
- }
- else if (day_diff == days_in_month - days_in_last_month)
- {
- // We have exactly a full month
- // We remove the days difference
- // and add one to the months difference
- day_diff = 0;
- month_diff += 1;
- }
- else
- {
- // We have a full month
- day_diff += days_in_last_month;
- }
-
- month_diff -= 1;
- }
-
- if (month_diff < 0)
- {
- month_diff += 12;
- year_diff -= 1;
- }
-
- return new_diff(
- year_diff * sign,
- month_diff * sign,
- day_diff * sign,
- hour_diff * sign,
- minute_diff * sign,
- second_diff * sign,
- microsecond_diff * sign,
- total_days * sign);
-}
-
-/* ------------------------------------------------------------------------- */
-
-static PyMethodDef helpers_methods[] = {
- {"is_leap",
- (PyCFunction)is_leap,
- METH_VARARGS,
- PyDoc_STR("Checks if a year is a leap year.")},
- {"is_long_year",
- (PyCFunction)is_long_year,
- METH_VARARGS,
- PyDoc_STR("Checks if a year is a long year.")},
- {"week_day",
- (PyCFunction)week_day,
- METH_VARARGS,
- PyDoc_STR("Returns the weekday number.")},
- {"days_in_year",
- (PyCFunction)days_in_year,
- METH_VARARGS,
- PyDoc_STR("Returns the number of days in the given year.")},
- {"timestamp",
- (PyCFunction)timestamp,
- METH_VARARGS,
- PyDoc_STR("Returns the timestamp of the given datetime.")},
- {"local_time",
- (PyCFunction)local_time,
- METH_VARARGS,
- PyDoc_STR("Returns a UNIX time as a broken down time for a particular transition type.")},
- {"precise_diff",
- (PyCFunction)precise_diff,
- METH_VARARGS,
- PyDoc_STR("Calculate a precise difference between two datetimes.")},
- {NULL}};
-
-/* ------------------------------------------------------------------------- */
-
-static struct PyModuleDef moduledef = {
- PyModuleDef_HEAD_INIT,
- "_helpers",
- NULL,
- -1,
- helpers_methods,
- NULL,
- NULL,
- NULL,
- NULL,
-};
-
-PyMODINIT_FUNC
-PyInit__helpers(void)
-{
- PyObject *module;
-
- PyDateTime_IMPORT;
-
- module = PyModule_Create(&moduledef);
-
- if (module == NULL)
- return NULL;
-
- // Diff declaration
- Diff_type.tp_new = PyType_GenericNew;
- Diff_type.tp_members = Diff_members;
- Diff_type.tp_init = (initproc)Diff_init;
-
- if (PyType_Ready(&Diff_type) < 0)
- return NULL;
-
- PyModule_AddObject(module, "PreciseDiff", (PyObject *)&Diff_type);
-
- return module;
-}
diff --git a/pendulum/_extensions/_helpers.pyi b/pendulum/_extensions/_helpers.pyi
deleted file mode 100644
index 99a5397..0000000
--- a/pendulum/_extensions/_helpers.pyi
+++ /dev/null
@@ -1,31 +0,0 @@
-from __future__ import annotations
-
-from collections import namedtuple
-from datetime import date
-from datetime import datetime
-
-def days_in_year(year: int) -> int: ...
-def is_leap(year: int) -> bool: ...
-def is_long_year(year: int) -> bool: ...
-def local_time(
- unix_time: int, utc_offset: int, microseconds: int
-) -> tuple[int, int, int, int, int, int, int]: ...
-
-class PreciseDiff(
- namedtuple(
- "PreciseDiff",
- "years months days " "hours minutes seconds microseconds " "total_days",
- )
-):
- years: int
- months: int
- days: int
- hours: int
- minutes: int
- seconds: int
- microseconds: int
- total_days: int
-
-def precise_diff(d1: datetime | date, d2: datetime | date) -> PreciseDiff: ...
-def timestamp(dt: datetime) -> int: ...
-def week_day(year: int, month: int, day: int) -> int: ...
diff --git a/pendulum/_extensions/helpers.py b/pendulum/_extensions/helpers.py
deleted file mode 100644
index 01066a3..0000000
--- a/pendulum/_extensions/helpers.py
+++ /dev/null
@@ -1,364 +0,0 @@
-from __future__ import annotations
-
-import datetime
-import math
-
-from collections import namedtuple
-from typing import cast
-
-from pendulum.constants import DAY_OF_WEEK_TABLE
-from pendulum.constants import DAYS_PER_L_YEAR
-from pendulum.constants import DAYS_PER_MONTHS
-from pendulum.constants import DAYS_PER_N_YEAR
-from pendulum.constants import EPOCH_YEAR
-from pendulum.constants import MONTHS_OFFSETS
-from pendulum.constants import SECS_PER_4_YEARS
-from pendulum.constants import SECS_PER_100_YEARS
-from pendulum.constants import SECS_PER_400_YEARS
-from pendulum.constants import SECS_PER_DAY
-from pendulum.constants import SECS_PER_HOUR
-from pendulum.constants import SECS_PER_MIN
-from pendulum.constants import SECS_PER_YEAR
-from pendulum.constants import TM_DECEMBER
-from pendulum.constants import TM_JANUARY
-from pendulum.tz.timezone import Timezone
-from pendulum.utils._compat import zoneinfo
-
-
-class PreciseDiff(
- namedtuple(
- "PreciseDiff",
- "years months days " "hours minutes seconds microseconds " "total_days",
- )
-):
- years: int
- months: int
- days: int
- hours: int
- minutes: int
- seconds: int
- microseconds: int
- total_days: int
-
- def __repr__(self) -> str:
- return (
- f"{self.years} years "
- f"{self.months} months "
- f"{self.days} days "
- f"{self.hours} hours "
- f"{self.minutes} minutes "
- f"{self.seconds} seconds "
- f"{self.microseconds} microseconds"
- )
-
-
-def is_leap(year: int) -> bool:
- return year % 4 == 0 and (year % 100 != 0 or year % 400 == 0)
-
-
-def is_long_year(year: int) -> bool:
- def p(y: int) -> int:
- return y + y // 4 - y // 100 + y // 400
-
- return p(year) % 7 == 4 or p(year - 1) % 7 == 3
-
-
-def week_day(year: int, month: int, day: int) -> int:
- if month < 3:
- year -= 1
-
- w = (
- year
- + year // 4
- - year // 100
- + year // 400
- + DAY_OF_WEEK_TABLE[month - 1]
- + day
- ) % 7
-
- if not w:
- w = 7
-
- return w
-
-
-def days_in_year(year: int) -> int:
- if is_leap(year):
- return DAYS_PER_L_YEAR
-
- return DAYS_PER_N_YEAR
-
-
-def timestamp(dt: datetime.datetime) -> int:
- year = dt.year
-
- result = (year - 1970) * 365 + MONTHS_OFFSETS[0][dt.month]
- result += (year - 1968) // 4
- result -= (year - 1900) // 100
- result += (year - 1600) // 400
-
- if is_leap(year) and dt.month < 3:
- result -= 1
-
- result += dt.day - 1
- result *= 24
- result += dt.hour
- result *= 60
- result += dt.minute
- result *= 60
- result += dt.second
-
- return result
-
-
-def local_time(
- unix_time: int, utc_offset: int, microseconds: int
-) -> tuple[int, int, int, int, int, int, int]:
- """
- Returns a UNIX time as a broken-down time
- for a particular transition type.
- """
- year = EPOCH_YEAR
- seconds = int(math.floor(unix_time))
-
- # Shift to a base year that is 400-year aligned.
- if seconds >= 0:
- seconds -= 10957 * SECS_PER_DAY
- year += 30 # == 2000
- else:
- seconds += (146097 - 10957) * SECS_PER_DAY
- year -= 370 # == 1600
-
- seconds += utc_offset
-
- # Handle years in chunks of 400/100/4/1
- year += 400 * (seconds // SECS_PER_400_YEARS)
- seconds %= SECS_PER_400_YEARS
- if seconds < 0:
- seconds += SECS_PER_400_YEARS
- year -= 400
-
- leap_year = 1 # 4-century aligned
-
- sec_per_100years = SECS_PER_100_YEARS[leap_year]
- while seconds >= sec_per_100years:
- seconds -= sec_per_100years
- year += 100
- leap_year = 0 # 1-century, non 4-century aligned
- sec_per_100years = SECS_PER_100_YEARS[leap_year]
-
- sec_per_4years = SECS_PER_4_YEARS[leap_year]
- while seconds >= sec_per_4years:
- seconds -= sec_per_4years
- year += 4
- leap_year = 1 # 4-year, non century aligned
- sec_per_4years = SECS_PER_4_YEARS[leap_year]
-
- sec_per_year = SECS_PER_YEAR[leap_year]
- while seconds >= sec_per_year:
- seconds -= sec_per_year
- year += 1
- leap_year = 0 # non 4-year aligned
- sec_per_year = SECS_PER_YEAR[leap_year]
-
- # Handle months and days
- month = TM_DECEMBER + 1
- day = seconds // SECS_PER_DAY + 1
- seconds %= SECS_PER_DAY
- while month != TM_JANUARY + 1:
- month_offset = MONTHS_OFFSETS[leap_year][month]
- if day > month_offset:
- day -= month_offset
- break
-
- month -= 1
-
- # Handle hours, minutes, seconds and microseconds
- hour = seconds // SECS_PER_HOUR
- seconds %= SECS_PER_HOUR
- minute = seconds // SECS_PER_MIN
- second = seconds % SECS_PER_MIN
-
- return year, month, day, hour, minute, second, microseconds
-
-
-def precise_diff(
- d1: datetime.datetime | datetime.date, d2: datetime.datetime | datetime.date
-) -> PreciseDiff:
- """
- Calculate a precise difference between two datetimes.
-
- :param d1: The first datetime
- :param d2: The second datetime
- """
- sign = 1
-
- if d1 == d2:
- return PreciseDiff(0, 0, 0, 0, 0, 0, 0, 0)
-
- tzinfo1: datetime.tzinfo | None = (
- d1.tzinfo if isinstance(d1, datetime.datetime) else None
- )
- tzinfo2: datetime.tzinfo | None = (
- d2.tzinfo if isinstance(d2, datetime.datetime) else None
- )
-
- if (
- tzinfo1 is None
- and tzinfo2 is not None
- or tzinfo2 is None
- and tzinfo1 is not None
- ):
- raise ValueError(
- "Comparison between naive and aware datetimes is not supported"
- )
-
- if d1 > d2:
- d1, d2 = d2, d1
- sign = -1
-
- d_diff = 0
- hour_diff = 0
- min_diff = 0
- sec_diff = 0
- mic_diff = 0
- total_days = _day_number(d2.year, d2.month, d2.day) - _day_number(
- d1.year, d1.month, d1.day
- )
- in_same_tz = False
- tz1 = None
- tz2 = None
-
- # Trying to figure out the timezone names
- # If we can't find them, we assume different timezones
- if tzinfo1 and tzinfo2:
- tz1 = _get_tzinfo_name(tzinfo1)
- tz2 = _get_tzinfo_name(tzinfo2)
-
- in_same_tz = tz1 == tz2 and tz1 is not None
-
- if isinstance(d2, datetime.datetime):
- if isinstance(d1, datetime.datetime):
- # If we are not in the same timezone
- # we need to adjust
- #
- # We also need to adjust if we do not
- # have variable-length units
- if not in_same_tz or total_days == 0:
- offset1 = d1.utcoffset()
- offset2 = d2.utcoffset()
-
- if offset1:
- d1 = d1 - offset1
-
- if offset2:
- d2 = d2 - offset2
-
- hour_diff = d2.hour - d1.hour
- min_diff = d2.minute - d1.minute
- sec_diff = d2.second - d1.second
- mic_diff = d2.microsecond - d1.microsecond
- else:
- hour_diff = d2.hour
- min_diff = d2.minute
- sec_diff = d2.second
- mic_diff = d2.microsecond
-
- if mic_diff < 0:
- mic_diff += 1000000
- sec_diff -= 1
-
- if sec_diff < 0:
- sec_diff += 60
- min_diff -= 1
-
- if min_diff < 0:
- min_diff += 60
- hour_diff -= 1
-
- if hour_diff < 0:
- hour_diff += 24
- d_diff -= 1
-
- y_diff = d2.year - d1.year
- m_diff = d2.month - d1.month
- d_diff += d2.day - d1.day
-
- if d_diff < 0:
- year = d2.year
- month = d2.month
-
- if month == 1:
- month = 12
- year -= 1
- else:
- month -= 1
-
- leap = int(is_leap(year))
-
- days_in_last_month = DAYS_PER_MONTHS[leap][month]
- days_in_month = DAYS_PER_MONTHS[int(is_leap(d2.year))][d2.month]
-
- if d_diff < days_in_month - days_in_last_month:
- # We don't have a full month, we calculate days
- if days_in_last_month < d1.day:
- d_diff += d1.day
- else:
- d_diff += days_in_last_month
- elif d_diff == days_in_month - days_in_last_month:
- # We have exactly a full month
- # We remove the days difference
- # and add one to the months difference
- d_diff = 0
- m_diff += 1
- else:
- # We have a full month
- d_diff += days_in_last_month
-
- m_diff -= 1
-
- if m_diff < 0:
- m_diff += 12
- y_diff -= 1
-
- return PreciseDiff(
- sign * y_diff,
- sign * m_diff,
- sign * d_diff,
- sign * hour_diff,
- sign * min_diff,
- sign * sec_diff,
- sign * mic_diff,
- sign * total_days,
- )
-
-
-def _day_number(year: int, month: int, day: int) -> int:
- month = (month + 9) % 12
- year = year - month // 10
-
- return (
- 365 * year
- + year // 4
- - year // 100
- + year // 400
- + (month * 306 + 5) // 10
- + (day - 1)
- )
-
-
-def _get_tzinfo_name(tzinfo: datetime.tzinfo | None) -> str | None:
- if tzinfo is None:
- return None
-
- if hasattr(tzinfo, "key"):
- # zoneinfo timezone
- return cast(str, cast(zoneinfo.ZoneInfo, tzinfo).key)
- elif hasattr(tzinfo, "name"):
- # Pendulum timezone
- return cast(Timezone, tzinfo).name
- elif hasattr(tzinfo, "zone"):
- # pytz timezone
- return tzinfo.zone # type: ignore
-
- return None
diff --git a/pendulum/constants.py b/pendulum/constants.py
deleted file mode 100644
index a3d2a18..0000000
--- a/pendulum/constants.py
+++ /dev/null
@@ -1,109 +0,0 @@
-# The day constants
-from __future__ import annotations
-
-SUNDAY = 0
-MONDAY = 1
-TUESDAY = 2
-WEDNESDAY = 3
-THURSDAY = 4
-FRIDAY = 5
-SATURDAY = 6
-
-# Number of X in Y.
-YEARS_PER_CENTURY = 100
-YEARS_PER_DECADE = 10
-MONTHS_PER_YEAR = 12
-WEEKS_PER_YEAR = 52
-DAYS_PER_WEEK = 7
-HOURS_PER_DAY = 24
-MINUTES_PER_HOUR = 60
-SECONDS_PER_MINUTE = 60
-SECONDS_PER_HOUR = MINUTES_PER_HOUR * SECONDS_PER_MINUTE
-SECONDS_PER_DAY = HOURS_PER_DAY * SECONDS_PER_HOUR
-US_PER_SECOND = 1000000
-
-# Formats
-ATOM = "YYYY-MM-DDTHH:mm:ssZ"
-COOKIE = "dddd, DD-MMM-YYYY HH:mm:ss zz"
-ISO8601 = "YYYY-MM-DDTHH:mm:ssZ"
-ISO8601_EXTENDED = "YYYY-MM-DDTHH:mm:ss.SSSSSSZ"
-RFC822 = "ddd, DD MMM YY HH:mm:ss ZZ"
-RFC850 = "dddd, DD-MMM-YY HH:mm:ss zz"
-RFC1036 = "ddd, DD MMM YY HH:mm:ss ZZ"
-RFC1123 = "ddd, DD MMM YYYY HH:mm:ss ZZ"
-RFC2822 = "ddd, DD MMM YYYY HH:mm:ss ZZ"
-RFC3339 = ISO8601
-RFC3339_EXTENDED = ISO8601_EXTENDED
-RSS = "ddd, DD MMM YYYY HH:mm:ss ZZ"
-W3C = ISO8601
-
-
-EPOCH_YEAR = 1970
-
-DAYS_PER_N_YEAR = 365
-DAYS_PER_L_YEAR = 366
-
-USECS_PER_SEC = 1000000
-
-SECS_PER_MIN = 60
-SECS_PER_HOUR = 60 * SECS_PER_MIN
-SECS_PER_DAY = SECS_PER_HOUR * 24
-
-# 400-year chunks always have 146097 days (20871 weeks).
-SECS_PER_400_YEARS = 146097 * SECS_PER_DAY
-
-# The number of seconds in an aligned 100-year chunk, for those that
-# do not begin with a leap year and those that do respectively.
-SECS_PER_100_YEARS = (
- (76 * DAYS_PER_N_YEAR + 24 * DAYS_PER_L_YEAR) * SECS_PER_DAY,
- (75 * DAYS_PER_N_YEAR + 25 * DAYS_PER_L_YEAR) * SECS_PER_DAY,
-)
-
-# The number of seconds in an aligned 4-year chunk, for those that
-# do not begin with a leap year and those that do respectively.
-SECS_PER_4_YEARS = (
- (4 * DAYS_PER_N_YEAR + 0 * DAYS_PER_L_YEAR) * SECS_PER_DAY,
- (3 * DAYS_PER_N_YEAR + 1 * DAYS_PER_L_YEAR) * SECS_PER_DAY,
-)
-
-# The number of seconds in non-leap and leap years respectively.
-SECS_PER_YEAR = (DAYS_PER_N_YEAR * SECS_PER_DAY, DAYS_PER_L_YEAR * SECS_PER_DAY)
-
-DAYS_PER_YEAR = (DAYS_PER_N_YEAR, DAYS_PER_L_YEAR)
-
-# The month lengths in non-leap and leap years respectively.
-DAYS_PER_MONTHS = (
- (-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
- (-1, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
-)
-
-# The day offsets of the beginning of each (1-based) month in non-leap
-# and leap years respectively.
-# For example, in a leap year there are 335 days before December.
-MONTHS_OFFSETS = (
- (-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365),
- (-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366),
-)
-
-DAY_OF_WEEK_TABLE = (0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4)
-
-TM_SUNDAY = 0
-TM_MONDAY = 1
-TM_TUESDAY = 2
-TM_WEDNESDAY = 3
-TM_THURSDAY = 4
-TM_FRIDAY = 5
-TM_SATURDAY = 6
-
-TM_JANUARY = 0
-TM_FEBRUARY = 1
-TM_MARCH = 2
-TM_APRIL = 3
-TM_MAY = 4
-TM_JUNE = 5
-TM_JULY = 6
-TM_AUGUST = 7
-TM_SEPTEMBER = 8
-TM_OCTOBER = 9
-TM_NOVEMBER = 10
-TM_DECEMBER = 11
diff --git a/pendulum/date.py b/pendulum/date.py
deleted file mode 100644
index 4e2655b..0000000
--- a/pendulum/date.py
+++ /dev/null
@@ -1,760 +0,0 @@
-from __future__ import annotations
-
-import calendar
-import math
-
-from datetime import date
-from datetime import datetime
-from datetime import timedelta
-from typing import NoReturn
-from typing import cast
-from typing import overload
-
-import pendulum
-
-from pendulum.constants import FRIDAY
-from pendulum.constants import MONDAY
-from pendulum.constants import MONTHS_PER_YEAR
-from pendulum.constants import SATURDAY
-from pendulum.constants import SUNDAY
-from pendulum.constants import THURSDAY
-from pendulum.constants import TUESDAY
-from pendulum.constants import WEDNESDAY
-from pendulum.constants import YEARS_PER_CENTURY
-from pendulum.constants import YEARS_PER_DECADE
-from pendulum.exceptions import PendulumException
-from pendulum.helpers import add_duration
-from pendulum.interval import Interval
-from pendulum.mixins.default import FormattableMixin
-
-
-class Date(FormattableMixin, date):
- # Names of days of the week
- _days = {
- SUNDAY: "Sunday",
- MONDAY: "Monday",
- TUESDAY: "Tuesday",
- WEDNESDAY: "Wednesday",
- THURSDAY: "Thursday",
- FRIDAY: "Friday",
- SATURDAY: "Saturday",
- }
-
- _MODIFIERS_VALID_UNITS = ["day", "week", "month", "year", "decade", "century"]
-
- # Getters/Setters
-
- def set(
- self, year: int | None = None, month: int | None = None, day: int | None = None
- ) -> Date:
- return self.replace(year=year, month=month, day=day)
-
- @property
- def day_of_week(self) -> int:
- """
- Returns the day of the week (0-6).
- """
- return self.isoweekday() % 7
-
- @property
- def day_of_year(self) -> int:
- """
- Returns the day of the year (1-366).
- """
- k = 1 if self.is_leap_year() else 2
-
- return (275 * self.month) // 9 - k * ((self.month + 9) // 12) + self.day - 30
-
- @property
- def week_of_year(self) -> int:
- return self.isocalendar()[1]
-
- @property
- def days_in_month(self) -> int:
- return calendar.monthrange(self.year, self.month)[1]
-
- @property
- def week_of_month(self) -> int:
- first_day_of_month = self.replace(day=1)
-
- return self.week_of_year - first_day_of_month.week_of_year + 1
-
- @property
- def age(self) -> int:
- return self.diff(abs=False).in_years()
-
- @property
- def quarter(self) -> int:
- return int(math.ceil(self.month / 3))
-
- # String Formatting
-
- def to_date_string(self) -> str:
- """
- Format the instance as date.
-
- :rtype: str
- """
- return self.strftime("%Y-%m-%d")
-
- def to_formatted_date_string(self) -> str:
- """
- Format the instance as a readable date.
-
- :rtype: str
- """
- return self.strftime("%b %d, %Y")
-
- def __repr__(self) -> str:
- return f"{self.__class__.__name__}({self.year}, {self.month}, {self.day})"
-
- # COMPARISONS
-
- def closest(self, dt1: date, dt2: date) -> Date:
- """
- Get the closest date from the instance.
- """
- dt1 = self.__class__(dt1.year, dt1.month, dt1.day)
- dt2 = self.__class__(dt2.year, dt2.month, dt2.day)
-
- if self.diff(dt1).in_seconds() < self.diff(dt2).in_seconds():
- return dt1
-
- return dt2
-
- def farthest(self, dt1: date, dt2: date) -> Date:
- """
- Get the farthest date from the instance.
- """
- dt1 = self.__class__(dt1.year, dt1.month, dt1.day)
- dt2 = self.__class__(dt2.year, dt2.month, dt2.day)
-
- if self.diff(dt1).in_seconds() > self.diff(dt2).in_seconds():
- return dt1
-
- return dt2
-
- def is_future(self) -> bool:
- """
- Determines if the instance is in the future, ie. greater than now.
- """
- return self > self.today()
-
- def is_past(self) -> bool:
- """
- Determines if the instance is in the past, ie. less than now.
- """
- return self < self.today()
-
- def is_leap_year(self) -> bool:
- """
- Determines if the instance is a leap year.
- """
- return calendar.isleap(self.year)
-
- def is_long_year(self) -> bool:
- """
- Determines if the instance is a long year
-
- See link `<https://en.wikipedia.org/wiki/ISO_8601#Week_dates>`_
- """
- return Date(self.year, 12, 28).isocalendar()[1] == 53
-
- def is_same_day(self, dt: date) -> bool:
- """
- Checks if the passed in date is the same day as the instance current day.
- """
- return self == dt
-
- def is_anniversary(self, dt: date | None = None) -> bool:
- """
- Check if it's the anniversary.
-
- Compares the date/month values of the two dates.
- """
- if dt is None:
- dt = Date.today()
-
- instance = self.__class__(dt.year, dt.month, dt.day)
-
- return (self.month, self.day) == (instance.month, instance.day)
-
- # the additional method for checking if today is the anniversary day
- # the alias is provided to start using a new name and keep the backward compatibility
- # the old name can be completely replaced with the new in one of the future versions
- is_birthday = is_anniversary
-
- # ADDITIONS AND SUBTRACTIONS
-
- def add(
- self, years: int = 0, months: int = 0, weeks: int = 0, days: int = 0
- ) -> Date:
- """
- Add duration to the instance.
-
- :param years: The number of years
- :param months: The number of months
- :param weeks: The number of weeks
- :param days: The number of days
- """
- dt = add_duration(
- date(self.year, self.month, self.day),
- years=years,
- months=months,
- weeks=weeks,
- days=days,
- )
-
- return self.__class__(dt.year, dt.month, dt.day)
-
- def subtract(
- self, years: int = 0, months: int = 0, weeks: int = 0, days: int = 0
- ) -> Date:
- """
- Remove duration from the instance.
-
- :param years: The number of years
- :param months: The number of months
- :param weeks: The number of weeks
- :param days: The number of days
- """
- return self.add(years=-years, months=-months, weeks=-weeks, days=-days)
-
- def _add_timedelta(self, delta: timedelta) -> Date:
- """
- Add timedelta duration to the instance.
-
- :param delta: The timedelta instance
- """
- if isinstance(delta, pendulum.Duration):
- return self.add(
- years=delta.years,
- months=delta.months,
- weeks=delta.weeks,
- days=delta.remaining_days,
- )
-
- return self.add(days=delta.days)
-
- def _subtract_timedelta(self, delta: timedelta) -> Date:
- """
- Remove timedelta duration from the instance.
-
- :param delta: The timedelta instance
- """
- if isinstance(delta, pendulum.Duration):
- return self.subtract(
- years=delta.years,
- months=delta.months,
- weeks=delta.weeks,
- days=delta.remaining_days,
- )
-
- return self.subtract(days=delta.days)
-
- def __add__(self, other: timedelta) -> Date:
- if not isinstance(other, timedelta):
- return NotImplemented
-
- return self._add_timedelta(other)
-
- @overload
- def __sub__(self, delta: timedelta) -> Date:
- ...
-
- @overload
- def __sub__(self, dt: datetime) -> NoReturn:
- ...
-
- @overload
- def __sub__(self, dt: Date) -> Interval:
- ...
-
- def __sub__(self, other: timedelta | date) -> Date | Interval:
- if isinstance(other, timedelta):
- return self._subtract_timedelta(other)
-
- if not isinstance(other, date):
- return NotImplemented
-
- dt = self.__class__(other.year, other.month, other.day)
-
- return dt.diff(self, False)
-
- # DIFFERENCES
-
- def diff(self, dt: date | None = None, abs: bool = True) -> Interval:
- """
- Returns the difference between two Date objects as an Interval.
-
- :param dt: The date to compare to (defaults to today)
- :param abs: Whether to return an absolute interval or not
- """
- if dt is None:
- dt = self.today()
-
- return Interval(self, Date(dt.year, dt.month, dt.day), absolute=abs)
-
- def diff_for_humans(
- self,
- other: date | None = None,
- absolute: bool = False,
- locale: str | None = None,
- ) -> str:
- """
- Get the difference in a human readable format in the current locale.
-
- When comparing a value in the past to default now:
- 1 day ago
- 5 months ago
-
- When comparing a value in the future to default now:
- 1 day from now
- 5 months from now
-
- When comparing a value in the past to another value:
- 1 day before
- 5 months before
-
- When comparing a value in the future to another value:
- 1 day after
- 5 months after
-
- :param other: The date to compare to (defaults to today)
- :param absolute: removes time difference modifiers ago, after, etc
- :param locale: The locale to use for localization
- """
- is_now = other is None
-
- if is_now:
- other = self.today()
-
- diff = self.diff(other)
-
- return pendulum.format_diff(diff, is_now, absolute, locale)
-
- # MODIFIERS
-
- def start_of(self, unit: str) -> Date:
- """
- Returns a copy of the instance with the time reset
- with the following rules:
-
- * day: time to 00:00:00
- * week: date to first day of the week and time to 00:00:00
- * month: date to first day of the month and time to 00:00:00
- * year: date to first day of the year and time to 00:00:00
- * decade: date to first day of the decade and time to 00:00:00
- * century: date to first day of century and time to 00:00:00
-
- :param unit: The unit to reset to
- """
- if unit not in self._MODIFIERS_VALID_UNITS:
- raise ValueError(f'Invalid unit "{unit}" for start_of()')
-
- return cast(Date, getattr(self, f"_start_of_{unit}")())
-
- def end_of(self, unit: str) -> Date:
- """
- Returns a copy of the instance with the time reset
- with the following rules:
-
- * week: date to last day of the week
- * month: date to last day of the month
- * year: date to last day of the year
- * decade: date to last day of the decade
- * century: date to last day of century
-
- :param unit: The unit to reset to
- """
- if unit not in self._MODIFIERS_VALID_UNITS:
- raise ValueError(f'Invalid unit "{unit}" for end_of()')
-
- return cast(Date, getattr(self, f"_end_of_{unit}")())
-
- def _start_of_day(self) -> Date:
- """
- Compatibility method.
- """
- return self
-
- def _end_of_day(self) -> Date:
- """
- Compatibility method
- """
- return self
-
- def _start_of_month(self) -> Date:
- """
- Reset the date to the first day of the month.
- """
- return self.set(self.year, self.month, 1)
-
- def _end_of_month(self) -> Date:
- """
- Reset the date to the last day of the month.
- """
- return self.set(self.year, self.month, self.days_in_month)
-
- def _start_of_year(self) -> Date:
- """
- Reset the date to the first day of the year.
- """
- return self.set(self.year, 1, 1)
-
- def _end_of_year(self) -> Date:
- """
- Reset the date to the last day of the year.
- """
- return self.set(self.year, 12, 31)
-
- def _start_of_decade(self) -> Date:
- """
- Reset the date to the first day of the decade.
- """
- year = self.year - self.year % YEARS_PER_DECADE
-
- return self.set(year, 1, 1)
-
- def _end_of_decade(self) -> Date:
- """
- Reset the date to the last day of the decade.
- """
- year = self.year - self.year % YEARS_PER_DECADE + YEARS_PER_DECADE - 1
-
- return self.set(year, 12, 31)
-
- def _start_of_century(self) -> Date:
- """
- Reset the date to the first day of the century.
- """
- year = self.year - 1 - (self.year - 1) % YEARS_PER_CENTURY + 1
-
- return self.set(year, 1, 1)
-
- def _end_of_century(self) -> Date:
- """
- Reset the date to the last day of the century.
- """
- year = self.year - 1 - (self.year - 1) % YEARS_PER_CENTURY + YEARS_PER_CENTURY
-
- return self.set(year, 12, 31)
-
- def _start_of_week(self) -> Date:
- """
- Reset the date to the first day of the week.
- """
- dt = self
-
- if self.day_of_week != pendulum._WEEK_STARTS_AT:
- dt = self.previous(pendulum._WEEK_STARTS_AT)
-
- return dt.start_of("day")
-
- def _end_of_week(self) -> Date:
- """
- Reset the date to the last day of the week.
- """
- dt = self
-
- if self.day_of_week != pendulum._WEEK_ENDS_AT:
- dt = self.next(pendulum._WEEK_ENDS_AT)
-
- return dt.end_of("day")
-
- def next(self, day_of_week: int | None = None) -> Date:
- """
- Modify to the next occurrence of a given day of the week.
- If no day_of_week is provided, modify to the next occurrence
- of the current day of the week. Use the supplied consts
- to indicate the desired day_of_week, ex. pendulum.MONDAY.
-
- :param day_of_week: The next day of week to reset to.
- """
- if day_of_week is None:
- day_of_week = self.day_of_week
-
- if day_of_week < SUNDAY or day_of_week > SATURDAY:
- raise ValueError("Invalid day of week")
-
- dt = self.add(days=1)
- while dt.day_of_week != day_of_week:
- dt = dt.add(days=1)
-
- return dt
-
- def previous(self, day_of_week: int | None = None) -> Date:
- """
- Modify to the previous occurrence of a given day of the week.
- If no day_of_week is provided, modify to the previous occurrence
- of the current day of the week. Use the supplied consts
- to indicate the desired day_of_week, ex. pendulum.MONDAY.
-
- :param day_of_week: The previous day of week to reset to.
- """
- if day_of_week is None:
- day_of_week = self.day_of_week
-
- if day_of_week < SUNDAY or day_of_week > SATURDAY:
- raise ValueError("Invalid day of week")
-
- dt = self.subtract(days=1)
- while dt.day_of_week != day_of_week:
- dt = dt.subtract(days=1)
-
- return dt
-
- def first_of(self, unit: str, day_of_week: int | None = None) -> Date:
- """
- Returns an instance set to the first occurrence
- of a given day of the week in the current unit.
- If no day_of_week is provided, modify to the first day of the unit.
- Use the supplied consts to indicate the desired day_of_week, ex. pendulum.MONDAY.
-
- Supported units are month, quarter and year.
-
- :param unit: The unit to use
- :param day_of_week: The day of week to reset to.
- """
- if unit not in ["month", "quarter", "year"]:
- raise ValueError(f'Invalid unit "{unit}" for first_of()')
-
- return cast(Date, getattr(self, f"_first_of_{unit}")(day_of_week))
-
- def last_of(self, unit: str, day_of_week: int | None = None) -> Date:
- """
- Returns an instance set to the last occurrence
- of a given day of the week in the current unit.
- If no day_of_week is provided, modify to the last day of the unit.
- Use the supplied consts to indicate the desired day_of_week, ex. pendulum.MONDAY.
-
- Supported units are month, quarter and year.
-
- :param unit: The unit to use
- :param day_of_week: The day of week to reset to.
- """
- if unit not in ["month", "quarter", "year"]:
- raise ValueError(f'Invalid unit "{unit}" for first_of()')
-
- return cast(Date, getattr(self, f"_last_of_{unit}")(day_of_week))
-
- def nth_of(self, unit: str, nth: int, day_of_week: int) -> Date:
- """
- Returns a new instance set to the given occurrence
- of a given day of the week in the current unit.
- If the calculated occurrence is outside the scope of the current unit,
- then raise an error. Use the supplied consts
- to indicate the desired day_of_week, ex. pendulum.MONDAY.
-
- Supported units are month, quarter and year.
-
- :param unit: The unit to use
- :param nth: The occurrence to use
- :param day_of_week: The day of week to set to.
- """
- if unit not in ["month", "quarter", "year"]:
- raise ValueError(f'Invalid unit "{unit}" for first_of()')
-
- dt = cast(Date, getattr(self, f"_nth_of_{unit}")(nth, day_of_week))
- if not dt:
- raise PendulumException(
- f"Unable to find occurence {nth}"
- f" of {self._days[day_of_week]} in {unit}"
- )
-
- return dt
-
- def _first_of_month(self, day_of_week: int) -> Date:
- """
- Modify to the first occurrence of a given day of the week
- in the current month. If no day_of_week is provided,
- modify to the first day of the month. Use the supplied consts
- to indicate the desired day_of_week, ex. pendulum.MONDAY.
-
- :param day_of_week: The day of week to set to.
- """
- dt = self
-
- if day_of_week is None:
- return dt.set(day=1)
-
- month = calendar.monthcalendar(dt.year, dt.month)
-
- calendar_day = (day_of_week - 1) % 7
-
- if month[0][calendar_day] > 0:
- day_of_month = month[0][calendar_day]
- else:
- day_of_month = month[1][calendar_day]
-
- return dt.set(day=day_of_month)
-
- def _last_of_month(self, day_of_week: int | None = None) -> Date:
- """
- Modify to the last occurrence of a given day of the week
- in the current month. If no day_of_week is provided,
- modify to the last day of the month. Use the supplied consts
- to indicate the desired day_of_week, ex. pendulum.MONDAY.
-
- :param day_of_week: The day of week to set to.
- """
- dt = self
-
- if day_of_week is None:
- return dt.set(day=self.days_in_month)
-
- month = calendar.monthcalendar(dt.year, dt.month)
-
- calendar_day = (day_of_week - 1) % 7
-
- if month[-1][calendar_day] > 0:
- day_of_month = month[-1][calendar_day]
- else:
- day_of_month = month[-2][calendar_day]
-
- return dt.set(day=day_of_month)
-
- def _nth_of_month(self, nth: int, day_of_week: int) -> Date | None:
- """
- Modify to the given occurrence of a given day of the week
- in the current month. If the calculated occurrence is outside,
- the scope of the current month, then return False and no
- modifications are made. Use the supplied consts
- to indicate the desired day_of_week, ex. pendulum.MONDAY.
- """
- if nth == 1:
- return self.first_of("month", day_of_week)
-
- dt = self.first_of("month")
- check = dt.format("YYYY-MM")
- for _ in range(nth - (1 if dt.day_of_week == day_of_week else 0)):
- dt = dt.next(day_of_week)
-
- if dt.format("YYYY-MM") == check:
- return self.set(day=dt.day)
-
- return None
-
- def _first_of_quarter(self, day_of_week: int | None = None) -> Date:
- """
- Modify to the first occurrence of a given day of the week
- in the current quarter. If no day_of_week is provided,
- modify to the first day of the quarter. Use the supplied consts
- to indicate the desired day_of_week, ex. pendulum.MONDAY.
- """
- return self.set(self.year, self.quarter * 3 - 2, 1).first_of(
- "month", day_of_week
- )
-
- def _last_of_quarter(self, day_of_week: int | None = None) -> Date:
- """
- Modify to the last occurrence of a given day of the week
- in the current quarter. If no day_of_week is provided,
- modify to the last day of the quarter. Use the supplied consts
- to indicate the desired day_of_week, ex. pendulum.MONDAY.
- """
- return self.set(self.year, self.quarter * 3, 1).last_of("month", day_of_week)
-
- def _nth_of_quarter(self, nth: int, day_of_week: int) -> Date | None:
- """
- Modify to the given occurrence of a given day of the week
- in the current quarter. If the calculated occurrence is outside,
- the scope of the current quarter, then return False and no
- modifications are made. Use the supplied consts
- to indicate the desired day_of_week, ex. pendulum.MONDAY.
- """
- if nth == 1:
- return self.first_of("quarter", day_of_week)
-
- dt = self.replace(self.year, self.quarter * 3, 1)
- last_month = dt.month
- year = dt.year
- dt = dt.first_of("quarter")
- for _ in range(nth - (1 if dt.day_of_week == day_of_week else 0)):
- dt = dt.next(day_of_week)
-
- if last_month < dt.month or year != dt.year:
- return None
-
- return self.set(self.year, dt.month, dt.day)
-
- def _first_of_year(self, day_of_week: int | None = None) -> Date:
- """
- Modify to the first occurrence of a given day of the week
- in the current year. If no day_of_week is provided,
- modify to the first day of the year. Use the supplied consts
- to indicate the desired day_of_week, ex. pendulum.MONDAY.
- """
- return self.set(month=1).first_of("month", day_of_week)
-
- def _last_of_year(self, day_of_week: int | None = None) -> Date:
- """
- Modify to the last occurrence of a given day of the week
- in the current year. If no day_of_week is provided,
- modify to the last day of the year. Use the supplied consts
- to indicate the desired day_of_week, ex. pendulum.MONDAY.
- """
- return self.set(month=MONTHS_PER_YEAR).last_of("month", day_of_week)
-
- def _nth_of_year(self, nth: int, day_of_week: int) -> Date | None:
- """
- Modify to the given occurrence of a given day of the week
- in the current year. If the calculated occurrence is outside,
- the scope of the current year, then return False and no
- modifications are made. Use the supplied consts
- to indicate the desired day_of_week, ex. pendulum.MONDAY.
- """
- if nth == 1:
- return self.first_of("year", day_of_week)
-
- dt = self.first_of("year")
- year = dt.year
- for _ in range(nth - (1 if dt.day_of_week == day_of_week else 0)):
- dt = dt.next(day_of_week)
-
- if year != dt.year:
- return None
-
- return self.set(self.year, dt.month, dt.day)
-
- def average(self, dt: date | None = None) -> Date:
- """
- Modify the current instance to the average
- of a given instance (default now) and the current instance.
- """
- if dt is None:
- dt = Date.today()
-
- return self.add(days=int(self.diff(dt, False).in_days() / 2))
-
- # Native methods override
-
- @classmethod
- def today(cls) -> Date:
- dt = date.today()
-
- return cls(dt.year, dt.month, dt.day)
-
- @classmethod
- def fromtimestamp(cls, t: float) -> Date:
- dt = super().fromtimestamp(t)
-
- return cls(dt.year, dt.month, dt.day)
-
- @classmethod
- def fromordinal(cls, n: int) -> Date:
- dt = super().fromordinal(n)
-
- return cls(dt.year, dt.month, dt.day)
-
- def replace(
- self,
- year: int | None = None,
- month: int | None = None,
- day: int | None = None,
- ) -> Date:
- year = year if year is not None else self.year
- month = month if month is not None else self.month
- day = day if day is not None else self.day
-
- return self.__class__(year, month, day)
diff --git a/pendulum/datetime.py b/pendulum/datetime.py
deleted file mode 100644
index 52ad3cc..0000000
--- a/pendulum/datetime.py
+++ /dev/null
@@ -1,1381 +0,0 @@
-from __future__ import annotations
-
-import calendar
-import datetime
-
-from typing import TYPE_CHECKING
-from typing import Any
-from typing import Callable
-from typing import Optional
-from typing import cast
-from typing import overload
-
-import pendulum
-
-from pendulum.constants import ATOM
-from pendulum.constants import COOKIE
-from pendulum.constants import MINUTES_PER_HOUR
-from pendulum.constants import MONTHS_PER_YEAR
-from pendulum.constants import RFC822
-from pendulum.constants import RFC850
-from pendulum.constants import RFC1036
-from pendulum.constants import RFC1123
-from pendulum.constants import RFC2822
-from pendulum.constants import RSS
-from pendulum.constants import SATURDAY
-from pendulum.constants import SECONDS_PER_DAY
-from pendulum.constants import SECONDS_PER_MINUTE
-from pendulum.constants import SUNDAY
-from pendulum.constants import W3C
-from pendulum.constants import YEARS_PER_CENTURY
-from pendulum.constants import YEARS_PER_DECADE
-from pendulum.date import Date
-from pendulum.exceptions import PendulumException
-from pendulum.helpers import add_duration
-from pendulum.interval import Interval
-from pendulum.time import Time
-from pendulum.tz import UTC
-from pendulum.tz import local_timezone
-from pendulum.tz.timezone import FixedTimezone
-from pendulum.tz.timezone import Timezone
-from pendulum.utils._compat import PY38
-
-if TYPE_CHECKING:
- from typing import Literal
-
-
-class DateTime(datetime.datetime, Date):
- EPOCH: DateTime
-
- # Formats
-
- _FORMATS: dict[str, str | Callable[[datetime.datetime], str]] = {
- "atom": ATOM,
- "cookie": COOKIE,
- "iso8601": lambda dt: dt.isoformat(),
- "rfc822": RFC822,
- "rfc850": RFC850,
- "rfc1036": RFC1036,
- "rfc1123": RFC1123,
- "rfc2822": RFC2822,
- "rfc3339": lambda dt: dt.isoformat(),
- "rss": RSS,
- "w3c": W3C,
- }
-
- _MODIFIERS_VALID_UNITS: list[str] = [
- "second",
- "minute",
- "hour",
- "day",
- "week",
- "month",
- "year",
- "decade",
- "century",
- ]
-
- _EPOCH: datetime.datetime = datetime.datetime(1970, 1, 1, tzinfo=UTC)
-
- @classmethod
- def create(
- cls,
- year: int,
- month: int,
- day: int,
- hour: int = 0,
- minute: int = 0,
- second: int = 0,
- microsecond: int = 0,
- tz: str | float | Timezone | FixedTimezone | None | datetime.tzinfo = UTC,
- fold: int = 1,
- raise_on_unknown_times: bool = False,
- ) -> DateTime:
- """
- Creates a new DateTime instance from a specific date and time.
- """
- if tz is not None:
- tz = pendulum._safe_timezone(tz)
-
- dt = datetime.datetime(
- year, month, day, hour, minute, second, microsecond, fold=fold
- )
-
- if tz is not None:
- dt = tz.convert(dt, raise_on_unknown_times=raise_on_unknown_times)
-
- return cls(
- dt.year,
- dt.month,
- dt.day,
- dt.hour,
- dt.minute,
- dt.second,
- dt.microsecond,
- tzinfo=dt.tzinfo,
- fold=dt.fold,
- )
-
- @overload
- @classmethod
- def now(cls, tz: datetime.tzinfo | None = None) -> DateTime:
- ...
-
- @overload
- @classmethod
- def now(cls, tz: str | Timezone | FixedTimezone | None = None) -> DateTime:
- ...
-
- @classmethod
- def now(
- cls, tz: str | Timezone | FixedTimezone | datetime.tzinfo | None = None
- ) -> DateTime:
- """
- Get a DateTime instance for the current date and time.
- """
- if tz is None or tz == "local":
- dt = datetime.datetime.now(local_timezone())
- elif tz is UTC or tz == "UTC":
- dt = datetime.datetime.now(UTC)
- else:
- dt = datetime.datetime.now(UTC)
- tz = pendulum._safe_timezone(tz)
- dt = dt.astimezone(tz)
-
- return cls(
- dt.year,
- dt.month,
- dt.day,
- dt.hour,
- dt.minute,
- dt.second,
- dt.microsecond,
- tzinfo=dt.tzinfo,
- fold=dt.fold,
- )
-
- @classmethod
- def utcnow(cls) -> DateTime:
- """
- Get a DateTime instance for the current date and time in UTC.
- """
- return cls.now(UTC)
-
- @classmethod
- def today(cls) -> DateTime:
- return cls.now()
-
- @classmethod
- def strptime(cls, time: str, fmt: str) -> DateTime:
- return pendulum.instance(datetime.datetime.strptime(time, fmt))
-
- # Getters/Setters
-
- def set(
- self,
- year: int | None = None,
- month: int | None = None,
- day: int | None = None,
- hour: int | None = None,
- minute: int | None = None,
- second: int | None = None,
- microsecond: int | None = None,
- tz: str | float | Timezone | FixedTimezone | datetime.tzinfo | None = None,
- ) -> DateTime:
- if year is None:
- year = self.year
- if month is None:
- month = self.month
- if day is None:
- day = self.day
- if hour is None:
- hour = self.hour
- if minute is None:
- minute = self.minute
- if second is None:
- second = self.second
- if microsecond is None:
- microsecond = self.microsecond
- if tz is None:
- tz = self.tz
-
- return DateTime.create(
- year, month, day, hour, minute, second, microsecond, tz=tz
- )
-
- @property
- def float_timestamp(self) -> float:
- return self.timestamp()
-
- @property
- def int_timestamp(self) -> int:
- # Workaround needed to avoid inaccuracy
- # for far into the future datetimes
- dt = datetime.datetime(
- self.year,
- self.month,
- self.day,
- self.hour,
- self.minute,
- self.second,
- self.microsecond,
- tzinfo=self.tzinfo,
- fold=self.fold,
- )
-
- delta = dt - self._EPOCH
-
- return delta.days * SECONDS_PER_DAY + delta.seconds
-
- @property
- def offset(self) -> int | None:
- return self.get_offset()
-
- @property
- def offset_hours(self) -> float | None:
- offset = self.get_offset()
-
- if offset is None:
- return None
-
- return offset / SECONDS_PER_MINUTE / MINUTES_PER_HOUR
-
- @property
- def timezone(self) -> Timezone | FixedTimezone | None:
- if not isinstance(self.tzinfo, (Timezone, FixedTimezone)):
- return None
-
- return self.tzinfo
-
- @property
- def tz(self) -> Timezone | FixedTimezone | None:
- return self.timezone
-
- @property
- def timezone_name(self) -> str | None:
- tz = self.timezone
-
- if tz is None:
- return None
-
- return tz.name
-
- @property
- def age(self) -> int:
- return self.date().diff(self.now(self.tz).date(), abs=False).in_years()
-
- def is_local(self) -> bool:
- return self.offset == self.in_timezone(pendulum.local_timezone()).offset
-
- def is_utc(self) -> bool:
- return self.offset == 0
-
- def is_dst(self) -> bool:
- return self.dst() != datetime.timedelta()
-
- def get_offset(self) -> int | None:
- utcoffset = self.utcoffset()
- if utcoffset is None:
- return None
-
- return int(utcoffset.total_seconds())
-
- def date(self) -> Date:
- return Date(self.year, self.month, self.day)
-
- def time(self) -> Time:
- return Time(self.hour, self.minute, self.second, self.microsecond)
-
- def naive(self) -> DateTime:
- """
- Return the DateTime without timezone information.
- """
- return self.__class__(
- self.year,
- self.month,
- self.day,
- self.hour,
- self.minute,
- self.second,
- self.microsecond,
- )
-
- def on(self, year: int, month: int, day: int) -> DateTime:
- """
- Returns a new instance with the current date set to a different date.
- """
- return self.set(year=int(year), month=int(month), day=int(day))
-
- def at(
- self, hour: int, minute: int = 0, second: int = 0, microsecond: int = 0
- ) -> DateTime:
- """
- Returns a new instance with the current time to a different time.
- """
- return self.set(
- hour=hour, minute=minute, second=second, microsecond=microsecond
- )
-
- def in_timezone(self, tz: str | Timezone | FixedTimezone) -> DateTime:
- """
- Set the instance's timezone from a string or object.
- """
- tz = pendulum._safe_timezone(tz)
-
- dt = self
- if not self.timezone:
- dt = dt.replace(fold=1)
-
- return cast(DateTime, tz.convert(dt))
-
- def in_tz(self, tz: str | Timezone | FixedTimezone) -> DateTime:
- """
- Set the instance's timezone from a string or object.
- """
- return self.in_timezone(tz)
-
- # STRING FORMATTING
-
- def to_time_string(self) -> str:
- """
- Format the instance as time.
- """
- return self.format("HH:mm:ss")
-
- def to_datetime_string(self) -> str:
- """
- Format the instance as date and time.
- """
- return self.format("YYYY-MM-DD HH:mm:ss")
-
- def to_day_datetime_string(self) -> str:
- """
- Format the instance as day, date and time (in english).
- """
- return self.format("ddd, MMM D, YYYY h:mm A", locale="en")
-
- def to_atom_string(self) -> str:
- """
- Format the instance as ATOM.
- """
- return self._to_string("atom")
-
- def to_cookie_string(self) -> str:
- """
- Format the instance as COOKIE.
- """
- return self._to_string("cookie", locale="en")
-
- def to_iso8601_string(self) -> str:
- """
- Format the instance as ISO 8601.
- """
- string = self._to_string("iso8601")
-
- if self.tz and self.tz.name == "UTC":
- string = string.replace("+00:00", "Z")
-
- return string
-
- def to_rfc822_string(self) -> str:
- """
- Format the instance as RFC 822.
- """
- return self._to_string("rfc822")
-
- def to_rfc850_string(self) -> str:
- """
- Format the instance as RFC 850.
- """
- return self._to_string("rfc850")
-
- def to_rfc1036_string(self) -> str:
- """
- Format the instance as RFC 1036.
- """
- return self._to_string("rfc1036")
-
- def to_rfc1123_string(self) -> str:
- """
- Format the instance as RFC 1123.
- """
- return self._to_string("rfc1123")
-
- def to_rfc2822_string(self) -> str:
- """
- Format the instance as RFC 2822.
- """
- return self._to_string("rfc2822")
-
- def to_rfc3339_string(self) -> str:
- """
- Format the instance as RFC 3339.
- """
- return self._to_string("rfc3339")
-
- def to_rss_string(self) -> str:
- """
- Format the instance as RSS.
- """
- return self._to_string("rss")
-
- def to_w3c_string(self) -> str:
- """
- Format the instance as W3C.
- """
- return self._to_string("w3c")
-
- def _to_string(self, fmt: str, locale: str | None = None) -> str:
- """
- Format the instance to a common string format.
- """
- if fmt not in self._FORMATS:
- raise ValueError(f"Format [{fmt}] is not supported")
-
- fmt_value = self._FORMATS[fmt]
- if callable(fmt_value):
- return fmt_value(self)
-
- return self.format(fmt_value, locale=locale)
-
- def __str__(self) -> str:
- return self.isoformat("T")
-
- def __repr__(self) -> str:
- us = ""
- if self.microsecond:
- us = f", {self.microsecond}"
-
- repr_ = "{klass}(" "{year}, {month}, {day}, " "{hour}, {minute}, {second}{us}"
-
- if self.tzinfo is not None:
- repr_ += ", tzinfo={tzinfo}"
-
- repr_ += ")"
-
- return repr_.format(
- klass=self.__class__.__name__,
- year=self.year,
- month=self.month,
- day=self.day,
- hour=self.hour,
- minute=self.minute,
- second=self.second,
- us=us,
- tzinfo=repr(self.tzinfo),
- )
-
- # Comparisons
- def closest(self, *dts: datetime.datetime) -> DateTime: # type: ignore[override]
- """
- Get the farthest date from the instance.
- """
- pdts = [pendulum.instance(x) for x in dts]
-
- return min((abs(self - dt), dt) for dt in pdts)[1]
-
- def farthest(self, *dts: datetime.datetime) -> DateTime: # type: ignore[override]
- """
- Get the farthest date from the instance.
- """
- pdts = [pendulum.instance(x) for x in dts]
-
- return max((abs(self - dt), dt) for dt in pdts)[1]
-
- def is_future(self) -> bool:
- """
- Determines if the instance is in the future, ie. greater than now.
- """
- return self > self.now(self.timezone)
-
- def is_past(self) -> bool:
- """
- Determines if the instance is in the past, ie. less than now.
- """
- return self < self.now(self.timezone)
-
- def is_long_year(self) -> bool:
- """
- Determines if the instance is a long year
-
- See link `https://en.wikipedia.org/wiki/ISO_8601#Week_dates`_
- """
- return (
- DateTime.create(self.year, 12, 28, 0, 0, 0, tz=self.tz).isocalendar()[1]
- == 53
- )
-
- def is_same_day(self, dt: datetime.datetime) -> bool: # type: ignore[override]
- """
- Checks if the passed in date is the same day
- as the instance current day.
- """
- dt = pendulum.instance(dt)
-
- return self.to_date_string() == dt.to_date_string()
-
- def is_anniversary( # type: ignore[override]
- self, dt: datetime.datetime | None = None
- ) -> bool:
- """
- Check if its the anniversary.
- Compares the date/month values of the two dates.
- """
- if dt is None:
- dt = self.now(self.tz)
-
- instance = pendulum.instance(dt)
-
- return (self.month, self.day) == (instance.month, instance.day)
-
- # ADDITIONS AND SUBSTRACTIONS
-
- def add(
- self,
- years: int = 0,
- months: int = 0,
- weeks: int = 0,
- days: int = 0,
- hours: int = 0,
- minutes: int = 0,
- seconds: float = 0,
- microseconds: int = 0,
- ) -> DateTime:
- """
- Add a duration to the instance.
-
- If we're adding units of variable length (i.e., years, months),
- move forward from current time, otherwise move forward from utc, for accuracy
- when moving across DST boundaries.
- """
- units_of_variable_length = any([years, months, weeks, days])
-
- current_dt = datetime.datetime(
- self.year,
- self.month,
- self.day,
- self.hour,
- self.minute,
- self.second,
- self.microsecond,
- )
- if not units_of_variable_length:
- offset = self.utcoffset()
- if offset:
- current_dt = current_dt - offset
-
- dt = add_duration(
- current_dt,
- years=years,
- months=months,
- weeks=weeks,
- days=days,
- hours=hours,
- minutes=minutes,
- seconds=seconds,
- microseconds=microseconds,
- )
-
- if units_of_variable_length or self.tz is None:
- return DateTime.create(
- dt.year,
- dt.month,
- dt.day,
- dt.hour,
- dt.minute,
- dt.second,
- dt.microsecond,
- tz=self.tz,
- )
-
- dt = datetime.datetime(
- dt.year,
- dt.month,
- dt.day,
- dt.hour,
- dt.minute,
- dt.second,
- dt.microsecond,
- tzinfo=UTC,
- )
-
- dt = self.tz.convert(dt)
-
- return self.__class__(
- dt.year,
- dt.month,
- dt.day,
- dt.hour,
- dt.minute,
- dt.second,
- dt.microsecond,
- tzinfo=self.tz,
- fold=dt.fold,
- )
-
- def subtract(
- self,
- years: int = 0,
- months: int = 0,
- weeks: int = 0,
- days: int = 0,
- hours: int = 0,
- minutes: int = 0,
- seconds: float = 0,
- microseconds: int = 0,
- ) -> DateTime:
- """
- Remove duration from the instance.
- """
- return self.add(
- years=-years,
- months=-months,
- weeks=-weeks,
- days=-days,
- hours=-hours,
- minutes=-minutes,
- seconds=-seconds,
- microseconds=-microseconds,
- )
-
- # Adding a final underscore to the method name
- # to avoid errors for PyPy which already defines
- # a _add_timedelta method
- def _add_timedelta_(self, delta: datetime.timedelta) -> DateTime:
- """
- Add timedelta duration to the instance.
- """
- if isinstance(delta, pendulum.Interval):
- return self.add(
- years=delta.years,
- months=delta.months,
- weeks=delta.weeks,
- days=delta.remaining_days,
- hours=delta.hours,
- minutes=delta.minutes,
- seconds=delta.remaining_seconds,
- microseconds=delta.microseconds,
- )
- elif isinstance(delta, pendulum.Duration):
- return self.add(
- years=delta.years, months=delta.months, seconds=delta._total
- )
-
- return self.add(seconds=delta.total_seconds())
-
- def _subtract_timedelta(self, delta: datetime.timedelta) -> DateTime:
- """
- Remove timedelta duration from the instance.
- """
- if isinstance(delta, pendulum.Duration):
- return self.subtract(
- years=delta.years, months=delta.months, seconds=delta._total
- )
-
- return self.subtract(seconds=delta.total_seconds())
-
- # DIFFERENCES
-
- def diff( # type: ignore[override]
- self, dt: datetime.datetime | None = None, abs: bool = True
- ) -> Interval:
- """
- Returns the difference between two DateTime objects represented as an Interval.
- """
- if dt is None:
- dt = self.now(self.tz)
-
- return Interval(self, dt, absolute=abs)
-
- def diff_for_humans( # type: ignore[override]
- self,
- other: DateTime | None = None,
- absolute: bool = False,
- locale: str | None = None,
- ) -> str:
- """
- Get the difference in a human readable format in the current locale.
-
- When comparing a value in the past to default now:
- 1 day ago
- 5 months ago
-
- When comparing a value in the future to default now:
- 1 day from now
- 5 months from now
-
- When comparing a value in the past to another value:
- 1 day before
- 5 months before
-
- When comparing a value in the future to another value:
- 1 day after
- 5 months after
- """
- is_now = other is None
-
- if is_now:
- other = self.now()
-
- diff = self.diff(other)
-
- return pendulum.format_diff(diff, is_now, absolute, locale)
-
- # Modifiers
- def start_of(self, unit: str) -> DateTime:
- """
- Returns a copy of the instance with the time reset
- with the following rules:
-
- * second: microsecond set to 0
- * minute: second and microsecond set to 0
- * hour: minute, second and microsecond set to 0
- * day: time to 00:00:00
- * week: date to first day of the week and time to 00:00:00
- * month: date to first day of the month and time to 00:00:00
- * year: date to first day of the year and time to 00:00:00
- * decade: date to first day of the decade and time to 00:00:00
- * century: date to first day of century and time to 00:00:00
- """
- if unit not in self._MODIFIERS_VALID_UNITS:
- raise ValueError(f'Invalid unit "{unit}" for start_of()')
-
- return cast(DateTime, getattr(self, f"_start_of_{unit}")())
-
- def end_of(self, unit: str) -> DateTime:
- """
- Returns a copy of the instance with the time reset
- with the following rules:
-
- * second: microsecond set to 999999
- * minute: second set to 59 and microsecond set to 999999
- * hour: minute and second set to 59 and microsecond set to 999999
- * day: time to 23:59:59.999999
- * week: date to last day of the week and time to 23:59:59.999999
- * month: date to last day of the month and time to 23:59:59.999999
- * year: date to last day of the year and time to 23:59:59.999999
- * decade: date to last day of the decade and time to 23:59:59.999999
- * century: date to last day of century and time to 23:59:59.999999
- """
- if unit not in self._MODIFIERS_VALID_UNITS:
- raise ValueError(f'Invalid unit "{unit}" for end_of()')
-
- return cast(DateTime, getattr(self, f"_end_of_{unit}")())
-
- def _start_of_second(self) -> DateTime:
- """
- Reset microseconds to 0.
- """
- return self.set(microsecond=0)
-
- def _end_of_second(self) -> DateTime:
- """
- Set microseconds to 999999.
- """
- return self.set(microsecond=999999)
-
- def _start_of_minute(self) -> DateTime:
- """
- Reset seconds and microseconds to 0.
- """
- return self.set(second=0, microsecond=0)
-
- def _end_of_minute(self) -> DateTime:
- """
- Set seconds to 59 and microseconds to 999999.
- """
- return self.set(second=59, microsecond=999999)
-
- def _start_of_hour(self) -> DateTime:
- """
- Reset minutes, seconds and microseconds to 0.
- """
- return self.set(minute=0, second=0, microsecond=0)
-
- def _end_of_hour(self) -> DateTime:
- """
- Set minutes and seconds to 59 and microseconds to 999999.
- """
- return self.set(minute=59, second=59, microsecond=999999)
-
- def _start_of_day(self) -> DateTime:
- """
- Reset the time to 00:00:00.
- """
- return self.at(0, 0, 0, 0)
-
- def _end_of_day(self) -> DateTime:
- """
- Reset the time to 23:59:59.999999.
- """
- return self.at(23, 59, 59, 999999)
-
- def _start_of_month(self) -> DateTime:
- """
- Reset the date to the first day of the month and the time to 00:00:00.
- """
- return self.set(self.year, self.month, 1, 0, 0, 0, 0)
-
- def _end_of_month(self) -> DateTime:
- """
- Reset the date to the last day of the month
- and the time to 23:59:59.999999.
- """
- return self.set(self.year, self.month, self.days_in_month, 23, 59, 59, 999999)
-
- def _start_of_year(self) -> DateTime:
- """
- Reset the date to the first day of the year and the time to 00:00:00.
- """
- return self.set(self.year, 1, 1, 0, 0, 0, 0)
-
- def _end_of_year(self) -> DateTime:
- """
- Reset the date to the last day of the year
- and the time to 23:59:59.999999.
- """
- return self.set(self.year, 12, 31, 23, 59, 59, 999999)
-
- def _start_of_decade(self) -> DateTime:
- """
- Reset the date to the first day of the decade
- and the time to 00:00:00.
- """
- year = self.year - self.year % YEARS_PER_DECADE
- return self.set(year, 1, 1, 0, 0, 0, 0)
-
- def _end_of_decade(self) -> DateTime:
- """
- Reset the date to the last day of the decade
- and the time to 23:59:59.999999.
- """
- year = self.year - self.year % YEARS_PER_DECADE + YEARS_PER_DECADE - 1
-
- return self.set(year, 12, 31, 23, 59, 59, 999999)
-
- def _start_of_century(self) -> DateTime:
- """
- Reset the date to the first day of the century
- and the time to 00:00:00.
- """
- year = self.year - 1 - (self.year - 1) % YEARS_PER_CENTURY + 1
-
- return self.set(year, 1, 1, 0, 0, 0, 0)
-
- def _end_of_century(self) -> DateTime:
- """
- Reset the date to the last day of the century
- and the time to 23:59:59.999999.
- """
- year = self.year - 1 - (self.year - 1) % YEARS_PER_CENTURY + YEARS_PER_CENTURY
-
- return self.set(year, 12, 31, 23, 59, 59, 999999)
-
- def _start_of_week(self) -> DateTime:
- """
- Reset the date to the first day of the week
- and the time to 00:00:00.
- """
- dt = self
-
- if self.day_of_week != pendulum._WEEK_STARTS_AT:
- dt = self.previous(pendulum._WEEK_STARTS_AT)
-
- return dt.start_of("day")
-
- def _end_of_week(self) -> DateTime:
- """
- Reset the date to the last day of the week
- and the time to 23:59:59.
- """
- dt = self
-
- if self.day_of_week != pendulum._WEEK_ENDS_AT:
- dt = self.next(pendulum._WEEK_ENDS_AT)
-
- return dt.end_of("day")
-
- def next(self, day_of_week: int | None = None, keep_time: bool = False) -> DateTime:
- """
- Modify to the next occurrence of a given day of the week.
- If no day_of_week is provided, modify to the next occurrence
- of the current day of the week. Use the supplied consts
- to indicate the desired day_of_week, ex. DateTime.MONDAY.
- """
- if day_of_week is None:
- day_of_week = self.day_of_week
-
- if day_of_week < SUNDAY or day_of_week > SATURDAY:
- raise ValueError("Invalid day of week")
-
- if keep_time:
- dt = self
- else:
- dt = self.start_of("day")
-
- dt = dt.add(days=1)
- while dt.day_of_week != day_of_week:
- dt = dt.add(days=1)
-
- return dt
-
- def previous(
- self, day_of_week: int | None = None, keep_time: bool = False
- ) -> DateTime:
- """
- Modify to the previous occurrence of a given day of the week.
- If no day_of_week is provided, modify to the previous occurrence
- of the current day of the week. Use the supplied consts
- to indicate the desired day_of_week, ex. DateTime.MONDAY.
- """
- if day_of_week is None:
- day_of_week = self.day_of_week
-
- if day_of_week < SUNDAY or day_of_week > SATURDAY:
- raise ValueError("Invalid day of week")
-
- if keep_time:
- dt = self
- else:
- dt = self.start_of("day")
-
- dt = dt.subtract(days=1)
- while dt.day_of_week != day_of_week:
- dt = dt.subtract(days=1)
-
- return dt
-
- def first_of(self, unit: str, day_of_week: int | None = None) -> DateTime:
- """
- Returns an instance set to the first occurrence
- of a given day of the week in the current unit.
- If no day_of_week is provided, modify to the first day of the unit.
- Use the supplied consts to indicate the desired day_of_week, ex. DateTime.MONDAY.
-
- Supported units are month, quarter and year.
- """
- if unit not in ["month", "quarter", "year"]:
- raise ValueError(f'Invalid unit "{unit}" for first_of()')
-
- return cast(DateTime, getattr(self, f"_first_of_{unit}")(day_of_week))
-
- def last_of(self, unit: str, day_of_week: int | None = None) -> DateTime:
- """
- Returns an instance set to the last occurrence
- of a given day of the week in the current unit.
- If no day_of_week is provided, modify to the last day of the unit.
- Use the supplied consts to indicate the desired day_of_week, ex. DateTime.MONDAY.
-
- Supported units are month, quarter and year.
- """
- if unit not in ["month", "quarter", "year"]:
- raise ValueError(f'Invalid unit "{unit}" for first_of()')
-
- return cast(DateTime, getattr(self, f"_last_of_{unit}")(day_of_week))
-
- def nth_of(self, unit: str, nth: int, day_of_week: int) -> DateTime:
- """
- Returns a new instance set to the given occurrence
- of a given day of the week in the current unit.
- If the calculated occurrence is outside the scope of the current unit,
- then raise an error. Use the supplied consts
- to indicate the desired day_of_week, ex. DateTime.MONDAY.
-
- Supported units are month, quarter and year.
- """
- if unit not in ["month", "quarter", "year"]:
- raise ValueError(f'Invalid unit "{unit}" for first_of()')
-
- dt = cast(
- Optional[DateTime], getattr(self, f"_nth_of_{unit}")(nth, day_of_week)
- )
- if not dt:
- raise PendulumException(
- f"Unable to find occurence {nth}"
- f" of {self._days[day_of_week]} in {unit}"
- )
-
- return dt
-
- def _first_of_month(self, day_of_week: int | None = None) -> DateTime:
- """
- Modify to the first occurrence of a given day of the week
- in the current month. If no day_of_week is provided,
- modify to the first day of the month. Use the supplied consts
- to indicate the desired day_of_week, ex. DateTime.MONDAY.
- """
- dt = self.start_of("day")
-
- if day_of_week is None:
- return dt.set(day=1)
-
- month = calendar.monthcalendar(dt.year, dt.month)
-
- calendar_day = (day_of_week - 1) % 7
-
- if month[0][calendar_day] > 0:
- day_of_month = month[0][calendar_day]
- else:
- day_of_month = month[1][calendar_day]
-
- return dt.set(day=day_of_month)
-
- def _last_of_month(self, day_of_week: int | None = None) -> DateTime:
- """
- Modify to the last occurrence of a given day of the week
- in the current month. If no day_of_week is provided,
- modify to the last day of the month. Use the supplied consts
- to indicate the desired day_of_week, ex. DateTime.MONDAY.
- """
- dt = self.start_of("day")
-
- if day_of_week is None:
- return dt.set(day=self.days_in_month)
-
- month = calendar.monthcalendar(dt.year, dt.month)
-
- calendar_day = (day_of_week - 1) % 7
-
- if month[-1][calendar_day] > 0:
- day_of_month = month[-1][calendar_day]
- else:
- day_of_month = month[-2][calendar_day]
-
- return dt.set(day=day_of_month)
-
- def _nth_of_month(
- self, nth: int, day_of_week: int | None = None
- ) -> DateTime | None:
- """
- Modify to the given occurrence of a given day of the week
- in the current month. If the calculated occurrence is outside,
- the scope of the current month, then return False and no
- modifications are made. Use the supplied consts
- to indicate the desired day_of_week, ex. DateTime.MONDAY.
- """
- if nth == 1:
- return self.first_of("month", day_of_week)
-
- dt = self.first_of("month")
- check = dt.format("%Y-%M")
- for _ in range(nth - (1 if dt.day_of_week == day_of_week else 0)):
- dt = dt.next(day_of_week)
-
- if dt.format("%Y-%M") == check:
- return self.set(day=dt.day).start_of("day")
-
- return None
-
- def _first_of_quarter(self, day_of_week: int | None = None) -> DateTime:
- """
- Modify to the first occurrence of a given day of the week
- in the current quarter. If no day_of_week is provided,
- modify to the first day of the quarter. Use the supplied consts
- to indicate the desired day_of_week, ex. DateTime.MONDAY.
- """
- return self.on(self.year, self.quarter * 3 - 2, 1).first_of(
- "month", day_of_week
- )
-
- def _last_of_quarter(self, day_of_week: int | None = None) -> DateTime:
- """
- Modify to the last occurrence of a given day of the week
- in the current quarter. If no day_of_week is provided,
- modify to the last day of the quarter. Use the supplied consts
- to indicate the desired day_of_week, ex. DateTime.MONDAY.
- """
- return self.on(self.year, self.quarter * 3, 1).last_of("month", day_of_week)
-
- def _nth_of_quarter(
- self, nth: int, day_of_week: int | None = None
- ) -> DateTime | None:
- """
- Modify to the given occurrence of a given day of the week
- in the current quarter. If the calculated occurrence is outside,
- the scope of the current quarter, then return False and no
- modifications are made. Use the supplied consts
- to indicate the desired day_of_week, ex. DateTime.MONDAY.
- """
- if nth == 1:
- return self.first_of("quarter", day_of_week)
-
- dt = self.set(day=1, month=self.quarter * 3)
- last_month = dt.month
- year = dt.year
- dt = dt.first_of("quarter")
- for _ in range(nth - (1 if dt.day_of_week == day_of_week else 0)):
- dt = dt.next(day_of_week)
-
- if last_month < dt.month or year != dt.year:
- return None
-
- return self.on(self.year, dt.month, dt.day).start_of("day")
-
- def _first_of_year(self, day_of_week: int | None = None) -> DateTime:
- """
- Modify to the first occurrence of a given day of the week
- in the current year. If no day_of_week is provided,
- modify to the first day of the year. Use the supplied consts
- to indicate the desired day_of_week, ex. DateTime.MONDAY.
- """
- return self.set(month=1).first_of("month", day_of_week)
-
- def _last_of_year(self, day_of_week: int | None = None) -> DateTime:
- """
- Modify to the last occurrence of a given day of the week
- in the current year. If no day_of_week is provided,
- modify to the last day of the year. Use the supplied consts
- to indicate the desired day_of_week, ex. DateTime.MONDAY.
- """
- return self.set(month=MONTHS_PER_YEAR).last_of("month", day_of_week)
-
- def _nth_of_year(self, nth: int, day_of_week: int | None = None) -> DateTime | None:
- """
- Modify to the given occurrence of a given day of the week
- in the current year. If the calculated occurrence is outside,
- the scope of the current year, then return False and no
- modifications are made. Use the supplied consts
- to indicate the desired day_of_week, ex. DateTime.MONDAY.
- """
- if nth == 1:
- return self.first_of("year", day_of_week)
-
- dt = self.first_of("year")
- year = dt.year
- for _ in range(nth - (1 if dt.day_of_week == day_of_week else 0)):
- dt = dt.next(day_of_week)
-
- if year != dt.year:
- return None
-
- return self.on(self.year, dt.month, dt.day).start_of("day")
-
- def average( # type: ignore[override]
- self, dt: datetime.datetime | None = None
- ) -> DateTime:
- """
- Modify the current instance to the average
- of a given instance (default now) and the current instance.
- """
- if dt is None:
- dt = self.now(self.tz)
-
- diff = self.diff(dt, False)
- return self.add(
- microseconds=(diff.in_seconds() * 1000000 + diff.microseconds) // 2
- )
-
- @overload # type: ignore[override]
- def __sub__(self, other: datetime.timedelta) -> DateTime:
- ...
-
- @overload
- def __sub__(self, other: DateTime) -> Interval:
- ...
-
- def __sub__(
- self, other: datetime.datetime | datetime.timedelta
- ) -> DateTime | Interval:
- if isinstance(other, datetime.timedelta):
- return self._subtract_timedelta(other)
-
- if not isinstance(other, datetime.datetime):
- return NotImplemented
-
- if not isinstance(other, self.__class__):
- if other.tzinfo is None:
- other = pendulum.naive(
- other.year,
- other.month,
- other.day,
- other.hour,
- other.minute,
- other.second,
- other.microsecond,
- )
- else:
- other = pendulum.instance(other)
-
- return other.diff(self, False)
-
- def __rsub__(self, other: datetime.datetime) -> Interval:
- if not isinstance(other, datetime.datetime):
- return NotImplemented
-
- if not isinstance(other, self.__class__):
- if other.tzinfo is None:
- other = pendulum.naive(
- other.year,
- other.month,
- other.day,
- other.hour,
- other.minute,
- other.second,
- other.microsecond,
- )
- else:
- other = pendulum.instance(other)
-
- return self.diff(other, False)
-
- def __add__(self, other: datetime.timedelta) -> DateTime:
- if not isinstance(other, datetime.timedelta):
- return NotImplemented
-
- if PY38:
- # This is a workaround for Python 3.8+
- # since calling astimezone() will call this method
- # instead of the base datetime class one.
- import inspect
-
- caller = inspect.stack()[1][3]
- if caller == "astimezone":
- return cast(DateTime, super().__add__(other))
-
- return self._add_timedelta_(other)
-
- def __radd__(self, other: datetime.timedelta) -> DateTime:
- return self.__add__(other)
-
- # Native methods override
-
- @classmethod
- def fromtimestamp(cls, t: float, tz: datetime.tzinfo | None = None) -> DateTime:
- tzinfo = pendulum._safe_timezone(tz)
-
- return pendulum.instance(
- datetime.datetime.fromtimestamp(t, tz=tzinfo), tz=tzinfo
- )
-
- @classmethod
- def utcfromtimestamp(cls, t: float) -> DateTime:
- return pendulum.instance(datetime.datetime.utcfromtimestamp(t), tz=None)
-
- @classmethod
- def fromordinal(cls, n: int) -> DateTime:
- return pendulum.instance(datetime.datetime.fromordinal(n), tz=None)
-
- @classmethod
- def combine(
- cls,
- date: datetime.date,
- time: datetime.time,
- tzinfo: datetime.tzinfo | None = None,
- ) -> DateTime:
- return pendulum.instance(datetime.datetime.combine(date, time), tz=tzinfo)
-
- def astimezone(self, tz: datetime.tzinfo | None = None) -> DateTime:
- dt = super().astimezone(tz)
-
- return self.__class__(
- dt.year,
- dt.month,
- dt.day,
- dt.hour,
- dt.minute,
- dt.second,
- dt.microsecond,
- fold=dt.fold,
- tzinfo=dt.tzinfo,
- )
-
- def replace(
- self,
- year: int | None = None,
- month: int | None = None,
- day: int | None = None,
- hour: int | None = None,
- minute: int | None = None,
- second: int | None = None,
- microsecond: int | None = None,
- tzinfo: bool | datetime.tzinfo | Literal[True] | None = True,
- fold: int | None = None,
- ) -> DateTime:
- if year is None:
- year = self.year
- if month is None:
- month = self.month
- if day is None:
- day = self.day
- if hour is None:
- hour = self.hour
- if minute is None:
- minute = self.minute
- if second is None:
- second = self.second
- if microsecond is None:
- microsecond = self.microsecond
- if tzinfo is True:
- tzinfo = self.tzinfo
- if fold is None:
- fold = self.fold
-
- if tzinfo is not None:
- tzinfo = pendulum._safe_timezone(tzinfo)
-
- return DateTime.create(
- year,
- month,
- day,
- hour,
- minute,
- second,
- microsecond,
- tz=tzinfo,
- fold=fold,
- )
-
- def __getnewargs__(self) -> tuple[DateTime]:
- return (self,)
-
- def _getstate(
- self, protocol: int = 3
- ) -> tuple[int, int, int, int, int, int, int, datetime.tzinfo | None]:
- return (
- self.year,
- self.month,
- self.day,
- self.hour,
- self.minute,
- self.second,
- self.microsecond,
- self.tzinfo,
- )
-
- def __reduce__(
- self,
- ) -> tuple[
- type[DateTime], tuple[int, int, int, int, int, int, int, datetime.tzinfo | None]
- ]:
- return self.__reduce_ex__(2)
-
- def __reduce_ex__( # type: ignore[override]
- self, protocol: int
- ) -> tuple[
- type[DateTime], tuple[int, int, int, int, int, int, int, datetime.tzinfo | None]
- ]:
- return self.__class__, self._getstate(protocol)
-
- def _cmp(self, other: datetime.datetime, **kwargs: Any) -> int:
- # Fix for pypy which compares using this method
- # which would lead to infinite recursion if we didn't override
- dt = datetime.datetime(
- self.year,
- self.month,
- self.day,
- self.hour,
- self.minute,
- self.second,
- self.microsecond,
- tzinfo=self.tz,
- fold=self.fold,
- )
-
- return 0 if dt == other else 1 if dt > other else -1
-
-
-DateTime.min: DateTime = DateTime(1, 1, 1, 0, 0, tzinfo=UTC) # type: ignore[misc]
-DateTime.max: DateTime = DateTime( # type: ignore[misc]
- 9999, 12, 31, 23, 59, 59, 999999, tzinfo=UTC
-)
-DateTime.EPOCH: DateTime = DateTime(1970, 1, 1, tzinfo=UTC) # type: ignore[misc]
diff --git a/pendulum/duration.py b/pendulum/duration.py
deleted file mode 100644
index a3a68b1..0000000
--- a/pendulum/duration.py
+++ /dev/null
@@ -1,502 +0,0 @@
-from __future__ import annotations
-
-from datetime import timedelta
-from typing import cast
-from typing import overload
-
-import pendulum
-
-from pendulum.constants import SECONDS_PER_DAY
-from pendulum.constants import SECONDS_PER_HOUR
-from pendulum.constants import SECONDS_PER_MINUTE
-from pendulum.constants import US_PER_SECOND
-from pendulum.utils._compat import PYPY
-
-
-def _divide_and_round(a: float, b: float) -> int:
- """divide a by b and round result to the nearest integer
-
- When the ratio is exactly half-way between two integers,
- the even integer is returned.
- """
- # Based on the reference implementation for divmod_near
- # in Objects/longobject.c.
- q, r = divmod(a, b)
-
- # The output of divmod() is either a float or an int,
- # but we always want it to be an int.
- q = int(q)
-
- # round up if either r / b > 0.5, or r / b == 0.5 and q is odd.
- # The expression r / b > 0.5 is equivalent to 2 * r > b if b is
- # positive, 2 * r < b if b negative.
- r *= 2
- greater_than_half = r > b if b > 0 else r < b
- if greater_than_half or r == b and q % 2 == 1:
- q += 1
-
- return q
-
-
-class Duration(timedelta):
- """
- Replacement for the standard timedelta class.
-
- Provides several improvements over the base class.
- """
-
- _total: float = 0
- _years: int = 0
- _months: int = 0
- _weeks: int = 0
- _days: int = 0
- _remaining_days: int = 0
- _seconds: int = 0
- _microseconds: int = 0
-
- _y = None
- _m = None
- _w = None
- _d = None
- _h = None
- _i = None
- _s = None
- _invert = None
-
- def __new__(
- cls,
- days: float = 0,
- seconds: float = 0,
- microseconds: float = 0,
- milliseconds: float = 0,
- minutes: float = 0,
- hours: float = 0,
- weeks: float = 0,
- years: float = 0,
- months: float = 0,
- ) -> Duration:
- if not isinstance(years, int) or not isinstance(months, int):
- raise ValueError("Float year and months are not supported")
-
- self = timedelta.__new__(
- cls,
- days + years * 365 + months * 30,
- seconds,
- microseconds,
- milliseconds,
- minutes,
- hours,
- weeks,
- )
-
- # Intuitive normalization
- total = self.total_seconds() - (years * 365 + months * 30) * SECONDS_PER_DAY
- self._total = total
-
- m = 1
- if total < 0:
- m = -1
-
- self._microseconds = round(total % m * 1e6)
- self._seconds = abs(int(total)) % SECONDS_PER_DAY * m
-
- _days = abs(int(total)) // SECONDS_PER_DAY * m
- self._days = _days
- self._remaining_days = abs(_days) % 7 * m
- self._weeks = abs(_days) // 7 * m
- self._months = months
- self._years = years
-
- return self
-
- def total_minutes(self) -> float:
- return self.total_seconds() / SECONDS_PER_MINUTE
-
- def total_hours(self) -> float:
- return self.total_seconds() / SECONDS_PER_HOUR
-
- def total_days(self) -> float:
- return self.total_seconds() / SECONDS_PER_DAY
-
- def total_weeks(self) -> float:
- return self.total_days() / 7
-
- if PYPY:
-
- def total_seconds(self) -> float:
- days = 0
-
- if hasattr(self, "_years"):
- days += self._years * 365
-
- if hasattr(self, "_months"):
- days += self._months * 30
-
- if hasattr(self, "_remaining_days"):
- days += self._weeks * 7 + self._remaining_days
- else:
- days += self._days
-
- return (
- (days * SECONDS_PER_DAY + self._seconds) * US_PER_SECOND
- + self._microseconds
- ) / US_PER_SECOND
-
- @property
- def years(self) -> int:
- return self._years
-
- @property
- def months(self) -> int:
- return self._months
-
- @property
- def weeks(self) -> int:
- return self._weeks
-
- if PYPY:
-
- @property
- def days(self) -> int:
- return self._years * 365 + self._months * 30 + self._days
-
- @property
- def remaining_days(self) -> int:
- return self._remaining_days
-
- @property
- def hours(self) -> int:
- if self._h is None:
- seconds = self._seconds
- self._h = 0
- if abs(seconds) >= 3600:
- self._h = (abs(seconds) // 3600 % 24) * self._sign(seconds)
-
- return self._h
-
- @property
- def minutes(self) -> int:
- if self._i is None:
- seconds = self._seconds
- self._i = 0
- if abs(seconds) >= 60:
- self._i = (abs(seconds) // 60 % 60) * self._sign(seconds)
-
- return self._i
-
- @property
- def seconds(self) -> int:
- return self._seconds
-
- @property
- def remaining_seconds(self) -> int:
- if self._s is None:
- self._s = self._seconds
- self._s = abs(self._s) % 60 * self._sign(self._s)
-
- return self._s
-
- @property
- def microseconds(self) -> int:
- return self._microseconds
-
- @property
- def invert(self) -> bool:
- if self._invert is None:
- self._invert = self.total_seconds() < 0
-
- return self._invert
-
- def in_weeks(self) -> int:
- return int(self.total_weeks())
-
- def in_days(self) -> int:
- return int(self.total_days())
-
- def in_hours(self) -> int:
- return int(self.total_hours())
-
- def in_minutes(self) -> int:
- return int(self.total_minutes())
-
- def in_seconds(self) -> int:
- return int(self.total_seconds())
-
- def in_words(self, locale: str | None = None, separator: str = " ") -> str:
- """
- Get the current interval in words in the current locale.
-
- Ex: 6 jours 23 heures 58 minutes
-
- :param locale: The locale to use. Defaults to current locale.
- :param separator: The separator to use between each unit
- """
- periods = [
- ("year", self.years),
- ("month", self.months),
- ("week", self.weeks),
- ("day", self.remaining_days),
- ("hour", self.hours),
- ("minute", self.minutes),
- ("second", self.remaining_seconds),
- ]
-
- if locale is None:
- locale = pendulum.get_locale()
-
- loaded_locale = pendulum.locale(locale)
-
- parts = []
- for period in periods:
- unit, period_count = period
- if abs(period_count) > 0:
- translation = loaded_locale.translation(
- f"units.{unit}.{loaded_locale.plural(abs(period_count))}"
- )
- parts.append(translation.format(period_count))
-
- if not parts:
- count: int | str = 0
- if abs(self.microseconds) > 0:
- unit = f"units.second.{loaded_locale.plural(1)}"
- count = f"{abs(self.microseconds) / 1e6:.2f}"
- else:
- unit = f"units.microsecond.{loaded_locale.plural(0)}"
- translation = loaded_locale.translation(unit)
- parts.append(translation.format(count))
-
- return separator.join(parts)
-
- def _sign(self, value: float) -> int:
- if value < 0:
- return -1
-
- return 1
-
- def as_timedelta(self) -> timedelta:
- """
- Return the interval as a native timedelta.
- """
- return timedelta(seconds=self.total_seconds())
-
- def __str__(self) -> str:
- return self.in_words()
-
- def __repr__(self) -> str:
- rep = f"{self.__class__.__name__}("
-
- if self._years:
- rep += f"years={self._years}, "
-
- if self._months:
- rep += f"months={self._months}, "
-
- if self._weeks:
- rep += f"weeks={self._weeks}, "
-
- if self._days:
- rep += f"days={self._remaining_days}, "
-
- if self.hours:
- rep += f"hours={self.hours}, "
-
- if self.minutes:
- rep += f"minutes={self.minutes}, "
-
- if self.remaining_seconds:
- rep += f"seconds={self.remaining_seconds}, "
-
- if self.microseconds:
- rep += f"microseconds={self.microseconds}, "
-
- rep += ")"
-
- return rep.replace(", )", ")")
-
- def __add__(self, other: timedelta) -> Duration:
- if isinstance(other, timedelta):
- return self.__class__(seconds=self.total_seconds() + other.total_seconds())
-
- return NotImplemented
-
- __radd__ = __add__
-
- def __sub__(self, other: timedelta) -> Duration:
- if isinstance(other, timedelta):
- return self.__class__(seconds=self.total_seconds() - other.total_seconds())
-
- return NotImplemented
-
- def __neg__(self) -> Duration:
- return self.__class__(
- years=-self._years,
- months=-self._months,
- weeks=-self._weeks,
- days=-self._remaining_days,
- seconds=-self._seconds,
- microseconds=-self._microseconds,
- )
-
- def _to_microseconds(self) -> int:
- return (self._days * (24 * 3600) + self._seconds) * 1000000 + self._microseconds
-
- def __mul__(self, other: int | float) -> Duration:
- if isinstance(other, int):
- return self.__class__(
- years=self._years * other,
- months=self._months * other,
- seconds=self._total * other,
- )
-
- if isinstance(other, float):
- usec = self._to_microseconds()
- a, b = other.as_integer_ratio()
-
- return self.__class__(0, 0, _divide_and_round(usec * a, b))
-
- return NotImplemented
-
- __rmul__ = __mul__
-
- @overload
- def __floordiv__(self, other: timedelta) -> int:
- ...
-
- @overload
- def __floordiv__(self, other: int) -> Duration:
- ...
-
- def __floordiv__(self, other: int | timedelta) -> int | Duration:
- if not isinstance(other, (int, timedelta)):
- return NotImplemented
-
- usec = self._to_microseconds()
- if isinstance(other, timedelta):
- return cast(int, usec // other._to_microseconds()) # type: ignore[attr-defined]
-
- if isinstance(other, int):
- return self.__class__(
- 0,
- 0,
- usec // other,
- years=self._years // other,
- months=self._months // other,
- )
-
- @overload
- def __truediv__(self, other: timedelta) -> float:
- ...
-
- @overload
- def __truediv__(self, other: float) -> Duration:
- ...
-
- def __truediv__(self, other: int | float | timedelta) -> Duration | float:
- if not isinstance(other, (int, float, timedelta)):
- return NotImplemented
-
- usec = self._to_microseconds()
- if isinstance(other, timedelta):
- return cast(float, usec / other._to_microseconds()) # type: ignore[attr-defined]
-
- if isinstance(other, int):
- return self.__class__(
- 0,
- 0,
- _divide_and_round(usec, other),
- years=_divide_and_round(self._years, other),
- months=_divide_and_round(self._months, other),
- )
-
- if isinstance(other, float):
- a, b = other.as_integer_ratio()
-
- return self.__class__(
- 0,
- 0,
- _divide_and_round(b * usec, a),
- years=_divide_and_round(self._years * b, a),
- months=_divide_and_round(self._months, other),
- )
-
- __div__ = __floordiv__
-
- def __mod__(self, other: timedelta) -> Duration:
- if isinstance(other, timedelta):
- r = self._to_microseconds() % other._to_microseconds() # type: ignore[attr-defined]
-
- return self.__class__(0, 0, r)
-
- return NotImplemented
-
- def __divmod__(self, other: timedelta) -> tuple[int, Duration]:
- if isinstance(other, timedelta):
- q, r = divmod(self._to_microseconds(), other._to_microseconds()) # type: ignore[attr-defined]
-
- return q, self.__class__(0, 0, r)
-
- return NotImplemented
-
-
-Duration.min = Duration(days=-999999999)
-Duration.max = Duration(
- days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999
-)
-Duration.resolution = Duration(microseconds=1)
-
-
-class AbsoluteDuration(Duration):
- """
- Duration that expresses a time difference in absolute values.
- """
-
- def __new__(
- cls,
- days: float = 0,
- seconds: float = 0,
- microseconds: float = 0,
- milliseconds: float = 0,
- minutes: float = 0,
- hours: float = 0,
- weeks: float = 0,
- years: float = 0,
- months: float = 0,
- ) -> AbsoluteDuration:
- if not isinstance(years, int) or not isinstance(months, int):
- raise ValueError("Float year and months are not supported")
-
- self = timedelta.__new__(
- cls, days, seconds, microseconds, milliseconds, minutes, hours, weeks
- )
-
- # We need to compute the total_seconds() value
- # on a native timedelta object
- delta = timedelta(
- days, seconds, microseconds, milliseconds, minutes, hours, weeks
- )
-
- # Intuitive normalization
- self._total = delta.total_seconds()
- total = abs(self._total)
-
- self._microseconds = round(total % 1 * 1e6)
- self._seconds = int(total) % SECONDS_PER_DAY
-
- days = int(total) // SECONDS_PER_DAY
- self._days = abs(days + years * 365 + months * 30)
- self._remaining_days = days % 7
- self._weeks = days // 7
- self._months = abs(months)
- self._years = abs(years)
-
- return self
-
- def total_seconds(self) -> float:
- return abs(self._total)
-
- @property
- def invert(self) -> bool:
- if self._invert is None:
- self._invert = self._total < 0
-
- return self._invert
diff --git a/pendulum/exceptions.py b/pendulum/exceptions.py
deleted file mode 100644
index 3ab4db9..0000000
--- a/pendulum/exceptions.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from __future__ import annotations
-
-from .parsing.exceptions import ParserError # noqa
-
-
-class PendulumException(Exception):
-
- pass
diff --git a/pendulum/formatting/__init__.py b/pendulum/formatting/__init__.py
deleted file mode 100644
index 975c409..0000000
--- a/pendulum/formatting/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from __future__ import annotations
-
-from pendulum.formatting.formatter import Formatter
-
-__all__ = ["Formatter"]
diff --git a/pendulum/formatting/difference_formatter.py b/pendulum/formatting/difference_formatter.py
deleted file mode 100644
index dad219d..0000000
--- a/pendulum/formatting/difference_formatter.py
+++ /dev/null
@@ -1,146 +0,0 @@
-from __future__ import annotations
-
-import typing as t
-
-from pendulum.locales.locale import Locale
-
-if t.TYPE_CHECKING:
- from pendulum import Duration
-
-
-class DifferenceFormatter:
- """
- Handles formatting differences in text.
- """
-
- def __init__(self, locale: str = "en") -> None:
- self._locale = Locale.load(locale)
-
- def format(
- self,
- diff: Duration,
- is_now: bool = True,
- absolute: bool = False,
- locale: str | Locale | None = None,
- ) -> str:
- """
- Formats a difference.
-
- :param diff: The difference to format
- :param is_now: Whether the difference includes now
- :param absolute: Whether it's an absolute difference or not
- :param locale: The locale to use
- """
- if locale is None:
- locale = self._locale
- else:
- locale = Locale.load(locale)
-
- if diff.years > 0:
- unit = "year"
- count = diff.years
-
- if diff.months > 6:
- count += 1
- elif diff.months == 11 and (diff.weeks * 7 + diff.remaining_days) > 15:
- unit = "year"
- count = 1
- elif diff.months > 0:
- unit = "month"
- count = diff.months
-
- if (diff.weeks * 7 + diff.remaining_days) >= 27:
- count += 1
- elif diff.weeks > 0:
- unit = "week"
- count = diff.weeks
-
- if diff.remaining_days > 3:
- count += 1
- elif diff.remaining_days > 0:
- unit = "day"
- count = diff.remaining_days
-
- if diff.hours >= 22:
- count += 1
- elif diff.hours > 0:
- unit = "hour"
- count = diff.hours
- elif diff.minutes > 0:
- unit = "minute"
- count = diff.minutes
- elif 10 < diff.remaining_seconds <= 59:
- unit = "second"
- count = diff.remaining_seconds
- else:
- # We check if the "a few seconds" unit exists
- time = locale.get("custom.units.few_second")
- if time is not None:
- if absolute:
- return t.cast(str, time)
-
- key = "custom"
- is_future = diff.invert
- if is_now:
- if is_future:
- key += ".from_now"
- else:
- key += ".ago"
- else:
- if is_future:
- key += ".after"
- else:
- key += ".before"
-
- return t.cast(str, locale.get(key).format(time))
- else:
- unit = "second"
- count = diff.remaining_seconds
-
- if count == 0:
- count = 1
-
- if absolute:
- key = f"translations.units.{unit}"
- else:
- is_future = diff.invert
-
- if is_now:
- # Relative to now, so we can use
- # the CLDR data
- key = f"translations.relative.{unit}"
-
- if is_future:
- key += ".future"
- else:
- key += ".past"
- else:
- # Absolute comparison
- # So we have to use the custom locale data
-
- # Checking for special pluralization rules
- key = "custom.units_relative"
- if is_future:
- key += f".{unit}.future"
- else:
- key += f".{unit}.past"
-
- trans = locale.get(key)
- if not trans:
- # No special rule
- key = f"translations.units.{unit}.{locale.plural(count)}"
- time = locale.get(key).format(count)
- else:
- time = trans[locale.plural(count)].format(count)
-
- key = "custom"
- if is_future:
- key += ".after"
- else:
- key += ".before"
-
- return t.cast(str, locale.get(key).format(time))
-
- key += f".{locale.plural(count)}"
-
- return t.cast(str, locale.get(key).format(count))
diff --git a/pendulum/formatting/formatter.py b/pendulum/formatting/formatter.py
deleted file mode 100644
index f91d5d9..0000000
--- a/pendulum/formatting/formatter.py
+++ /dev/null
@@ -1,683 +0,0 @@
-from __future__ import annotations
-
-import datetime
-import re
-
-from typing import TYPE_CHECKING
-from typing import Any
-from typing import Callable
-from typing import Match
-from typing import Sequence
-from typing import cast
-
-import pendulum
-
-from pendulum.locales.locale import Locale
-
-if TYPE_CHECKING:
- from pendulum import Timezone
-
-_MATCH_1 = r"\d"
-_MATCH_2 = r"\d\d"
-_MATCH_3 = r"\d{3}"
-_MATCH_4 = r"\d{4}"
-_MATCH_6 = r"[+-]?\d{6}"
-_MATCH_1_TO_2 = r"\d\d?"
-_MATCH_1_TO_2_LEFT_PAD = r"[0-9 ]\d?"
-_MATCH_1_TO_3 = r"\d{1,3}"
-_MATCH_1_TO_4 = r"\d{1,4}"
-_MATCH_1_TO_6 = r"[+-]?\d{1,6}"
-_MATCH_3_TO_4 = r"\d{3}\d?"
-_MATCH_5_TO_6 = r"\d{5}\d?"
-_MATCH_UNSIGNED = r"\d+"
-_MATCH_SIGNED = r"[+-]?\d+"
-_MATCH_OFFSET = r"[Zz]|[+-]\d\d:?\d\d"
-_MATCH_SHORT_OFFSET = r"[Zz]|[+-]\d\d(?::?\d\d)?"
-_MATCH_TIMESTAMP = r"[+-]?\d+(\.\d{1,6})?"
-_MATCH_WORD = (
- "(?i)[0-9]*"
- "['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+"
- r"|[\u0600-\u06FF/]+(\s*?[\u0600-\u06FF]+){1,2}"
-)
-_MATCH_TIMEZONE = "[A-Za-z0-9-+]+(/[A-Za-z0-9-+_]+)?"
-
-
-class Formatter:
- _TOKENS: str = (
- r"\[([^\[]*)\]|\\(.)|"
- "("
- "Mo|MM?M?M?"
- "|Do|DDDo|DD?D?D?|ddd?d?|do?"
- "|E{1,4}"
- "|w[o|w]?|W[o|W]?|Qo?"
- "|YYYY|YY|Y"
- "|gg(ggg?)?|GG(GGG?)?"
- "|a|A"
- "|hh?|HH?|kk?"
- "|mm?|ss?|S{1,9}"
- "|x|X"
- "|zz?|ZZ?"
- "|LTS|LT|LL?L?L?"
- ")"
- )
-
- _FORMAT_RE: re.Pattern[str] = re.compile(_TOKENS)
-
- _FROM_FORMAT_RE: re.Pattern[str] = re.compile(r"(?<!\\\[)" + _TOKENS + r"(?!\\\])")
-
- _LOCALIZABLE_TOKENS: dict[str, str | Callable[[Locale], Sequence[str]] | None] = {
- "Qo": None,
- "MMMM": "months.wide",
- "MMM": "months.abbreviated",
- "Mo": None,
- "DDDo": None,
- "Do": lambda locale: tuple(
- rf"\d+{o}" for o in locale.get("custom.ordinal").values()
- ),
- "dddd": "days.wide",
- "ddd": "days.abbreviated",
- "dd": "days.short",
- "do": None,
- "Wo": None,
- "wo": None,
- "A": lambda locale: (
- locale.translation("day_periods.am"),
- locale.translation("day_periods.pm"),
- ),
- "a": lambda locale: (
- locale.translation("day_periods.am").lower(),
- locale.translation("day_periods.pm").lower(),
- ),
- }
-
- _TOKENS_RULES: dict[str, Callable[[pendulum.DateTime], str]] = {
- # Year
- "YYYY": lambda dt: f"{dt.year:d}",
- "YY": lambda dt: f"{dt.year:d}"[2:],
- "Y": lambda dt: f"{dt.year:d}",
- # Quarter
- "Q": lambda dt: f"{dt.quarter:d}",
- # Month
- "MM": lambda dt: f"{dt.month:02d}",
- "M": lambda dt: f"{dt.month:d}",
- # Day
- "DD": lambda dt: f"{dt.day:02d}",
- "D": lambda dt: f"{dt.day:d}",
- # Day of Year
- "DDDD": lambda dt: f"{dt.day_of_year:03d}",
- "DDD": lambda dt: f"{dt.day_of_year:d}",
- # Day of Week
- "d": lambda dt: f"{dt.day_of_week:d}",
- # Day of ISO Week
- "E": lambda dt: f"{dt.isoweekday():d}",
- # Hour
- "HH": lambda dt: f"{dt.hour:02d}",
- "H": lambda dt: f"{dt.hour:d}",
- "hh": lambda dt: f"{dt.hour % 12 or 12:02d}",
- "h": lambda dt: f"{dt.hour % 12 or 12:d}",
- # Minute
- "mm": lambda dt: f"{dt.minute:02d}",
- "m": lambda dt: f"{dt.minute:d}",
- # Second
- "ss": lambda dt: f"{dt.second:02d}",
- "s": lambda dt: f"{dt.second:d}",
- # Fractional second
- "S": lambda dt: f"{dt.microsecond // 100000:01d}",
- "SS": lambda dt: f"{dt.microsecond // 10000:02d}",
- "SSS": lambda dt: f"{dt.microsecond // 1000:03d}",
- "SSSS": lambda dt: f"{dt.microsecond // 100:04d}",
- "SSSSS": lambda dt: f"{dt.microsecond // 10:05d}",
- "SSSSSS": lambda dt: f"{dt.microsecond:06d}",
- # Timestamp
- "X": lambda dt: f"{dt.int_timestamp:d}",
- "x": lambda dt: f"{dt.int_timestamp * 1000 + dt.microsecond // 1000:d}",
- # Timezone
- "zz": lambda dt: f'{dt.tzname() if dt.tzinfo is not None else ""}',
- "z": lambda dt: f'{dt.timezone_name or ""}',
- }
-
- _DATE_FORMATS = {
- "LTS": "formats.time.full",
- "LT": "formats.time.short",
- "L": "formats.date.short",
- "LL": "formats.date.long",
- "LLL": "formats.datetime.long",
- "LLLL": "formats.datetime.full",
- }
-
- _DEFAULT_DATE_FORMATS = {
- "LTS": "h:mm:ss A",
- "LT": "h:mm A",
- "L": "MM/DD/YYYY",
- "LL": "MMMM D, YYYY",
- "LLL": "MMMM D, YYYY h:mm A",
- "LLLL": "dddd, MMMM D, YYYY h:mm A",
- }
-
- _REGEX_TOKENS: dict[str, str | Sequence[str] | None] = {
- "Y": _MATCH_SIGNED,
- "YY": (_MATCH_1_TO_2, _MATCH_2),
- "YYYY": (_MATCH_1_TO_4, _MATCH_4),
- "Q": _MATCH_1,
- "Qo": None,
- "M": _MATCH_1_TO_2,
- "MM": (_MATCH_1_TO_2, _MATCH_2),
- "MMM": _MATCH_WORD,
- "MMMM": _MATCH_WORD,
- "D": _MATCH_1_TO_2,
- "DD": (_MATCH_1_TO_2_LEFT_PAD, _MATCH_2),
- "DDD": _MATCH_1_TO_3,
- "DDDD": _MATCH_3,
- "dddd": _MATCH_WORD,
- "ddd": _MATCH_WORD,
- "dd": _MATCH_WORD,
- "d": _MATCH_1,
- "E": _MATCH_1,
- "Do": None,
- "H": _MATCH_1_TO_2,
- "HH": (_MATCH_1_TO_2, _MATCH_2),
- "h": _MATCH_1_TO_2,
- "hh": (_MATCH_1_TO_2, _MATCH_2),
- "m": _MATCH_1_TO_2,
- "mm": (_MATCH_1_TO_2, _MATCH_2),
- "s": _MATCH_1_TO_2,
- "ss": (_MATCH_1_TO_2, _MATCH_2),
- "S": (_MATCH_1_TO_3, _MATCH_1),
- "SS": (_MATCH_1_TO_3, _MATCH_2),
- "SSS": (_MATCH_1_TO_3, _MATCH_3),
- "SSSS": _MATCH_UNSIGNED,
- "SSSSS": _MATCH_UNSIGNED,
- "SSSSSS": _MATCH_UNSIGNED,
- "x": _MATCH_SIGNED,
- "X": _MATCH_TIMESTAMP,
- "ZZ": _MATCH_SHORT_OFFSET,
- "Z": _MATCH_OFFSET,
- "z": _MATCH_TIMEZONE,
- }
-
- _PARSE_TOKENS: dict[str, Callable[[str], Any]] = {
- "YYYY": lambda year: int(year),
- "YY": lambda year: int(year),
- "Q": lambda quarter: int(quarter),
- "MMMM": lambda month: month,
- "MMM": lambda month: month,
- "MM": lambda month: int(month),
- "M": lambda month: int(month),
- "DDDD": lambda day: int(day),
- "DDD": lambda day: int(day),
- "DD": lambda day: int(day),
- "D": lambda day: int(day),
- "dddd": lambda weekday: weekday,
- "ddd": lambda weekday: weekday,
- "dd": lambda weekday: weekday,
- "d": lambda weekday: int(weekday) % 7,
- "E": lambda weekday: int(weekday),
- "HH": lambda hour: int(hour),
- "H": lambda hour: int(hour),
- "hh": lambda hour: int(hour),
- "h": lambda hour: int(hour),
- "mm": lambda minute: int(minute),
- "m": lambda minute: int(minute),
- "ss": lambda second: int(second),
- "s": lambda second: int(second),
- "S": lambda us: int(us) * 100000,
- "SS": lambda us: int(us) * 10000,
- "SSS": lambda us: int(us) * 1000,
- "SSSS": lambda us: int(us) * 100,
- "SSSSS": lambda us: int(us) * 10,
- "SSSSSS": lambda us: int(us),
- "a": lambda meridiem: meridiem,
- "X": lambda ts: float(ts),
- "x": lambda ts: float(ts) / 1e3,
- "ZZ": str,
- "Z": str,
- "z": str,
- }
-
- def format(
- self, dt: pendulum.DateTime, fmt: str, locale: str | Locale | None = None
- ) -> str:
- """
- Formats a DateTime instance with a given format and locale.
-
- :param dt: The instance to format
- :param fmt: The format to use
- :param locale: The locale to use
- """
- loaded_locale: Locale = Locale.load(locale or pendulum.get_locale())
-
- result = self._FORMAT_RE.sub(
- lambda m: m.group(1)
- if m.group(1)
- else m.group(2)
- if m.group(2)
- else self._format_token(dt, m.group(3), loaded_locale),
- fmt,
- )
-
- return result
-
- def _format_token(self, dt: pendulum.DateTime, token: str, locale: Locale) -> str:
- """
- Formats a DateTime instance with a given token and locale.
-
- :param dt: The instance to format
- :param token: The token to use
- :param locale: The locale to use
- """
- if token in self._DATE_FORMATS:
- fmt = locale.get(f"custom.date_formats.{token}")
- if fmt is None:
- fmt = self._DEFAULT_DATE_FORMATS[token]
-
- return self.format(dt, fmt, locale)
-
- if token in self._LOCALIZABLE_TOKENS:
- return self._format_localizable_token(dt, token, locale)
-
- if token in self._TOKENS_RULES:
- return self._TOKENS_RULES[token](dt)
-
- # Timezone
- if token in ["ZZ", "Z"]:
- if dt.tzinfo is None:
- return ""
-
- separator = ":" if token == "Z" else ""
- offset = dt.utcoffset() or datetime.timedelta()
- minutes = offset.total_seconds() / 60
-
- if minutes >= 0:
- sign = "+"
- else:
- sign = "-"
-
- hour, minute = divmod(abs(int(minutes)), 60)
-
- return f"{sign}{hour:02d}{separator}{minute:02d}"
-
- return token
-
- def _format_localizable_token(
- self, dt: pendulum.DateTime, token: str, locale: Locale
- ) -> str:
- """
- Formats a DateTime instance
- with a given localizable token and locale.
-
- :param dt: The instance to format
- :param token: The token to use
- :param locale: The locale to use
- """
- if token == "MMM":
- return cast(str, locale.get("translations.months.abbreviated")[dt.month])
- elif token == "MMMM":
- return cast(str, locale.get("translations.months.wide")[dt.month])
- elif token == "dd":
- return cast(str, locale.get("translations.days.short")[dt.day_of_week])
- elif token == "ddd":
- return cast(
- str, locale.get("translations.days.abbreviated")[dt.day_of_week]
- )
- elif token == "dddd":
- return cast(str, locale.get("translations.days.wide")[dt.day_of_week])
- elif token == "Do":
- return locale.ordinalize(dt.day)
- elif token == "do":
- return locale.ordinalize(dt.day_of_week)
- elif token == "Mo":
- return locale.ordinalize(dt.month)
- elif token == "Qo":
- return locale.ordinalize(dt.quarter)
- elif token == "wo":
- return locale.ordinalize(dt.week_of_year)
- elif token == "DDDo":
- return locale.ordinalize(dt.day_of_year)
- elif token == "A":
- key = "translations.day_periods"
- if dt.hour >= 12:
- key += ".pm"
- else:
- key += ".am"
-
- return cast(str, locale.get(key))
- else:
- return token
-
- def parse(
- self,
- time: str,
- fmt: str,
- now: pendulum.DateTime,
- locale: str | None = None,
- ) -> dict[str, Any]:
- """
- Parses a time string matching a given format as a tuple.
-
- :param time: The timestring
- :param fmt: The format
- :param now: The datetime to use as "now"
- :param locale: The locale to use
-
- :return: The parsed elements
- """
- escaped_fmt = re.escape(fmt)
-
- tokens = self._FROM_FORMAT_RE.findall(escaped_fmt)
- if not tokens:
- raise ValueError("The given time string does not match the given format")
-
- if not locale:
- locale = pendulum.get_locale()
-
- loaded_locale: Locale = Locale.load(locale)
-
- parsed = {
- "year": None,
- "month": None,
- "day": None,
- "hour": None,
- "minute": None,
- "second": None,
- "microsecond": None,
- "tz": None,
- "quarter": None,
- "day_of_week": None,
- "day_of_year": None,
- "meridiem": None,
- "timestamp": None,
- }
-
- pattern = self._FROM_FORMAT_RE.sub(
- lambda m: self._replace_tokens(m.group(0), loaded_locale), escaped_fmt
- )
-
- if not re.search("^" + pattern + "$", time):
- raise ValueError(f"String does not match format {fmt}")
-
- _get_parsed_values: Callable[
- [Match[str]], Any
- ] = lambda m: self._get_parsed_values(m, parsed, loaded_locale, now)
-
- re.sub(pattern, _get_parsed_values, time)
-
- return self._check_parsed(parsed, now)
-
- def _check_parsed(
- self, parsed: dict[str, Any], now: pendulum.DateTime
- ) -> dict[str, Any]:
- """
- Checks validity of parsed elements.
-
- :param parsed: The elements to parse.
-
- :return: The validated elements.
- """
- validated: dict[str, int | Timezone | None] = {
- "year": parsed["year"],
- "month": parsed["month"],
- "day": parsed["day"],
- "hour": parsed["hour"],
- "minute": parsed["minute"],
- "second": parsed["second"],
- "microsecond": parsed["microsecond"],
- "tz": None,
- }
-
- # If timestamp has been specified
- # we use it and don't go any further
- if parsed["timestamp"] is not None:
- str_us = str(parsed["timestamp"])
- if "." in str_us:
- microseconds = int(f'{str_us.split(".")[1].ljust(6, "0")}')
- else:
- microseconds = 0
-
- from pendulum.helpers import local_time
-
- time = local_time(parsed["timestamp"], 0, microseconds)
- validated["year"] = time[0]
- validated["month"] = time[1]
- validated["day"] = time[2]
- validated["hour"] = time[3]
- validated["minute"] = time[4]
- validated["second"] = time[5]
- validated["microsecond"] = time[6]
-
- return validated
-
- if parsed["quarter"] is not None:
- if validated["year"] is not None:
- dt = pendulum.datetime(validated["year"], 1, 1)
- else:
- dt = now
-
- dt = dt.start_of("year")
-
- while dt.quarter != parsed["quarter"]:
- dt = dt.add(months=3)
-
- validated["year"] = dt.year
- validated["month"] = dt.month
- validated["day"] = dt.day
-
- if validated["year"] is None:
- validated["year"] = now.year
-
- if parsed["day_of_year"] is not None:
- dt = cast(
- pendulum.DateTime,
- pendulum.parse(f'{validated["year"]}-{parsed["day_of_year"]:>03d}'),
- )
-
- validated["month"] = dt.month
- validated["day"] = dt.day
-
- if parsed["day_of_week"] is not None:
- dt = pendulum.datetime(
- cast(int, validated["year"]),
- validated["month"] or now.month,
- validated["day"] or now.day,
- )
- dt = dt.start_of("week").subtract(days=1)
- dt = dt.next(parsed["day_of_week"])
- validated["year"] = dt.year
- validated["month"] = dt.month
- validated["day"] = dt.day
-
- # Meridiem
- if parsed["meridiem"] is not None:
- # If the time is greater than 13:00:00
- # This is not valid
- if validated["hour"] is None:
- raise ValueError("Invalid Date")
-
- t = (
- validated["hour"],
- validated["minute"],
- validated["second"],
- validated["microsecond"],
- )
- if t >= (13, 0, 0, 0):
- raise ValueError("Invalid date")
-
- pm = parsed["meridiem"] == "pm"
- validated["hour"] %= 12
- if pm:
- validated["hour"] += 12
-
- if validated["month"] is None:
- if parsed["year"] is not None:
- validated["month"] = parsed["month"] or 1
- else:
- validated["month"] = parsed["month"] or now.month
-
- if validated["day"] is None:
- if parsed["year"] is not None or parsed["month"] is not None:
- validated["day"] = parsed["day"] or 1
- else:
- validated["day"] = parsed["day"] or now.day
-
- for part in ["hour", "minute", "second", "microsecond"]:
- if validated[part] is None:
- validated[part] = 0
-
- validated["tz"] = parsed["tz"]
-
- return validated
-
- def _get_parsed_values(
- self,
- m: Match[str],
- parsed: dict[str, Any],
- locale: Locale,
- now: pendulum.DateTime,
- ) -> None:
- for token, index in m.re.groupindex.items():
- if token in self._LOCALIZABLE_TOKENS:
- self._get_parsed_locale_value(token, m.group(index), parsed, locale)
- else:
- self._get_parsed_value(token, m.group(index), parsed, now)
-
- def _get_parsed_value(
- self,
- token: str,
- value: str,
- parsed: dict[str, Any],
- now: pendulum.DateTime,
- ) -> None:
- parsed_token = self._PARSE_TOKENS[token](value)
-
- if "Y" in token:
- if token == "YY":
- parsed_token = now.year // 100 * 100 + parsed_token
-
- parsed["year"] = parsed_token
- elif token == "Q":
- parsed["quarter"] = parsed_token
- elif token in ["MM", "M"]:
- parsed["month"] = parsed_token
- elif token in ["DDDD", "DDD"]:
- parsed["day_of_year"] = parsed_token
- elif "D" in token:
- parsed["day"] = parsed_token
- elif "H" in token:
- parsed["hour"] = parsed_token
- elif token in ["hh", "h"]:
- if parsed_token > 12:
- raise ValueError("Invalid date")
-
- parsed["hour"] = parsed_token
- elif "m" in token:
- parsed["minute"] = parsed_token
- elif "s" in token:
- parsed["second"] = parsed_token
- elif "S" in token:
- parsed["microsecond"] = parsed_token
- elif token in ["d", "E"]:
- parsed["day_of_week"] = parsed_token
- elif token in ["X", "x"]:
- parsed["timestamp"] = parsed_token
- elif token in ["ZZ", "Z"]:
- negative = bool(value.startswith("-"))
- tz = value[1:]
- if ":" not in tz:
- if len(tz) == 2:
- tz = f"{tz}00"
-
- off_hour = tz[0:2]
- off_minute = tz[2:4]
- else:
- off_hour, off_minute = tz.split(":")
-
- offset = ((int(off_hour) * 60) + int(off_minute)) * 60
-
- if negative:
- offset = -1 * offset
-
- parsed["tz"] = pendulum.timezone(offset)
- elif token == "z":
- # Full timezone
- if value not in pendulum.timezones():
- raise ValueError("Invalid date")
-
- parsed["tz"] = pendulum.timezone(value)
-
- def _get_parsed_locale_value(
- self, token: str, value: str, parsed: dict[str, Any], locale: Locale
- ) -> None:
- if token == "MMMM":
- unit = "month"
- match = "months.wide"
- elif token == "MMM":
- unit = "month"
- match = "months.abbreviated"
- elif token == "Do":
- parsed["day"] = int(cast(Match[str], re.match(r"(\d+)", value)).group(1))
-
- return
- elif token == "dddd":
- unit = "day_of_week"
- match = "days.wide"
- elif token == "ddd":
- unit = "day_of_week"
- match = "days.abbreviated"
- elif token == "dd":
- unit = "day_of_week"
- match = "days.short"
- elif token in ["a", "A"]:
- valid_values = [
- locale.translation("day_periods.am"),
- locale.translation("day_periods.pm"),
- ]
-
- if token == "a":
- value = value.lower()
- valid_values = [x.lower() for x in valid_values]
-
- if value not in valid_values:
- raise ValueError("Invalid date")
-
- parsed["meridiem"] = ["am", "pm"][valid_values.index(value)]
-
- return
- else:
- raise ValueError(f'Invalid token "{token}"')
-
- parsed[unit] = locale.match_translation(match, value)
- if value is None:
- raise ValueError("Invalid date")
-
- def _replace_tokens(self, token: str, locale: Locale) -> str:
- if token.startswith("[") and token.endswith("]"):
- return token[1:-1]
- elif token.startswith("\\"):
- if len(token) == 2 and token[1] in {"[", "]"}:
- return ""
-
- return token
- elif token not in self._REGEX_TOKENS and token not in self._LOCALIZABLE_TOKENS:
- raise ValueError(f"Unsupported token: {token}")
-
- if token in self._LOCALIZABLE_TOKENS:
- values = self._LOCALIZABLE_TOKENS[token]
- if callable(values):
- candidates = values(locale)
- else:
- candidates = tuple(
- locale.translation(
- cast(str, self._LOCALIZABLE_TOKENS[token])
- ).values()
- )
- else:
- candidates = cast(Sequence[str], self._REGEX_TOKENS[token])
-
- if not candidates:
- raise ValueError(f"Unsupported token: {token}")
-
- if not isinstance(candidates, tuple):
- candidates = (cast(str, candidates),)
-
- pattern = f'(?P<{token}>{"|".join(candidates)})'
-
- return pattern
diff --git a/pendulum/helpers.py b/pendulum/helpers.py
deleted file mode 100644
index 13b7f22..0000000
--- a/pendulum/helpers.py
+++ /dev/null
@@ -1,223 +0,0 @@
-from __future__ import annotations
-
-import os
-import struct
-
-from datetime import date
-from datetime import datetime
-from datetime import timedelta
-from math import copysign
-from typing import TYPE_CHECKING
-from typing import TypeVar
-from typing import overload
-
-import pendulum
-
-from pendulum.constants import DAYS_PER_MONTHS
-from pendulum.formatting.difference_formatter import DifferenceFormatter
-from pendulum.locales.locale import Locale
-
-if TYPE_CHECKING:
- # Prevent import cycles
- from pendulum.duration import Duration
-
-with_extensions = os.getenv("PENDULUM_EXTENSIONS", "1") == "1"
-
-_DT = TypeVar("_DT", bound=datetime)
-_D = TypeVar("_D", bound=date)
-
-try:
- # nopycln: file # noqa: E800
- if not with_extensions or struct.calcsize("P") == 4:
- raise ImportError()
-
- from pendulum._extensions._helpers import PreciseDiff
- from pendulum._extensions._helpers import days_in_year
- from pendulum._extensions._helpers import is_leap
- from pendulum._extensions._helpers import is_long_year
- from pendulum._extensions._helpers import local_time
- from pendulum._extensions._helpers import precise_diff
- from pendulum._extensions._helpers import timestamp
- from pendulum._extensions._helpers import week_day
-except ImportError:
- from pendulum._extensions.helpers import PreciseDiff # type: ignore[misc]
- from pendulum._extensions.helpers import days_in_year
- from pendulum._extensions.helpers import is_leap
- from pendulum._extensions.helpers import is_long_year
- from pendulum._extensions.helpers import local_time
- from pendulum._extensions.helpers import precise_diff # type: ignore[misc]
- from pendulum._extensions.helpers import timestamp
- from pendulum._extensions.helpers import week_day
-
-difference_formatter = DifferenceFormatter()
-
-
-@overload
-def add_duration(
- dt: datetime,
- years: int = 0,
- months: int = 0,
- weeks: int = 0,
- days: int = 0,
- hours: int = 0,
- minutes: int = 0,
- seconds: float = 0,
- microseconds: int = 0,
-) -> datetime:
- ...
-
-
-@overload
-def add_duration(
- dt: date,
- years: int = 0,
- months: int = 0,
- weeks: int = 0,
- days: int = 0,
-) -> date:
- pass
-
-
-def add_duration(
- dt: date | datetime,
- years: int = 0,
- months: int = 0,
- weeks: int = 0,
- days: int = 0,
- hours: int = 0,
- minutes: int = 0,
- seconds: float = 0,
- microseconds: int = 0,
-) -> date | datetime:
- """
- Adds a duration to a date/datetime instance.
- """
- days += weeks * 7
-
- if (
- isinstance(dt, date)
- and not isinstance(dt, datetime)
- and any([hours, minutes, seconds, microseconds])
- ):
- raise RuntimeError("Time elements cannot be added to a date instance.")
-
- # Normalizing
- if abs(microseconds) > 999999:
- s = _sign(microseconds)
- div, mod = divmod(microseconds * s, 1000000)
- microseconds = mod * s
- seconds += div * s
-
- if abs(seconds) > 59:
- s = _sign(seconds)
- div, mod = divmod(seconds * s, 60) # type: ignore[assignment]
- seconds = mod * s
- minutes += div * s
-
- if abs(minutes) > 59:
- s = _sign(minutes)
- div, mod = divmod(minutes * s, 60)
- minutes = mod * s
- hours += div * s
-
- if abs(hours) > 23:
- s = _sign(hours)
- div, mod = divmod(hours * s, 24)
- hours = mod * s
- days += div * s
-
- if abs(months) > 11:
- s = _sign(months)
- div, mod = divmod(months * s, 12)
- months = mod * s
- years += div * s
-
- year = dt.year + years
- month = dt.month
-
- if months:
- month += months
- if month > 12:
- year += 1
- month -= 12
- elif month < 1:
- year -= 1
- month += 12
-
- day = min(DAYS_PER_MONTHS[int(is_leap(year))][month], dt.day)
-
- dt = dt.replace(year=year, month=month, day=day)
-
- return dt + timedelta(
- days=days,
- hours=hours,
- minutes=minutes,
- seconds=seconds,
- microseconds=microseconds,
- )
-
-
-def format_diff(
- diff: Duration,
- is_now: bool = True,
- absolute: bool = False,
- locale: str | None = None,
-) -> str:
- if locale is None:
- locale = get_locale()
-
- return difference_formatter.format(diff, is_now, absolute, locale)
-
-
-def _sign(x: float) -> int:
- return int(copysign(1, x))
-
-
-# Global helpers
-
-
-def locale(name: str) -> Locale:
- return Locale.load(name)
-
-
-def set_locale(name: str) -> None:
- locale(name)
-
- pendulum._LOCALE = name
-
-
-def get_locale() -> str:
- return pendulum._LOCALE
-
-
-def week_starts_at(wday: int) -> None:
- if wday < pendulum.SUNDAY or wday > pendulum.SATURDAY:
- raise ValueError("Invalid week day as start of week.")
-
- pendulum._WEEK_STARTS_AT = wday
-
-
-def week_ends_at(wday: int) -> None:
- if wday < pendulum.SUNDAY or wday > pendulum.SATURDAY:
- raise ValueError("Invalid week day as start of week.")
-
- pendulum._WEEK_ENDS_AT = wday
-
-
-__all__ = [
- "PreciseDiff",
- "days_in_year",
- "is_leap",
- "is_long_year",
- "local_time",
- "precise_diff",
- "timestamp",
- "week_day",
- "add_duration",
- "format_diff",
- "locale",
- "set_locale",
- "get_locale",
- "week_starts_at",
- "week_ends_at",
-]
diff --git a/pendulum/interval.py b/pendulum/interval.py
deleted file mode 100644
index f20042b..0000000
--- a/pendulum/interval.py
+++ /dev/null
@@ -1,448 +0,0 @@
-from __future__ import annotations
-
-import operator
-
-from datetime import date
-from datetime import datetime
-from datetime import timedelta
-from typing import TYPE_CHECKING
-from typing import Iterator
-from typing import Union
-from typing import cast
-from typing import overload
-
-import pendulum
-
-from pendulum.constants import MONTHS_PER_YEAR
-from pendulum.duration import Duration
-from pendulum.helpers import precise_diff
-
-if TYPE_CHECKING:
- from typing import SupportsIndex
-
- from pendulum.helpers import PreciseDiff
- from pendulum.locales.locale import Locale # noqa
-
-
-class Interval(Duration):
- """
- A period of time between two datetimes.
- """
-
- @overload
- def __new__(
- cls,
- start: pendulum.DateTime | datetime,
- end: pendulum.DateTime | datetime,
- absolute: bool = False,
- ) -> Interval:
- ...
-
- @overload
- def __new__(
- cls,
- start: pendulum.Date | date,
- end: pendulum.Date | date,
- absolute: bool = False,
- ) -> Interval:
- ...
-
- def __new__(
- cls,
- start: pendulum.DateTime | pendulum.Date | datetime | date,
- end: pendulum.DateTime | pendulum.Date | datetime | date,
- absolute: bool = False,
- ) -> Interval:
- if (
- isinstance(start, datetime)
- and not isinstance(end, datetime)
- or not isinstance(start, datetime)
- and isinstance(end, datetime)
- ):
- raise ValueError("Both start and end of a Period must have the same type")
-
- if (
- isinstance(start, datetime)
- and isinstance(end, datetime)
- and (
- start.tzinfo is None
- and end.tzinfo is not None
- or start.tzinfo is not None
- and end.tzinfo is None
- )
- ):
- raise TypeError("can't compare offset-naive and offset-aware datetimes")
-
- if absolute and start > end:
- end, start = start, end
-
- _start = start
- _end = end
- if isinstance(start, pendulum.DateTime):
- _start = datetime(
- start.year,
- start.month,
- start.day,
- start.hour,
- start.minute,
- start.second,
- start.microsecond,
- tzinfo=start.tzinfo,
- fold=start.fold,
- )
- elif isinstance(start, pendulum.Date):
- _start = date(start.year, start.month, start.day)
-
- if isinstance(end, pendulum.DateTime):
- _end = datetime(
- end.year,
- end.month,
- end.day,
- end.hour,
- end.minute,
- end.second,
- end.microsecond,
- tzinfo=end.tzinfo,
- fold=end.fold,
- )
- elif isinstance(end, pendulum.Date):
- _end = date(end.year, end.month, end.day)
-
- # Fixing issues with datetime.__sub__()
- # not handling offsets if the tzinfo is the same
- if (
- isinstance(_start, datetime)
- and isinstance(_end, datetime)
- and _start.tzinfo is _end.tzinfo
- ):
- if _start.tzinfo is not None:
- offset = cast(timedelta, cast(datetime, start).utcoffset())
- _start = (_start - offset).replace(tzinfo=None)
-
- if isinstance(end, datetime) and _end.tzinfo is not None:
- offset = cast(timedelta, end.utcoffset())
- _end = (_end - offset).replace(tzinfo=None)
-
- delta: timedelta = _end - _start # type: ignore[operator]
-
- return cast(Interval, super().__new__(cls, seconds=delta.total_seconds()))
-
- def __init__(
- self,
- start: pendulum.DateTime | pendulum.Date | datetime | date,
- end: pendulum.DateTime | pendulum.Date | datetime | date,
- absolute: bool = False,
- ) -> None:
- super().__init__()
-
- _start: pendulum.DateTime | pendulum.Date | datetime | date
- if not isinstance(start, pendulum.Date):
- if isinstance(start, datetime):
- start = pendulum.instance(start)
- else:
- start = pendulum.date(start.year, start.month, start.day)
-
- _start = start
- else:
- if isinstance(start, pendulum.DateTime):
- _start = datetime(
- start.year,
- start.month,
- start.day,
- start.hour,
- start.minute,
- start.second,
- start.microsecond,
- tzinfo=start.tzinfo,
- )
- else:
- _start = date(start.year, start.month, start.day)
-
- _end: pendulum.DateTime | pendulum.Date | datetime | date
- if not isinstance(end, pendulum.Date):
- if isinstance(end, datetime):
- end = pendulum.instance(end)
- else:
- end = pendulum.date(end.year, end.month, end.day)
-
- _end = end
- else:
- if isinstance(end, pendulum.DateTime):
- _end = datetime(
- end.year,
- end.month,
- end.day,
- end.hour,
- end.minute,
- end.second,
- end.microsecond,
- tzinfo=end.tzinfo,
- )
- else:
- _end = date(end.year, end.month, end.day)
-
- self._invert = False
- if start > end:
- self._invert = True
-
- if absolute:
- end, start = start, end
- _end, _start = _start, _end
-
- self._absolute = absolute
- self._start: pendulum.DateTime | pendulum.Date = start
- self._end: pendulum.DateTime | pendulum.Date = end
- self._delta: PreciseDiff = precise_diff(_start, _end)
-
- @property
- def years(self) -> int:
- return self._delta.years
-
- @property
- def months(self) -> int:
- return self._delta.months
-
- @property
- def weeks(self) -> int:
- return abs(self._delta.days) // 7 * self._sign(self._delta.days)
-
- @property
- def days(self) -> int:
- return self._days
-
- @property
- def remaining_days(self) -> int:
- return abs(self._delta.days) % 7 * self._sign(self._days)
-
- @property
- def hours(self) -> int:
- return self._delta.hours
-
- @property
- def minutes(self) -> int:
- return self._delta.minutes
-
- @property
- def start(self) -> pendulum.DateTime | pendulum.Date | datetime | date:
- return self._start
-
- @property
- def end(self) -> pendulum.DateTime | pendulum.Date | datetime | date:
- return self._end
-
- def in_years(self) -> int:
- """
- Gives the duration of the Period in full years.
- """
- return self.years
-
- def in_months(self) -> int:
- """
- Gives the duration of the Period in full months.
- """
- return self.years * MONTHS_PER_YEAR + self.months
-
- def in_weeks(self) -> int:
- days = self.in_days()
- sign = 1
-
- if days < 0:
- sign = -1
-
- return sign * (abs(days) // 7)
-
- def in_days(self) -> int:
- return self._delta.total_days
-
- def in_words(self, locale: str | None = None, separator: str = " ") -> str:
- """
- Get the current interval in words in the current locale.
-
- Ex: 6 jours 23 heures 58 minutes
-
- :param locale: The locale to use. Defaults to current locale.
- :param separator: The separator to use between each unit
- """
- from pendulum.locales.locale import Locale # noqa
-
- periods = [
- ("year", self.years),
- ("month", self.months),
- ("week", self.weeks),
- ("day", self.remaining_days),
- ("hour", self.hours),
- ("minute", self.minutes),
- ("second", self.remaining_seconds),
- ]
- loaded_locale: Locale = Locale.load(locale or pendulum.get_locale())
- parts = []
- for period in periods:
- unit, period_count = period
- if abs(period_count) > 0:
- translation = loaded_locale.translation(
- f"units.{unit}.{loaded_locale.plural(abs(period_count))}"
- )
- parts.append(translation.format(period_count))
-
- if not parts:
- count: str | int = 0
- if abs(self.microseconds) > 0:
- unit = f"units.second.{loaded_locale.plural(1)}"
- count = f"{abs(self.microseconds) / 1e6:.2f}"
- else:
- unit = f"units.microsecond.{loaded_locale.plural(0)}"
-
- translation = loaded_locale.translation(unit)
- parts.append(translation.format(count))
-
- return separator.join(parts)
-
- def range(
- self, unit: str, amount: int = 1
- ) -> Iterator[pendulum.DateTime | pendulum.Date]:
- method = "add"
- op = operator.le
- if not self._absolute and self.invert:
- method = "subtract"
- op = operator.ge
-
- start, end = self.start, self.end
-
- i = amount
- while op(start, end):
- yield cast(Union[pendulum.DateTime, pendulum.Date], start)
-
- start = getattr(self.start, method)(**{unit: i})
-
- i += amount
-
- def as_interval(self) -> Duration:
- """
- Return the Period as a Duration.
- """
- return Duration(seconds=self.total_seconds())
-
- def __iter__(self) -> Iterator[pendulum.DateTime | pendulum.Date]:
- return self.range("days")
-
- def __contains__(
- self, item: datetime | date | pendulum.DateTime | pendulum.Date
- ) -> bool:
- return self.start <= item <= self.end
-
- def __add__(self, other: timedelta) -> Duration:
- return self.as_interval().__add__(other)
-
- __radd__ = __add__
-
- def __sub__(self, other: timedelta) -> Duration:
- return self.as_interval().__sub__(other)
-
- def __neg__(self) -> Interval:
- return self.__class__(self.end, self.start, self._absolute)
-
- def __mul__(self, other: int | float) -> Duration:
- return self.as_interval().__mul__(other)
-
- __rmul__ = __mul__
-
- @overload
- def __floordiv__(self, other: timedelta) -> int:
- ...
-
- @overload
- def __floordiv__(self, other: int) -> Duration:
- ...
-
- def __floordiv__(self, other: int | timedelta) -> int | Duration:
- return self.as_interval().__floordiv__(other)
-
- __div__ = __floordiv__ # type: ignore[assignment]
-
- @overload
- def __truediv__(self, other: timedelta) -> float:
- ...
-
- @overload
- def __truediv__(self, other: float) -> Duration:
- ...
-
- def __truediv__(self, other: float | timedelta) -> Duration | float:
- return self.as_interval().__truediv__(other)
-
- def __mod__(self, other: timedelta) -> Duration:
- return self.as_interval().__mod__(other)
-
- def __divmod__(self, other: timedelta) -> tuple[int, Duration]:
- return self.as_interval().__divmod__(other)
-
- def __abs__(self) -> Interval:
- return self.__class__(self.start, self.end, absolute=True)
-
- def __repr__(self) -> str:
- return f"<Period [{self._start} -> {self._end}]>"
-
- def __str__(self) -> str:
- return self.__repr__()
-
- def _cmp(self, other: timedelta) -> int:
- # Only needed for PyPy
- assert isinstance(other, timedelta)
-
- if isinstance(other, Interval):
- other = other.as_timedelta()
-
- td = self.as_timedelta()
-
- return 0 if td == other else 1 if td > other else -1
-
- def _getstate(
- self, protocol: SupportsIndex = 3
- ) -> tuple[
- pendulum.DateTime | pendulum.Date | datetime | date,
- pendulum.DateTime | pendulum.Date | datetime | date,
- bool,
- ]:
- start, end = self.start, self.end
-
- if self._invert and self._absolute:
- end, start = start, end
-
- return start, end, self._absolute
-
- def __reduce__(
- self,
- ) -> tuple[
- type[Interval],
- tuple[
- pendulum.DateTime | pendulum.Date | datetime | date,
- pendulum.DateTime | pendulum.Date | datetime | date,
- bool,
- ],
- ]:
- return self.__reduce_ex__(2)
-
- def __reduce_ex__(
- self, protocol: SupportsIndex
- ) -> tuple[
- type[Interval],
- tuple[
- pendulum.DateTime | pendulum.Date | datetime | date,
- pendulum.DateTime | pendulum.Date | datetime | date,
- bool,
- ],
- ]:
- return self.__class__, self._getstate(protocol)
-
- def __hash__(self) -> int:
- return hash((self.start, self.end, self._absolute))
-
- def __eq__(self, other: object) -> bool:
- if isinstance(other, Interval):
- return (self.start, self.end, self._absolute) == (
- other.start,
- other.end,
- other._absolute,
- )
- else:
- return self.as_interval() == other
diff --git a/pendulum/locales/__init__.py b/pendulum/locales/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/cs/__init__.py b/pendulum/locales/cs/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/cs/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/cs/custom.py b/pendulum/locales/cs/custom.py
deleted file mode 100644
index 5f66b69..0000000
--- a/pendulum/locales/cs/custom.py
+++ /dev/null
@@ -1,23 +0,0 @@
-"""
-cs custom locale file.
-"""
-
-translations = {
- "units": {"few_second": "pár vteřin"},
- # Relative time
- "ago": "{} zpět",
- "from_now": "za {}",
- "after": "{0} po",
- "before": "{0} zpět",
- # Ordinals
- "ordinal": {"one": ".", "two": ".", "few": ".", "other": "."},
- # Date formats
- "date_formats": {
- "LTS": "h:mm:ss",
- "LT": "h:mm",
- "L": "DD. M. YYYY",
- "LL": "D. MMMM, YYYY",
- "LLL": "D. MMMM, YYYY h:mm",
- "LLLL": "dddd, D. MMMM, YYYY h:mm",
- },
-}
diff --git a/pendulum/locales/cs/locale.py b/pendulum/locales/cs/locale.py
deleted file mode 100644
index 2c51c78..0000000
--- a/pendulum/locales/cs/locale.py
+++ /dev/null
@@ -1,266 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-cs locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "few"
- if ((n == n and (n >= 2 and n <= 4)) and (0 == 0 and (0 == 0)))
- else "many"
- if (not (0 == 0 and (0 == 0)))
- else "one"
- if ((n == n and (n == 1)) and (0 == 0 and (0 == 0)))
- else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "ne",
- 1: "po",
- 2: "út",
- 3: "st",
- 4: "čt",
- 5: "pá",
- 6: "so",
- },
- "narrow": {
- 0: "N",
- 1: "P",
- 2: "Ú",
- 3: "S",
- 4: "Č",
- 5: "P",
- 6: "S",
- },
- "short": {
- 0: "ne",
- 1: "po",
- 2: "út",
- 3: "st",
- 4: "čt",
- 5: "pá",
- 6: "so",
- },
- "wide": {
- 0: "neděle",
- 1: "pondělí",
- 2: "úterý",
- 3: "středa",
- 4: "čtvrtek",
- 5: "pátek",
- 6: "sobota",
- },
- },
- "months": {
- "abbreviated": {
- 1: "led",
- 2: "úno",
- 3: "bře",
- 4: "dub",
- 5: "kvě",
- 6: "čvn",
- 7: "čvc",
- 8: "srp",
- 9: "zář",
- 10: "říj",
- 11: "lis",
- 12: "pro",
- },
- "narrow": {
- 1: "1",
- 2: "2",
- 3: "3",
- 4: "4",
- 5: "5",
- 6: "6",
- 7: "7",
- 8: "8",
- 9: "9",
- 10: "10",
- 11: "11",
- 12: "12",
- },
- "wide": {
- 1: "ledna",
- 2: "února",
- 3: "března",
- 4: "dubna",
- 5: "května",
- 6: "června",
- 7: "července",
- 8: "srpna",
- 9: "září",
- 10: "října",
- 11: "listopadu",
- 12: "prosince",
- },
- },
- "units": {
- "year": {
- "one": "{0} rok",
- "few": "{0} roky",
- "many": "{0} roku",
- "other": "{0} let",
- },
- "month": {
- "one": "{0} měsíc",
- "few": "{0} měsíce",
- "many": "{0} měsíce",
- "other": "{0} měsíců",
- },
- "week": {
- "one": "{0} týden",
- "few": "{0} týdny",
- "many": "{0} týdne",
- "other": "{0} týdnů",
- },
- "day": {
- "one": "{0} den",
- "few": "{0} dny",
- "many": "{0} dne",
- "other": "{0} dní",
- },
- "hour": {
- "one": "{0} hodina",
- "few": "{0} hodiny",
- "many": "{0} hodiny",
- "other": "{0} hodin",
- },
- "minute": {
- "one": "{0} minuta",
- "few": "{0} minuty",
- "many": "{0} minuty",
- "other": "{0} minut",
- },
- "second": {
- "one": "{0} sekunda",
- "few": "{0} sekundy",
- "many": "{0} sekundy",
- "other": "{0} sekund",
- },
- "microsecond": {
- "one": "{0} mikrosekunda",
- "few": "{0} mikrosekundy",
- "many": "{0} mikrosekundy",
- "other": "{0} mikrosekund",
- },
- },
- "relative": {
- "year": {
- "future": {
- "other": "za {0} let",
- "one": "za {0} rok",
- "few": "za {0} roky",
- "many": "za {0} roku",
- },
- "past": {
- "other": "před {0} lety",
- "one": "před {0} rokem",
- "few": "před {0} lety",
- "many": "před {0} roku",
- },
- },
- "month": {
- "future": {
- "other": "za {0} měsíců",
- "one": "za {0} měsíc",
- "few": "za {0} měsíce",
- "many": "za {0} měsíce",
- },
- "past": {
- "other": "před {0} měsíci",
- "one": "před {0} měsícem",
- "few": "před {0} měsíci",
- "many": "před {0} měsíce",
- },
- },
- "week": {
- "future": {
- "other": "za {0} týdnů",
- "one": "za {0} týden",
- "few": "za {0} týdny",
- "many": "za {0} týdne",
- },
- "past": {
- "other": "před {0} týdny",
- "one": "před {0} týdnem",
- "few": "před {0} týdny",
- "many": "před {0} týdne",
- },
- },
- "day": {
- "future": {
- "other": "za {0} dní",
- "one": "za {0} den",
- "few": "za {0} dny",
- "many": "za {0} dne",
- },
- "past": {
- "other": "před {0} dny",
- "one": "před {0} dnem",
- "few": "před {0} dny",
- "many": "před {0} dne",
- },
- },
- "hour": {
- "future": {
- "other": "za {0} hodin",
- "one": "za {0} hodinu",
- "few": "za {0} hodiny",
- "many": "za {0} hodiny",
- },
- "past": {
- "other": "před {0} hodinami",
- "one": "před {0} hodinou",
- "few": "před {0} hodinami",
- "many": "před {0} hodiny",
- },
- },
- "minute": {
- "future": {
- "other": "za {0} minut",
- "one": "za {0} minutu",
- "few": "za {0} minuty",
- "many": "za {0} minuty",
- },
- "past": {
- "other": "před {0} minutami",
- "one": "před {0} minutou",
- "few": "před {0} minutami",
- "many": "před {0} minuty",
- },
- },
- "second": {
- "future": {
- "other": "za {0} sekund",
- "one": "za {0} sekundu",
- "few": "za {0} sekundy",
- "many": "za {0} sekundy",
- },
- "past": {
- "other": "před {0} sekundami",
- "one": "před {0} sekundou",
- "few": "před {0} sekundami",
- "many": "před {0} sekundy",
- },
- },
- },
- "day_periods": {
- "midnight": "půlnoc",
- "am": "dop.",
- "noon": "poledne",
- "pm": "odp.",
- "morning1": "ráno",
- "morning2": "dopoledne",
- "afternoon1": "odpoledne",
- "evening1": "večer",
- "night1": "v noci",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/da/__init__.py b/pendulum/locales/da/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/da/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/da/custom.py b/pendulum/locales/da/custom.py
deleted file mode 100644
index c62ab83..0000000
--- a/pendulum/locales/da/custom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-da custom locale file.
-"""
-
-translations = {
- # Relative time
- "after": "{0} efter",
- "before": "{0} før",
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "LLLL": "dddd [d.] D. MMMM YYYY HH:mm",
- "LLL": "D. MMMM YYYY HH:mm",
- "LL": "D. MMMM YYYY",
- "L": "DD/MM/YYYY",
- },
-}
diff --git a/pendulum/locales/da/locale.py b/pendulum/locales/da/locale.py
deleted file mode 100644
index 936af3a..0000000
--- a/pendulum/locales/da/locale.py
+++ /dev/null
@@ -1,147 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-da locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one"
- if (
- (n == n and (n == 1))
- or ((not (0 == 0 and (0 == 0))) and (n == n and ((n == 0) or (n == 1))))
- )
- else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "søn.",
- 1: "man.",
- 2: "tir.",
- 3: "ons.",
- 4: "tor.",
- 5: "fre.",
- 6: "lør.",
- },
- "narrow": {0: "S", 1: "M", 2: "T", 3: "O", 4: "T", 5: "F", 6: "L"},
- "short": {0: "sø", 1: "ma", 2: "ti", 3: "on", 4: "to", 5: "fr", 6: "lø"},
- "wide": {
- 0: "søndag",
- 1: "mandag",
- 2: "tirsdag",
- 3: "onsdag",
- 4: "torsdag",
- 5: "fredag",
- 6: "lørdag",
- },
- },
- "months": {
- "abbreviated": {
- 1: "jan.",
- 2: "feb.",
- 3: "mar.",
- 4: "apr.",
- 5: "maj",
- 6: "jun.",
- 7: "jul.",
- 8: "aug.",
- 9: "sep.",
- 10: "okt.",
- 11: "nov.",
- 12: "dec.",
- },
- "narrow": {
- 1: "J",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "J",
- 7: "J",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "januar",
- 2: "februar",
- 3: "marts",
- 4: "april",
- 5: "maj",
- 6: "juni",
- 7: "juli",
- 8: "august",
- 9: "september",
- 10: "oktober",
- 11: "november",
- 12: "december",
- },
- },
- "units": {
- "year": {"one": "{0} år", "other": "{0} år"},
- "month": {"one": "{0} måned", "other": "{0} måneder"},
- "week": {"one": "{0} uge", "other": "{0} uger"},
- "day": {"one": "{0} dag", "other": "{0} dage"},
- "hour": {"one": "{0} time", "other": "{0} timer"},
- "minute": {"one": "{0} minut", "other": "{0} minutter"},
- "second": {"one": "{0} sekund", "other": "{0} sekunder"},
- "microsecond": {"one": "{0} mikrosekund", "other": "{0} mikrosekunder"},
- },
- "relative": {
- "year": {
- "future": {"other": "om {0} år", "one": "om {0} år"},
- "past": {"other": "for {0} år siden", "one": "for {0} år siden"},
- },
- "month": {
- "future": {"other": "om {0} måneder", "one": "om {0} måned"},
- "past": {
- "other": "for {0} måneder siden",
- "one": "for {0} måned siden",
- },
- },
- "week": {
- "future": {"other": "om {0} uger", "one": "om {0} uge"},
- "past": {"other": "for {0} uger siden", "one": "for {0} uge siden"},
- },
- "day": {
- "future": {"other": "om {0} dage", "one": "om {0} dag"},
- "past": {"other": "for {0} dage siden", "one": "for {0} dag siden"},
- },
- "hour": {
- "future": {"other": "om {0} timer", "one": "om {0} time"},
- "past": {"other": "for {0} timer siden", "one": "for {0} time siden"},
- },
- "minute": {
- "future": {"other": "om {0} minutter", "one": "om {0} minut"},
- "past": {
- "other": "for {0} minutter siden",
- "one": "for {0} minut siden",
- },
- },
- "second": {
- "future": {"other": "om {0} sekunder", "one": "om {0} sekund"},
- "past": {
- "other": "for {0} sekunder siden",
- "one": "for {0} sekund siden",
- },
- },
- },
- "day_periods": {
- "midnight": "midnat",
- "am": "AM",
- "pm": "PM",
- "morning1": "om morgenen",
- "morning2": "om formiddagen",
- "afternoon1": "om eftermiddagen",
- "evening1": "om aftenen",
- "night1": "om natten",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/de/__init__.py b/pendulum/locales/de/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/de/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/de/custom.py b/pendulum/locales/de/custom.py
deleted file mode 100644
index a19a8e1..0000000
--- a/pendulum/locales/de/custom.py
+++ /dev/null
@@ -1,36 +0,0 @@
-"""
-de custom locale file.
-"""
-
-translations = {
- # Relative time
- "after": "{0} später",
- "before": "{0} zuvor",
- "units_relative": {
- "year": {
- "future": {"one": "{0} Jahr", "other": "{0} Jahren"},
- "past": {"one": "{0} Jahr", "other": "{0} Jahren"},
- },
- "month": {
- "future": {"one": "{0} Monat", "other": "{0} Monaten"},
- "past": {"one": "{0} Monat", "other": "{0} Monaten"},
- },
- "week": {
- "future": {"one": "{0} Woche", "other": "{0} Wochen"},
- "past": {"one": "{0} Woche", "other": "{0} Wochen"},
- },
- "day": {
- "future": {"one": "{0} Tag", "other": "{0} Tagen"},
- "past": {"one": "{0} Tag", "other": "{0} Tagen"},
- },
- },
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "LLLL": "dddd, D. MMMM YYYY HH:mm",
- "LLL": "D. MMMM YYYY HH:mm",
- "LL": "D. MMMM YYYY",
- "L": "DD.MM.YYYY",
- },
-}
diff --git a/pendulum/locales/de/locale.py b/pendulum/locales/de/locale.py
deleted file mode 100644
index 94d2ff1..0000000
--- a/pendulum/locales/de/locale.py
+++ /dev/null
@@ -1,144 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-de locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one"
- if ((n == n and (n == 1)) and (0 == 0 and (0 == 0)))
- else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "So.",
- 1: "Mo.",
- 2: "Di.",
- 3: "Mi.",
- 4: "Do.",
- 5: "Fr.",
- 6: "Sa.",
- },
- "narrow": {0: "S", 1: "M", 2: "D", 3: "M", 4: "D", 5: "F", 6: "S"},
- "short": {
- 0: "So.",
- 1: "Mo.",
- 2: "Di.",
- 3: "Mi.",
- 4: "Do.",
- 5: "Fr.",
- 6: "Sa.",
- },
- "wide": {
- 0: "Sonntag",
- 1: "Montag",
- 2: "Dienstag",
- 3: "Mittwoch",
- 4: "Donnerstag",
- 5: "Freitag",
- 6: "Samstag",
- },
- },
- "months": {
- "abbreviated": {
- 1: "Jan.",
- 2: "Feb.",
- 3: "März",
- 4: "Apr.",
- 5: "Mai",
- 6: "Juni",
- 7: "Juli",
- 8: "Aug.",
- 9: "Sep.",
- 10: "Okt.",
- 11: "Nov.",
- 12: "Dez.",
- },
- "narrow": {
- 1: "J",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "J",
- 7: "J",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "Januar",
- 2: "Februar",
- 3: "März",
- 4: "April",
- 5: "Mai",
- 6: "Juni",
- 7: "Juli",
- 8: "August",
- 9: "September",
- 10: "Oktober",
- 11: "November",
- 12: "Dezember",
- },
- },
- "units": {
- "year": {"one": "{0} Jahr", "other": "{0} Jahre"},
- "month": {"one": "{0} Monat", "other": "{0} Monate"},
- "week": {"one": "{0} Woche", "other": "{0} Wochen"},
- "day": {"one": "{0} Tag", "other": "{0} Tage"},
- "hour": {"one": "{0} Stunde", "other": "{0} Stunden"},
- "minute": {"one": "{0} Minute", "other": "{0} Minuten"},
- "second": {"one": "{0} Sekunde", "other": "{0} Sekunden"},
- "microsecond": {"one": "{0} Mikrosekunde", "other": "{0} Mikrosekunden"},
- },
- "relative": {
- "year": {
- "future": {"other": "in {0} Jahren", "one": "in {0} Jahr"},
- "past": {"other": "vor {0} Jahren", "one": "vor {0} Jahr"},
- },
- "month": {
- "future": {"other": "in {0} Monaten", "one": "in {0} Monat"},
- "past": {"other": "vor {0} Monaten", "one": "vor {0} Monat"},
- },
- "week": {
- "future": {"other": "in {0} Wochen", "one": "in {0} Woche"},
- "past": {"other": "vor {0} Wochen", "one": "vor {0} Woche"},
- },
- "day": {
- "future": {"other": "in {0} Tagen", "one": "in {0} Tag"},
- "past": {"other": "vor {0} Tagen", "one": "vor {0} Tag"},
- },
- "hour": {
- "future": {"other": "in {0} Stunden", "one": "in {0} Stunde"},
- "past": {"other": "vor {0} Stunden", "one": "vor {0} Stunde"},
- },
- "minute": {
- "future": {"other": "in {0} Minuten", "one": "in {0} Minute"},
- "past": {"other": "vor {0} Minuten", "one": "vor {0} Minute"},
- },
- "second": {
- "future": {"other": "in {0} Sekunden", "one": "in {0} Sekunde"},
- "past": {"other": "vor {0} Sekunden", "one": "vor {0} Sekunde"},
- },
- },
- "day_periods": {
- "midnight": "Mitternacht",
- "am": "vorm.",
- "pm": "nachm.",
- "morning1": "morgens",
- "morning2": "vormittags",
- "afternoon1": "mittags",
- "afternoon2": "nachmittags",
- "evening1": "abends",
- "night1": "nachts",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/en/__init__.py b/pendulum/locales/en/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/en/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/en/custom.py b/pendulum/locales/en/custom.py
deleted file mode 100644
index a403ad8..0000000
--- a/pendulum/locales/en/custom.py
+++ /dev/null
@@ -1,23 +0,0 @@
-"""
-en custom locale file.
-"""
-
-translations = {
- "units": {"few_second": "a few seconds"},
- # Relative time
- "ago": "{} ago",
- "from_now": "in {}",
- "after": "{0} after",
- "before": "{0} before",
- # Ordinals
- "ordinal": {"one": "st", "two": "nd", "few": "rd", "other": "th"},
- # Date formats
- "date_formats": {
- "LTS": "h:mm:ss A",
- "LT": "h:mm A",
- "L": "MM/DD/YYYY",
- "LL": "MMMM D, YYYY",
- "LLL": "MMMM D, YYYY h:mm A",
- "LLLL": "dddd, MMMM D, YYYY h:mm A",
- },
-}
diff --git a/pendulum/locales/en/locale.py b/pendulum/locales/en/locale.py
deleted file mode 100644
index 00eafc2..0000000
--- a/pendulum/locales/en/locale.py
+++ /dev/null
@@ -1,150 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-en locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one"
- if ((n == n and (n == 1)) and (0 == 0 and (0 == 0)))
- else "other",
- "ordinal": lambda n: "few"
- if (
- ((n % 10) == (n % 10) and ((n % 10) == 3))
- and (not ((n % 100) == (n % 100) and ((n % 100) == 13)))
- )
- else "one"
- if (
- ((n % 10) == (n % 10) and ((n % 10) == 1))
- and (not ((n % 100) == (n % 100) and ((n % 100) == 11)))
- )
- else "two"
- if (
- ((n % 10) == (n % 10) and ((n % 10) == 2))
- and (not ((n % 100) == (n % 100) and ((n % 100) == 12)))
- )
- else "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "Sun",
- 1: "Mon",
- 2: "Tue",
- 3: "Wed",
- 4: "Thu",
- 5: "Fri",
- 6: "Sat",
- },
- "narrow": {0: "S", 1: "M", 2: "T", 3: "W", 4: "T", 5: "F", 6: "S"},
- "short": {0: "Su", 1: "Mo", 2: "Tu", 3: "We", 4: "Th", 5: "Fr", 6: "Sa"},
- "wide": {
- 0: "Sunday",
- 1: "Monday",
- 2: "Tuesday",
- 3: "Wednesday",
- 4: "Thursday",
- 5: "Friday",
- 6: "Saturday",
- },
- },
- "months": {
- "abbreviated": {
- 1: "Jan",
- 2: "Feb",
- 3: "Mar",
- 4: "Apr",
- 5: "May",
- 6: "Jun",
- 7: "Jul",
- 8: "Aug",
- 9: "Sep",
- 10: "Oct",
- 11: "Nov",
- 12: "Dec",
- },
- "narrow": {
- 1: "J",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "J",
- 7: "J",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "January",
- 2: "February",
- 3: "March",
- 4: "April",
- 5: "May",
- 6: "June",
- 7: "July",
- 8: "August",
- 9: "September",
- 10: "October",
- 11: "November",
- 12: "December",
- },
- },
- "units": {
- "year": {"one": "{0} year", "other": "{0} years"},
- "month": {"one": "{0} month", "other": "{0} months"},
- "week": {"one": "{0} week", "other": "{0} weeks"},
- "day": {"one": "{0} day", "other": "{0} days"},
- "hour": {"one": "{0} hour", "other": "{0} hours"},
- "minute": {"one": "{0} minute", "other": "{0} minutes"},
- "second": {"one": "{0} second", "other": "{0} seconds"},
- "microsecond": {"one": "{0} microsecond", "other": "{0} microseconds"},
- },
- "relative": {
- "year": {
- "future": {"other": "in {0} years", "one": "in {0} year"},
- "past": {"other": "{0} years ago", "one": "{0} year ago"},
- },
- "month": {
- "future": {"other": "in {0} months", "one": "in {0} month"},
- "past": {"other": "{0} months ago", "one": "{0} month ago"},
- },
- "week": {
- "future": {"other": "in {0} weeks", "one": "in {0} week"},
- "past": {"other": "{0} weeks ago", "one": "{0} week ago"},
- },
- "day": {
- "future": {"other": "in {0} days", "one": "in {0} day"},
- "past": {"other": "{0} days ago", "one": "{0} day ago"},
- },
- "hour": {
- "future": {"other": "in {0} hours", "one": "in {0} hour"},
- "past": {"other": "{0} hours ago", "one": "{0} hour ago"},
- },
- "minute": {
- "future": {"other": "in {0} minutes", "one": "in {0} minute"},
- "past": {"other": "{0} minutes ago", "one": "{0} minute ago"},
- },
- "second": {
- "future": {"other": "in {0} seconds", "one": "in {0} second"},
- "past": {"other": "{0} seconds ago", "one": "{0} second ago"},
- },
- },
- "day_periods": {
- "midnight": "midnight",
- "am": "AM",
- "noon": "noon",
- "pm": "PM",
- "morning1": "in the morning",
- "afternoon1": "in the afternoon",
- "evening1": "in the evening",
- "night1": "at night",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/es/__init__.py b/pendulum/locales/es/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/es/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/es/custom.py b/pendulum/locales/es/custom.py
deleted file mode 100644
index 4b7e2b5..0000000
--- a/pendulum/locales/es/custom.py
+++ /dev/null
@@ -1,23 +0,0 @@
-"""
-es custom locale file.
-"""
-
-translations = {
- "units": {"few_second": "unos segundos"},
- # Relative time
- "ago": "hace {0}",
- "from_now": "dentro de {0}",
- "after": "{0} después",
- "before": "{0} antes",
- # Ordinals
- "ordinal": {"other": "º"},
- # Date formats
- "date_formats": {
- "LTS": "H:mm:ss",
- "LT": "H:mm",
- "LLLL": "dddd, D [de] MMMM [de] YYYY H:mm",
- "LLL": "D [de] MMMM [de] YYYY H:mm",
- "LL": "D [de] MMMM [de] YYYY",
- "L": "DD/MM/YYYY",
- },
-}
diff --git a/pendulum/locales/es/locale.py b/pendulum/locales/es/locale.py
deleted file mode 100644
index edba4d3..0000000
--- a/pendulum/locales/es/locale.py
+++ /dev/null
@@ -1,141 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-es locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one" if (n == n and (n == 1)) else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "dom.",
- 1: "lun.",
- 2: "mar.",
- 3: "mié.",
- 4: "jue.",
- 5: "vie.",
- 6: "sáb.",
- },
- "narrow": {0: "D", 1: "L", 2: "M", 3: "X", 4: "J", 5: "V", 6: "S"},
- "short": {0: "DO", 1: "LU", 2: "MA", 3: "MI", 4: "JU", 5: "VI", 6: "SA"},
- "wide": {
- 0: "domingo",
- 1: "lunes",
- 2: "martes",
- 3: "miércoles",
- 4: "jueves",
- 5: "viernes",
- 6: "sábado",
- },
- },
- "months": {
- "abbreviated": {
- 1: "ene.",
- 2: "feb.",
- 3: "mar.",
- 4: "abr.",
- 5: "may.",
- 6: "jun.",
- 7: "jul.",
- 8: "ago.",
- 9: "sept.",
- 10: "oct.",
- 11: "nov.",
- 12: "dic.",
- },
- "narrow": {
- 1: "E",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "J",
- 7: "J",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "enero",
- 2: "febrero",
- 3: "marzo",
- 4: "abril",
- 5: "mayo",
- 6: "junio",
- 7: "julio",
- 8: "agosto",
- 9: "septiembre",
- 10: "octubre",
- 11: "noviembre",
- 12: "diciembre",
- },
- },
- "units": {
- "year": {"one": "{0} año", "other": "{0} años"},
- "month": {"one": "{0} mes", "other": "{0} meses"},
- "week": {"one": "{0} semana", "other": "{0} semanas"},
- "day": {"one": "{0} día", "other": "{0} días"},
- "hour": {"one": "{0} hora", "other": "{0} horas"},
- "minute": {"one": "{0} minuto", "other": "{0} minutos"},
- "second": {"one": "{0} segundo", "other": "{0} segundos"},
- "microsecond": {"one": "{0} microsegundo", "other": "{0} microsegundos"},
- },
- "relative": {
- "year": {
- "future": {"other": "dentro de {0} años", "one": "dentro de {0} año"},
- "past": {"other": "hace {0} años", "one": "hace {0} año"},
- },
- "month": {
- "future": {"other": "dentro de {0} meses", "one": "dentro de {0} mes"},
- "past": {"other": "hace {0} meses", "one": "hace {0} mes"},
- },
- "week": {
- "future": {
- "other": "dentro de {0} semanas",
- "one": "dentro de {0} semana",
- },
- "past": {"other": "hace {0} semanas", "one": "hace {0} semana"},
- },
- "day": {
- "future": {"other": "dentro de {0} días", "one": "dentro de {0} día"},
- "past": {"other": "hace {0} días", "one": "hace {0} día"},
- },
- "hour": {
- "future": {"other": "dentro de {0} horas", "one": "dentro de {0} hora"},
- "past": {"other": "hace {0} horas", "one": "hace {0} hora"},
- },
- "minute": {
- "future": {
- "other": "dentro de {0} minutos",
- "one": "dentro de {0} minuto",
- },
- "past": {"other": "hace {0} minutos", "one": "hace {0} minuto"},
- },
- "second": {
- "future": {
- "other": "dentro de {0} segundos",
- "one": "dentro de {0} segundo",
- },
- "past": {"other": "hace {0} segundos", "one": "hace {0} segundo"},
- },
- },
- "day_periods": {
- "am": "a. m.",
- "noon": "del mediodía",
- "pm": "p. m.",
- "morning1": "de la madrugada",
- "morning2": "de la mañana",
- "evening1": "de la tarde",
- "night1": "de la noche",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/fa/__init__.py b/pendulum/locales/fa/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/fa/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/fa/custom.py b/pendulum/locales/fa/custom.py
deleted file mode 100644
index 082bfad..0000000
--- a/pendulum/locales/fa/custom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-fa custom locale file.
-"""
-
-translations = {
- # Relative time
- "after": "{0} پس از",
- "before": "{0} پیش از",
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "LLLL": "dddd, D MMMM YYYY HH:mm",
- "LLL": "D MMMM YYYY HH:mm",
- "LL": "D MMMM YYYY",
- "L": "DD/MM/YYYY",
- },
-}
diff --git a/pendulum/locales/fa/locale.py b/pendulum/locales/fa/locale.py
deleted file mode 100644
index 32f8e5f..0000000
--- a/pendulum/locales/fa/locale.py
+++ /dev/null
@@ -1,135 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-fa locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one"
- if ((n == n and (n == 0)) or (n == n and (n == 1)))
- else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "یکشنبه",
- 1: "دوشنبه",
- 2: "سه\u200cشنبه",
- 3: "چهارشنبه",
- 4: "پنجشنبه",
- 5: "جمعه",
- 6: "شنبه",
- },
- "narrow": {0: "ی", 1: "د", 2: "س", 3: "چ", 4: "پ", 5: "ج", 6: "ش"},
- "short": {0: "۱ش", 1: "۲ش", 2: "۳ش", 3: "۴ش", 4: "۵ش", 5: "ج", 6: "ش"},
- "wide": {
- 0: "یکشنبه",
- 1: "دوشنبه",
- 2: "سه\u200cشنبه",
- 3: "چهارشنبه",
- 4: "پنجشنبه",
- 5: "جمعه",
- 6: "شنبه",
- },
- },
- "months": {
- "abbreviated": {
- 1: "ژانویهٔ",
- 2: "فوریهٔ",
- 3: "مارس",
- 4: "آوریل",
- 5: "مهٔ",
- 6: "ژوئن",
- 7: "ژوئیهٔ",
- 8: "اوت",
- 9: "سپتامبر",
- 10: "اکتبر",
- 11: "نوامبر",
- 12: "دسامبر",
- },
- "narrow": {
- 1: "ژ",
- 2: "ف",
- 3: "م",
- 4: "آ",
- 5: "م",
- 6: "ژ",
- 7: "ژ",
- 8: "ا",
- 9: "س",
- 10: "ا",
- 11: "ن",
- 12: "د",
- },
- "wide": {
- 1: "ژانویهٔ",
- 2: "فوریهٔ",
- 3: "مارس",
- 4: "آوریل",
- 5: "مهٔ",
- 6: "ژوئن",
- 7: "ژوئیهٔ",
- 8: "اوت",
- 9: "سپتامبر",
- 10: "اکتبر",
- 11: "نوامبر",
- 12: "دسامبر",
- },
- },
- "units": {
- "year": {"one": "{0} سال", "other": "{0} سال"},
- "month": {"one": "{0} ماه", "other": "{0} ماه"},
- "week": {"one": "{0} هفته", "other": "{0} هفته"},
- "day": {"one": "{0} روز", "other": "{0} روز"},
- "hour": {"one": "{0} ساعت", "other": "{0} ساعت"},
- "minute": {"one": "{0} دقیقه", "other": "{0} دقیقه"},
- "second": {"one": "{0} ثانیه", "other": "{0} ثانیه"},
- "microsecond": {"one": "{0} میکروثانیه", "other": "{0} میکروثانیه"},
- },
- "relative": {
- "year": {
- "future": {"other": "{0} سال بعد", "one": "{0} سال بعد"},
- "past": {"other": "{0} سال پیش", "one": "{0} سال پیش"},
- },
- "month": {
- "future": {"other": "{0} ماه بعد", "one": "{0} ماه بعد"},
- "past": {"other": "{0} ماه پیش", "one": "{0} ماه پیش"},
- },
- "week": {
- "future": {"other": "{0} هفته بعد", "one": "{0} هفته بعد"},
- "past": {"other": "{0} هفته پیش", "one": "{0} هفته پیش"},
- },
- "day": {
- "future": {"other": "{0} روز بعد", "one": "{0} روز بعد"},
- "past": {"other": "{0} روز پیش", "one": "{0} روز پیش"},
- },
- "hour": {
- "future": {"other": "{0} ساعت بعد", "one": "{0} ساعت بعد"},
- "past": {"other": "{0} ساعت پیش", "one": "{0} ساعت پیش"},
- },
- "minute": {
- "future": {"other": "{0} دقیقه بعد", "one": "{0} دقیقه بعد"},
- "past": {"other": "{0} دقیقه پیش", "one": "{0} دقیقه پیش"},
- },
- "second": {
- "future": {"other": "{0} ثانیه بعد", "one": "{0} ثانیه بعد"},
- "past": {"other": "{0} ثانیه پیش", "one": "{0} ثانیه پیش"},
- },
- },
- "day_periods": {
- "midnight": "نیمه\u200cشب",
- "am": "قبل\u200cازظهر",
- "noon": "ظهر",
- "pm": "بعدازظهر",
- "morning1": "صبح",
- "afternoon1": "عصر",
- "evening1": "عصر",
- "night1": "شب",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/fo/__init__.py b/pendulum/locales/fo/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/fo/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/fo/custom.py b/pendulum/locales/fo/custom.py
deleted file mode 100644
index 456dd59..0000000
--- a/pendulum/locales/fo/custom.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-fo custom locale file.
-"""
-
-translations = {
- # Relative time
- "after": "{0} aftaná",
- "before": "{0} áðrenn",
- # Ordinals
- "ordinal": {"other": "."},
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "LLLL": "dddd D. MMMM, YYYY HH:mm",
- "LLL": "D MMMM YYYY HH:mm",
- "LL": "D MMMM YYYY",
- "L": "DD/MM/YYYY",
- },
-}
diff --git a/pendulum/locales/fo/locale.py b/pendulum/locales/fo/locale.py
deleted file mode 100644
index 10319ea..0000000
--- a/pendulum/locales/fo/locale.py
+++ /dev/null
@@ -1,132 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-fo locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one" if (n == n and (n == 1)) else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "sun.",
- 1: "mán.",
- 2: "týs.",
- 3: "mik.",
- 4: "hós.",
- 5: "frí.",
- 6: "ley.",
- },
- "narrow": {0: "S", 1: "M", 2: "T", 3: "M", 4: "H", 5: "F", 6: "L"},
- "short": {
- 0: "su.",
- 1: "má.",
- 2: "tý.",
- 3: "mi.",
- 4: "hó.",
- 5: "fr.",
- 6: "le.",
- },
- "wide": {
- 0: "sunnudagur",
- 1: "mánadagur",
- 2: "týsdagur",
- 3: "mikudagur",
- 4: "hósdagur",
- 5: "fríggjadagur",
- 6: "leygardagur",
- },
- },
- "months": {
- "abbreviated": {
- 1: "jan.",
- 2: "feb.",
- 3: "mar.",
- 4: "apr.",
- 5: "mai",
- 6: "jun.",
- 7: "jul.",
- 8: "aug.",
- 9: "sep.",
- 10: "okt.",
- 11: "nov.",
- 12: "des.",
- },
- "narrow": {
- 1: "J",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "J",
- 7: "J",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "januar",
- 2: "februar",
- 3: "mars",
- 4: "apríl",
- 5: "mai",
- 6: "juni",
- 7: "juli",
- 8: "august",
- 9: "september",
- 10: "oktober",
- 11: "november",
- 12: "desember",
- },
- },
- "units": {
- "year": {"one": "{0} ár", "other": "{0} ár"},
- "month": {"one": "{0} mánaður", "other": "{0} mánaðir"},
- "week": {"one": "{0} vika", "other": "{0} vikur"},
- "day": {"one": "{0} dagur", "other": "{0} dagar"},
- "hour": {"one": "{0} tími", "other": "{0} tímar"},
- "minute": {"one": "{0} minuttur", "other": "{0} minuttir"},
- "second": {"one": "{0} sekund", "other": "{0} sekundir"},
- "microsecond": {"one": "{0} mikrosekund", "other": "{0} mikrosekundir"},
- },
- "relative": {
- "year": {
- "future": {"other": "um {0} ár", "one": "um {0} ár"},
- "past": {"other": "{0} ár síðan", "one": "{0} ár síðan"},
- },
- "month": {
- "future": {"other": "um {0} mánaðir", "one": "um {0} mánað"},
- "past": {"other": "{0} mánaðir síðan", "one": "{0} mánað síðan"},
- },
- "week": {
- "future": {"other": "um {0} vikur", "one": "um {0} viku"},
- "past": {"other": "{0} vikur síðan", "one": "{0} vika síðan"},
- },
- "day": {
- "future": {"other": "um {0} dagar", "one": "um {0} dag"},
- "past": {"other": "{0} dagar síðan", "one": "{0} dagur síðan"},
- },
- "hour": {
- "future": {"other": "um {0} tímar", "one": "um {0} tíma"},
- "past": {"other": "{0} tímar síðan", "one": "{0} tími síðan"},
- },
- "minute": {
- "future": {"other": "um {0} minuttir", "one": "um {0} minutt"},
- "past": {"other": "{0} minuttir síðan", "one": "{0} minutt síðan"},
- },
- "second": {
- "future": {"other": "um {0} sekund", "one": "um {0} sekund"},
- "past": {"other": "{0} sekund síðan", "one": "{0} sekund síðan"},
- },
- },
- "day_periods": {"am": "AM", "pm": "PM"},
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/fr/__init__.py b/pendulum/locales/fr/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/fr/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/fr/custom.py b/pendulum/locales/fr/custom.py
deleted file mode 100644
index 134f297..0000000
--- a/pendulum/locales/fr/custom.py
+++ /dev/null
@@ -1,23 +0,0 @@
-"""
-fr custom locale file.
-"""
-
-translations = {
- "units": {"few_second": "quelques secondes"},
- # Relative Time
- "ago": "il y a {0}",
- "from_now": "dans {0}",
- "after": "{0} après",
- "before": "{0} avant",
- # Ordinals
- "ordinal": {"one": "er", "other": "e"},
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "LLLL": "dddd D MMMM YYYY HH:mm",
- "LLL": "D MMMM YYYY HH:mm",
- "LL": "D MMMM YYYY",
- "L": "DD/MM/YYYY",
- },
-}
diff --git a/pendulum/locales/fr/locale.py b/pendulum/locales/fr/locale.py
deleted file mode 100644
index 8855d53..0000000
--- a/pendulum/locales/fr/locale.py
+++ /dev/null
@@ -1,133 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-fr locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one" if (n == n and ((n == 0) or (n == 1))) else "other",
- "ordinal": lambda n: "one" if (n == n and (n == 1)) else "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "dim.",
- 1: "lun.",
- 2: "mar.",
- 3: "mer.",
- 4: "jeu.",
- 5: "ven.",
- 6: "sam.",
- },
- "narrow": {0: "D", 1: "L", 2: "M", 3: "M", 4: "J", 5: "V", 6: "S"},
- "short": {0: "di", 1: "lu", 2: "ma", 3: "me", 4: "je", 5: "ve", 6: "sa"},
- "wide": {
- 0: "dimanche",
- 1: "lundi",
- 2: "mardi",
- 3: "mercredi",
- 4: "jeudi",
- 5: "vendredi",
- 6: "samedi",
- },
- },
- "months": {
- "abbreviated": {
- 1: "janv.",
- 2: "févr.",
- 3: "mars",
- 4: "avr.",
- 5: "mai",
- 6: "juin",
- 7: "juil.",
- 8: "août",
- 9: "sept.",
- 10: "oct.",
- 11: "nov.",
- 12: "déc.",
- },
- "narrow": {
- 1: "J",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "J",
- 7: "J",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "janvier",
- 2: "février",
- 3: "mars",
- 4: "avril",
- 5: "mai",
- 6: "juin",
- 7: "juillet",
- 8: "août",
- 9: "septembre",
- 10: "octobre",
- 11: "novembre",
- 12: "décembre",
- },
- },
- "units": {
- "year": {"one": "{0} an", "other": "{0} ans"},
- "month": {"one": "{0} mois", "other": "{0} mois"},
- "week": {"one": "{0} semaine", "other": "{0} semaines"},
- "day": {"one": "{0} jour", "other": "{0} jours"},
- "hour": {"one": "{0} heure", "other": "{0} heures"},
- "minute": {"one": "{0} minute", "other": "{0} minutes"},
- "second": {"one": "{0} seconde", "other": "{0} secondes"},
- "microsecond": {"one": "{0} microseconde", "other": "{0} microsecondes"},
- },
- "relative": {
- "year": {
- "future": {"other": "dans {0} ans", "one": "dans {0} an"},
- "past": {"other": "il y a {0} ans", "one": "il y a {0} an"},
- },
- "month": {
- "future": {"other": "dans {0} mois", "one": "dans {0} mois"},
- "past": {"other": "il y a {0} mois", "one": "il y a {0} mois"},
- },
- "week": {
- "future": {"other": "dans {0} semaines", "one": "dans {0} semaine"},
- "past": {"other": "il y a {0} semaines", "one": "il y a {0} semaine"},
- },
- "day": {
- "future": {"other": "dans {0} jours", "one": "dans {0} jour"},
- "past": {"other": "il y a {0} jours", "one": "il y a {0} jour"},
- },
- "hour": {
- "future": {"other": "dans {0} heures", "one": "dans {0} heure"},
- "past": {"other": "il y a {0} heures", "one": "il y a {0} heure"},
- },
- "minute": {
- "future": {"other": "dans {0} minutes", "one": "dans {0} minute"},
- "past": {"other": "il y a {0} minutes", "one": "il y a {0} minute"},
- },
- "second": {
- "future": {"other": "dans {0} secondes", "one": "dans {0} seconde"},
- "past": {"other": "il y a {0} secondes", "one": "il y a {0} seconde"},
- },
- },
- "day_periods": {
- "midnight": "minuit",
- "am": "AM",
- "noon": "midi",
- "pm": "PM",
- "morning1": "du matin",
- "afternoon1": "de l’après-midi",
- "evening1": "du soir",
- "night1": "de nuit",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/he/__init__.py b/pendulum/locales/he/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/he/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/he/custom.py b/pendulum/locales/he/custom.py
deleted file mode 100644
index 51f8476..0000000
--- a/pendulum/locales/he/custom.py
+++ /dev/null
@@ -1,23 +0,0 @@
-"""
-he custom locale file.
-"""
-
-translations = {
- "units": {"few_second": "כמה שניות"},
- # Relative time
- "ago": "לפני {0}",
- "from_now": "תוך {0}",
- "after": "בעוד {0}",
- "before": "{0} קודם",
- # Ordinals
- "ordinal": {"other": "º"},
- # Date formats
- "date_formats": {
- "LTS": "H:mm:ss",
- "LT": "H:mm",
- "LLLL": "dddd, D [ב] MMMM [ב] YYYY H:mm",
- "LLL": "D [ב] MMMM [ב] YYYY H:mm",
- "LL": "D [ב] MMMM [ב] YYYY",
- "L": "DD/MM/YYYY",
- },
-}
diff --git a/pendulum/locales/he/locale.py b/pendulum/locales/he/locale.py
deleted file mode 100644
index 457c101..0000000
--- a/pendulum/locales/he/locale.py
+++ /dev/null
@@ -1,269 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-he locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "many"
- if (
- ((0 == 0 and (0 == 0)) and (not (n == n and (n >= 0 and n <= 10))))
- and ((n % 10) == (n % 10) and ((n % 10) == 0))
- )
- else "one"
- if ((n == n and (n == 1)) and (0 == 0 and (0 == 0)))
- else "two"
- if ((n == n and (n == 2)) and (0 == 0 and (0 == 0)))
- else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "יום א׳",
- 1: "יום ב׳",
- 2: "יום ג׳",
- 3: "יום ד׳",
- 4: "יום ה׳",
- 5: "יום ו׳",
- 6: "שבת",
- },
- "narrow": {
- 0: "א׳",
- 1: "ב׳",
- 2: "ג׳",
- 3: "ד׳",
- 4: "ה׳",
- 5: "ו׳",
- 6: "ש׳",
- },
- "short": {
- 0: "א׳",
- 1: "ב׳",
- 2: "ג׳",
- 3: "ד׳",
- 4: "ה׳",
- 5: "ו׳",
- 6: "ש׳",
- },
- "wide": {
- 0: "יום ראשון",
- 1: "יום שני",
- 2: "יום שלישי",
- 3: "יום רביעי",
- 4: "יום חמישי",
- 5: "יום שישי",
- 6: "יום שבת",
- },
- },
- "months": {
- "abbreviated": {
- 1: "ינו׳",
- 2: "פבר׳",
- 3: "מרץ",
- 4: "אפר׳",
- 5: "מאי",
- 6: "יוני",
- 7: "יולי",
- 8: "אוג׳",
- 9: "ספט׳",
- 10: "אוק׳",
- 11: "נוב׳",
- 12: "דצמ׳",
- },
- "narrow": {
- 1: "1",
- 2: "2",
- 3: "3",
- 4: "4",
- 5: "5",
- 6: "6",
- 7: "7",
- 8: "8",
- 9: "9",
- 10: "10",
- 11: "11",
- 12: "12",
- },
- "wide": {
- 1: "ינואר",
- 2: "פברואר",
- 3: "מרץ",
- 4: "אפריל",
- 5: "מאי",
- 6: "יוני",
- 7: "יולי",
- 8: "אוגוסט",
- 9: "ספטמבר",
- 10: "אוקטובר",
- 11: "נובמבר",
- 12: "דצמבר",
- },
- },
- "units": {
- "year": {
- "one": "שנה",
- "two": "שנתיים",
- "many": "{0} שנים",
- "other": "{0} שנים",
- },
- "month": {
- "one": "חודש",
- "two": "חודשיים",
- "many": "{0} חודשים",
- "other": "{0} חודשים",
- },
- "week": {
- "one": "שבוע",
- "two": "שבועיים",
- "many": "{0} שבועות",
- "other": "{0} שבועות",
- },
- "day": {
- "one": "יום {0}",
- "two": "יומיים",
- "many": "{0} יום",
- "other": "{0} ימים",
- },
- "hour": {
- "one": "שעה",
- "two": "שעתיים",
- "many": "{0} שעות",
- "other": "{0} שעות",
- },
- "minute": {
- "one": "דקה",
- "two": "שתי דקות",
- "many": "{0} דקות",
- "other": "{0} דקות",
- },
- "second": {
- "one": "שניה",
- "two": "שתי שניות",
- "many": "\u200f{0} שניות",
- "other": "{0} שניות",
- },
- "microsecond": {
- "one": "{0} מיליונית שנייה",
- "two": "{0} מיליוניות שנייה",
- "many": "{0} מיליוניות שנייה",
- "other": "{0} מיליוניות שנייה",
- },
- },
- "relative": {
- "year": {
- "future": {
- "other": "בעוד {0} שנים",
- "one": "בעוד שנה",
- "two": "בעוד שנתיים",
- "many": "בעוד {0} שנה",
- },
- "past": {
- "other": "לפני {0} שנים",
- "one": "לפני שנה",
- "two": "לפני שנתיים",
- "many": "לפני {0} שנה",
- },
- },
- "month": {
- "future": {
- "other": "בעוד {0} חודשים",
- "one": "בעוד חודש",
- "two": "בעוד חודשיים",
- "many": "בעוד {0} חודשים",
- },
- "past": {
- "other": "לפני {0} חודשים",
- "one": "לפני חודש",
- "two": "לפני חודשיים",
- "many": "לפני {0} חודשים",
- },
- },
- "week": {
- "future": {
- "other": "בעוד {0} שבועות",
- "one": "בעוד שבוע",
- "two": "בעוד שבועיים",
- "many": "בעוד {0} שבועות",
- },
- "past": {
- "other": "לפני {0} שבועות",
- "one": "לפני שבוע",
- "two": "לפני שבועיים",
- "many": "לפני {0} שבועות",
- },
- },
- "day": {
- "future": {
- "other": "בעוד {0} ימים",
- "one": "בעוד יום {0}",
- "two": "בעוד יומיים",
- "many": "בעוד {0} ימים",
- },
- "past": {
- "other": "לפני {0} ימים",
- "one": "לפני יום {0}",
- "two": "לפני יומיים",
- "many": "לפני {0} ימים",
- },
- },
- "hour": {
- "future": {
- "other": "בעוד {0} שעות",
- "one": "בעוד שעה",
- "two": "בעוד שעתיים",
- "many": "בעוד {0} שעות",
- },
- "past": {
- "other": "לפני {0} שעות",
- "one": "לפני שעה",
- "two": "לפני שעתיים",
- "many": "לפני {0} שעות",
- },
- },
- "minute": {
- "future": {
- "other": "בעוד {0} דקות",
- "one": "בעוד דקה",
- "two": "בעוד שתי דקות",
- "many": "בעוד {0} דקות",
- },
- "past": {
- "other": "לפני {0} דקות",
- "one": "לפני דקה",
- "two": "לפני שתי דקות",
- "many": "לפני {0} דקות",
- },
- },
- "second": {
- "future": {
- "other": "בעוד {0} שניות",
- "one": "בעוד שנייה",
- "two": "בעוד שתי שניות",
- "many": "בעוד {0} שניות",
- },
- "past": {
- "other": "לפני {0} שניות",
- "one": "לפני שנייה",
- "two": "לפני שתי שניות",
- "many": "לפני {0} שניות",
- },
- },
- },
- "day_periods": {
- "midnight": "חצות",
- "am": "לפנה״צ",
- "pm": "אחה״צ",
- "morning1": "בבוקר",
- "afternoon1": "בצהריים",
- "afternoon2": "אחר הצהריים",
- "evening1": "בערב",
- "night1": "בלילה",
- "night2": "לפנות בוקר",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/id/__init__.py b/pendulum/locales/id/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/id/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/id/custom.py b/pendulum/locales/id/custom.py
deleted file mode 100644
index 3ba2035..0000000
--- a/pendulum/locales/id/custom.py
+++ /dev/null
@@ -1,19 +0,0 @@
-"""
-id custom locale file.
-"""
-
-translations = {
- "units": {"few_second": "beberapa detik"},
- "ago": "{} yang lalu",
- "from_now": "dalam {}",
- "after": "{0} kemudian",
- "before": "{0} yang lalu",
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "LLLL": "dddd [d.] D. MMMM YYYY HH:mm",
- "LLL": "D. MMMM YYYY HH:mm",
- "LL": "D. MMMM YYYY",
- "L": "DD/MM/YYYY",
- },
-}
diff --git a/pendulum/locales/id/locale.py b/pendulum/locales/id/locale.py
deleted file mode 100644
index bc994ce..0000000
--- a/pendulum/locales/id/locale.py
+++ /dev/null
@@ -1,141 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-id locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "Min",
- 1: "Sen",
- 2: "Sel",
- 3: "Rab",
- 4: "Kam",
- 5: "Jum",
- 6: "Sab",
- },
- "narrow": {0: "M", 1: "S", 2: "S", 3: "R", 4: "K", 5: "J", 6: "S"},
- "short": {
- 0: "Min",
- 1: "Sen",
- 2: "Sel",
- 3: "Rab",
- 4: "Kam",
- 5: "Jum",
- 6: "Sab",
- },
- "wide": {
- 0: "Minggu",
- 1: "Senin",
- 2: "Selasa",
- 3: "Rabu",
- 4: "Kamis",
- 5: "Jumat",
- 6: "Sabtu",
- },
- },
- "months": {
- "abbreviated": {
- 1: "Jan",
- 2: "Feb",
- 3: "Mar",
- 4: "Apr",
- 5: "Mei",
- 6: "Jun",
- 7: "Jul",
- 8: "Agt",
- 9: "Sep",
- 10: "Okt",
- 11: "Nov",
- 12: "Des",
- },
- "narrow": {
- 1: "J",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "J",
- 7: "J",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "Januari",
- 2: "Februari",
- 3: "Maret",
- 4: "April",
- 5: "Mei",
- 6: "Juni",
- 7: "Juli",
- 8: "Agustus",
- 9: "September",
- 10: "Oktober",
- 11: "November",
- 12: "Desember",
- },
- },
- "units": {
- "year": {"other": "{0} tahun"},
- "month": {"other": "{0} bulan"},
- "week": {"other": "{0} minggu"},
- "day": {"other": "{0} hari"},
- "hour": {"other": "{0} jam"},
- "minute": {"other": "{0} menit"},
- "second": {"other": "{0} detik"},
- "microsecond": {"other": "{0} mikrodetik"},
- },
- "relative": {
- "year": {
- "future": {"other": "dalam {0} tahun"},
- "past": {"other": "{0} tahun yang lalu"},
- },
- "month": {
- "future": {"other": "dalam {0} bulan"},
- "past": {"other": "{0} bulan yang lalu"},
- },
- "week": {
- "future": {"other": "dalam {0} minggu"},
- "past": {"other": "{0} minggu yang lalu"},
- },
- "day": {
- "future": {"other": "dalam {0} hari"},
- "past": {"other": "{0} hari yang lalu"},
- },
- "hour": {
- "future": {"other": "dalam {0} jam"},
- "past": {"other": "{0} jam yang lalu"},
- },
- "minute": {
- "future": {"other": "dalam {0} menit"},
- "past": {"other": "{0} menit yang lalu"},
- },
- "second": {
- "future": {"other": "dalam {0} detik"},
- "past": {"other": "{0} detik yang lalu"},
- },
- },
- "day_periods": {
- "midnight": "tengah malam",
- "am": "AM",
- "noon": "tengah hari",
- "pm": "PM",
- "morning1": "pagi",
- "afternoon1": "siang",
- "evening1": "sore",
- "night1": "malam",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/it/__init__.py b/pendulum/locales/it/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/it/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/it/custom.py b/pendulum/locales/it/custom.py
deleted file mode 100644
index e5cf1cc..0000000
--- a/pendulum/locales/it/custom.py
+++ /dev/null
@@ -1,24 +0,0 @@
-"""
-it custom locale file.
-"""
-
-
-translations = {
- "units": {"few_second": "alcuni secondi"},
- # Relative Time
- "ago": "{0} fa",
- "from_now": "in {0}",
- "after": "{0} dopo",
- "before": "{0} prima",
- # Ordinals
- "ordinal": {"other": "°"},
- # Date formats
- "date_formats": {
- "LTS": "H:mm:ss",
- "LT": "H:mm",
- "L": "DD/MM/YYYY",
- "LL": "D MMMM YYYY",
- "LLL": "D MMMM YYYY [alle] H:mm",
- "LLLL": "dddd, D MMMM YYYY [alle] H:mm",
- },
-}
diff --git a/pendulum/locales/it/locale.py b/pendulum/locales/it/locale.py
deleted file mode 100644
index bb3fdcf..0000000
--- a/pendulum/locales/it/locale.py
+++ /dev/null
@@ -1,145 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-it locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one"
- if ((n == n and (n == 1)) and (0 == 0 and (0 == 0)))
- else "other",
- "ordinal": lambda n: "many"
- if (n == n and ((n == 11) or (n == 8) or (n == 80) or (n == 800)))
- else "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "dom",
- 1: "lun",
- 2: "mar",
- 3: "mer",
- 4: "gio",
- 5: "ven",
- 6: "sab",
- },
- "narrow": {0: "D", 1: "L", 2: "M", 3: "M", 4: "G", 5: "V", 6: "S"},
- "short": {
- 0: "dom",
- 1: "lun",
- 2: "mar",
- 3: "mer",
- 4: "gio",
- 5: "ven",
- 6: "sab",
- },
- "wide": {
- 0: "domenica",
- 1: "lunedì",
- 2: "martedì",
- 3: "mercoledì",
- 4: "giovedì",
- 5: "venerdì",
- 6: "sabato",
- },
- },
- "months": {
- "abbreviated": {
- 1: "gen",
- 2: "feb",
- 3: "mar",
- 4: "apr",
- 5: "mag",
- 6: "giu",
- 7: "lug",
- 8: "ago",
- 9: "set",
- 10: "ott",
- 11: "nov",
- 12: "dic",
- },
- "narrow": {
- 1: "G",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "G",
- 7: "L",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "gennaio",
- 2: "febbraio",
- 3: "marzo",
- 4: "aprile",
- 5: "maggio",
- 6: "giugno",
- 7: "luglio",
- 8: "agosto",
- 9: "settembre",
- 10: "ottobre",
- 11: "novembre",
- 12: "dicembre",
- },
- },
- "units": {
- "year": {"one": "{0} anno", "other": "{0} anni"},
- "month": {"one": "{0} mese", "other": "{0} mesi"},
- "week": {"one": "{0} settimana", "other": "{0} settimane"},
- "day": {"one": "{0} giorno", "other": "{0} giorni"},
- "hour": {"one": "{0} ora", "other": "{0} ore"},
- "minute": {"one": "{0} minuto", "other": "{0} minuti"},
- "second": {"one": "{0} secondo", "other": "{0} secondi"},
- "microsecond": {"one": "{0} microsecondo", "other": "{0} microsecondi"},
- },
- "relative": {
- "year": {
- "future": {"other": "tra {0} anni", "one": "tra {0} anno"},
- "past": {"other": "{0} anni fa", "one": "{0} anno fa"},
- },
- "month": {
- "future": {"other": "tra {0} mesi", "one": "tra {0} mese"},
- "past": {"other": "{0} mesi fa", "one": "{0} mese fa"},
- },
- "week": {
- "future": {"other": "tra {0} settimane", "one": "tra {0} settimana"},
- "past": {"other": "{0} settimane fa", "one": "{0} settimana fa"},
- },
- "day": {
- "future": {"other": "tra {0} giorni", "one": "tra {0} giorno"},
- "past": {"other": "{0} giorni fa", "one": "{0} giorno fa"},
- },
- "hour": {
- "future": {"other": "tra {0} ore", "one": "tra {0} ora"},
- "past": {"other": "{0} ore fa", "one": "{0} ora fa"},
- },
- "minute": {
- "future": {"other": "tra {0} minuti", "one": "tra {0} minuto"},
- "past": {"other": "{0} minuti fa", "one": "{0} minuto fa"},
- },
- "second": {
- "future": {"other": "tra {0} secondi", "one": "tra {0} secondo"},
- "past": {"other": "{0} secondi fa", "one": "{0} secondo fa"},
- },
- },
- "day_periods": {
- "midnight": "mezzanotte",
- "am": "AM",
- "noon": "mezzogiorno",
- "pm": "PM",
- "morning1": "di mattina",
- "afternoon1": "del pomeriggio",
- "evening1": "di sera",
- "night1": "di notte",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/ja/__init__.py b/pendulum/locales/ja/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/ja/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/ja/custom.py b/pendulum/locales/ja/custom.py
deleted file mode 100644
index c076250..0000000
--- a/pendulum/locales/ja/custom.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""
-ja custom locale file.
-"""
-
-translations = {
- "units": {"few_second": "数秒"},
- # Relative time
- "ago": "{} 前に",
- "from_now": "今から {}",
- "after": "{0} 後",
- "before": "{0} 前",
- # Date formats
- "date_formats": {
- "LTS": "h:mm:ss A",
- "LT": "h:mm A",
- "L": "MM/DD/YYYY",
- "LL": "MMMM D, YYYY",
- "LLL": "MMMM D, YYYY h:mm A",
- "LLLL": "dddd, MMMM D, YYYY h:mm A",
- },
-}
diff --git a/pendulum/locales/ja/locale.py b/pendulum/locales/ja/locale.py
deleted file mode 100644
index 574d2ec..0000000
--- a/pendulum/locales/ja/locale.py
+++ /dev/null
@@ -1,194 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-ja locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "日",
- 1: "月",
- 2: "火",
- 3: "水",
- 4: "木",
- 5: "金",
- 6: "土",
- },
- "narrow": {
- 0: "日",
- 1: "月",
- 2: "火",
- 3: "水",
- 4: "木",
- 5: "金",
- 6: "土",
- },
- "short": {
- 0: "日",
- 1: "月",
- 2: "火",
- 3: "水",
- 4: "木",
- 5: "金",
- 6: "土",
- },
- "wide": {
- 0: "日曜日",
- 1: "月曜日",
- 2: "火曜日",
- 3: "水曜日",
- 4: "木曜日",
- 5: "金曜日",
- 6: "土曜日",
- },
- },
- "months": {
- "abbreviated": {
- 1: "1月",
- 2: "2月",
- 3: "3月",
- 4: "4月",
- 5: "5月",
- 6: "6月",
- 7: "7月",
- 8: "8月",
- 9: "9月",
- 10: "10月",
- 11: "11月",
- 12: "12月",
- },
- "narrow": {
- 1: "1",
- 2: "2",
- 3: "3",
- 4: "4",
- 5: "5",
- 6: "6",
- 7: "7",
- 8: "8",
- 9: "9",
- 10: "10",
- 11: "11",
- 12: "12",
- },
- "wide": {
- 1: "1月",
- 2: "2月",
- 3: "3月",
- 4: "4月",
- 5: "5月",
- 6: "6月",
- 7: "7月",
- 8: "8月",
- 9: "9月",
- 10: "10月",
- 11: "11月",
- 12: "12月",
- },
- },
- "units": {
- "year": {
- "other": "{0} 年",
- },
- "month": {
- "other": "{0} か月",
- },
- "week": {
- "other": "{0} 週間",
- },
- "day": {
- "other": "{0} 日",
- },
- "hour": {
- "other": "{0} 時間",
- },
- "minute": {
- "other": "{0} 分",
- },
- "second": {
- "other": "{0} 秒",
- },
- "microsecond": {
- "other": "{0} マイクロ秒",
- },
- },
- "relative": {
- "year": {
- "future": {
- "other": "{0} 年後",
- },
- "past": {
- "other": "{0} 年前",
- },
- },
- "month": {
- "future": {
- "other": "{0} か月後",
- },
- "past": {
- "other": "{0} か月前",
- },
- },
- "week": {
- "future": {
- "other": "{0} 週間後",
- },
- "past": {
- "other": "{0} 週間前",
- },
- },
- "day": {
- "future": {
- "other": "{0} 日後",
- },
- "past": {
- "other": "{0} 日前",
- },
- },
- "hour": {
- "future": {
- "other": "{0} 時間後",
- },
- "past": {
- "other": "{0} 時間前",
- },
- },
- "minute": {
- "future": {
- "other": "{0} 分後",
- },
- "past": {
- "other": "{0} 分前",
- },
- },
- "second": {
- "future": {
- "other": "{0} 秒後",
- },
- "past": {
- "other": "{0} 秒前",
- },
- },
- },
- "day_periods": {
- "midnight": "真夜中",
- "am": "午前",
- "noon": "正午",
- "pm": "午後",
- "morning1": "朝",
- "afternoon1": "昼",
- "evening1": "夕方",
- "night1": "夜",
- "night2": "夜中",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/ko/__init__.py b/pendulum/locales/ko/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/ko/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/ko/custom.py b/pendulum/locales/ko/custom.py
deleted file mode 100644
index 2c0e50c..0000000
--- a/pendulum/locales/ko/custom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-ko custom locale file.
-"""
-
-translations = {
- # Relative time
- "after": "{0} 뒤",
- "before": "{0} 앞",
- # Date formats
- "date_formats": {
- "LTS": "A h시 m분 s초",
- "LT": "A h시 m분",
- "LLLL": "YYYY년 MMMM D일 dddd A h시 m분",
- "LLL": "YYYY년 MMMM D일 A h시 m분",
- "LL": "YYYY년 MMMM D일",
- "L": "YYYY.MM.DD",
- },
-}
diff --git a/pendulum/locales/ko/locale.py b/pendulum/locales/ko/locale.py
deleted file mode 100644
index 0f5a346..0000000
--- a/pendulum/locales/ko/locale.py
+++ /dev/null
@@ -1,105 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-ko locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {0: "일", 1: "월", 2: "화", 3: "수", 4: "목", 5: "금", 6: "토"},
- "narrow": {0: "일", 1: "월", 2: "화", 3: "수", 4: "목", 5: "금", 6: "토"},
- "short": {0: "일", 1: "월", 2: "화", 3: "수", 4: "목", 5: "금", 6: "토"},
- "wide": {
- 0: "일요일",
- 1: "월요일",
- 2: "화요일",
- 3: "수요일",
- 4: "목요일",
- 5: "금요일",
- 6: "토요일",
- },
- },
- "months": {
- "abbreviated": {
- 1: "1월",
- 2: "2월",
- 3: "3월",
- 4: "4월",
- 5: "5월",
- 6: "6월",
- 7: "7월",
- 8: "8월",
- 9: "9월",
- 10: "10월",
- 11: "11월",
- 12: "12월",
- },
- "narrow": {
- 1: "1월",
- 2: "2월",
- 3: "3월",
- 4: "4월",
- 5: "5월",
- 6: "6월",
- 7: "7월",
- 8: "8월",
- 9: "9월",
- 10: "10월",
- 11: "11월",
- 12: "12월",
- },
- "wide": {
- 1: "1월",
- 2: "2월",
- 3: "3월",
- 4: "4월",
- 5: "5월",
- 6: "6월",
- 7: "7월",
- 8: "8월",
- 9: "9월",
- 10: "10월",
- 11: "11월",
- 12: "12월",
- },
- },
- "units": {
- "year": {"other": "{0}년"},
- "month": {"other": "{0}개월"},
- "week": {"other": "{0}주"},
- "day": {"other": "{0}일"},
- "hour": {"other": "{0}시간"},
- "minute": {"other": "{0}분"},
- "second": {"other": "{0}초"},
- "microsecond": {"other": "{0}마이크로초"},
- },
- "relative": {
- "year": {"future": {"other": "{0}년 후"}, "past": {"other": "{0}년 전"}},
- "month": {"future": {"other": "{0}개월 후"}, "past": {"other": "{0}개월 전"}},
- "week": {"future": {"other": "{0}주 후"}, "past": {"other": "{0}주 전"}},
- "day": {"future": {"other": "{0}일 후"}, "past": {"other": "{0}일 전"}},
- "hour": {"future": {"other": "{0}시간 후"}, "past": {"other": "{0}시간 전"}},
- "minute": {"future": {"other": "{0}분 후"}, "past": {"other": "{0}분 전"}},
- "second": {"future": {"other": "{0}초 후"}, "past": {"other": "{0}초 전"}},
- },
- "day_periods": {
- "midnight": "자정",
- "am": "오전",
- "noon": "정오",
- "pm": "오후",
- "morning1": "새벽",
- "morning2": "오전",
- "afternoon1": "오후",
- "evening1": "저녁",
- "night1": "밤",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/locale.py b/pendulum/locales/locale.py
deleted file mode 100644
index 637509a..0000000
--- a/pendulum/locales/locale.py
+++ /dev/null
@@ -1,102 +0,0 @@
-from __future__ import annotations
-
-from importlib import import_module
-from pathlib import Path
-
-import re
-import sys
-from typing import Any, cast
-from typing import Dict
-
-if sys.version_info >= (3, 9):
- from importlib import resources
-else:
- import importlib_resources as resources
-
-
-class Locale:
- """
- Represent a specific locale.
- """
-
- _cache: dict[str, Locale] = {}
-
- def __init__(self, locale: str, data: Any) -> None:
- self._locale: str = locale
- self._data: Any = data
- self._key_cache: dict[str, str] = {}
-
- @classmethod
- def load(cls, locale: str | Locale) -> Locale:
- if isinstance(locale, Locale):
- return locale
-
- locale = cls.normalize_locale(locale)
- if locale in cls._cache:
- return cls._cache[locale]
-
- # Checking locale existence
- actual_locale = locale
- locale_path = cast(Path, resources.files(__package__).joinpath(actual_locale))
- while not locale_path.exists():
- if actual_locale == locale:
- raise ValueError(f"Locale [{locale}] does not exist.")
-
- actual_locale = actual_locale.split("_")[0]
-
- m = import_module(f"pendulum.locales.{actual_locale}.locale")
-
- cls._cache[locale] = cls(locale, m.locale)
-
- return cls._cache[locale]
-
- @classmethod
- def normalize_locale(cls, locale: str) -> str:
- m = re.match("([a-z]{2})[-_]([a-z]{2})", locale, re.I)
- if m:
- return f"{m.group(1).lower()}_{m.group(2).lower()}"
- else:
- return locale.lower()
-
- def get(self, key: str, default: Any | None = None) -> Any:
- if key in self._key_cache:
- return self._key_cache[key]
-
- parts = key.split(".")
- try:
- result = self._data[parts[0]]
- for part in parts[1:]:
- result = result[part]
- except KeyError:
- result = default
-
- self._key_cache[key] = result
-
- return self._key_cache[key]
-
- def translation(self, key: str) -> Any:
- return self.get(f"translations.{key}")
-
- def plural(self, number: int) -> str:
- return cast(str, self._data["plural"](number))
-
- def ordinal(self, number: int) -> str:
- return cast(str, self._data["ordinal"](number))
-
- def ordinalize(self, number: int) -> str:
- ordinal = self.get(f"custom.ordinal.{self.ordinal(number)}")
-
- if not ordinal:
- return f"{number}"
-
- return f"{number}{ordinal}"
-
- def match_translation(self, key: str, value: Any) -> dict[str, str] | None:
- translations = self.translation(key)
- if value not in translations.values():
- return None
-
- return cast(Dict[str, str], {v: k for k, v in translations.items()}[value])
-
- def __repr__(self) -> str:
- return f"{self.__class__.__name__}('{self._locale}')"
diff --git a/pendulum/locales/lt/__init__.py b/pendulum/locales/lt/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/lt/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/lt/custom.py b/pendulum/locales/lt/custom.py
deleted file mode 100644
index 6480c31..0000000
--- a/pendulum/locales/lt/custom.py
+++ /dev/null
@@ -1,118 +0,0 @@
-"""
-lt custom locale file.
-"""
-
-translations = {
- # Relative time
- "units_relative": {
- "year": {
- "future": {
- "other": "{0} metų",
- "one": "{0} metų",
- "few": "{0} metų",
- "many": "{0} metų",
- },
- "past": {
- "other": "{0} metų",
- "one": "{0} metus",
- "few": "{0} metus",
- "many": "{0} metų",
- },
- },
- "month": {
- "future": {
- "other": "{0} mėnesių",
- "one": "{0} mėnesio",
- "few": "{0} mėnesių",
- "many": "{0} mėnesio",
- },
- "past": {
- "other": "{0} mėnesių",
- "one": "{0} mėnesį",
- "few": "{0} mėnesius",
- "many": "{0} mėnesio",
- },
- },
- "week": {
- "future": {
- "other": "{0} savaičių",
- "one": "{0} savaitės",
- "few": "{0} savaičių",
- "many": "{0} savaitės",
- },
- "past": {
- "other": "{0} savaičių",
- "one": "{0} savaitę",
- "few": "{0} savaites",
- "many": "{0} savaitės",
- },
- },
- "day": {
- "future": {
- "other": "{0} dienų",
- "one": "{0} dienos",
- "few": "{0} dienų",
- "many": "{0} dienos",
- },
- "past": {
- "other": "{0} dienų",
- "one": "{0} dieną",
- "few": "{0} dienas",
- "many": "{0} dienos",
- },
- },
- "hour": {
- "future": {
- "other": "{0} valandų",
- "one": "{0} valandos",
- "few": "{0} valandų",
- "many": "{0} valandos",
- },
- "past": {
- "other": "{0} valandų",
- "one": "{0} valandą",
- "few": "{0} valandas",
- "many": "{0} valandos",
- },
- },
- "minute": {
- "future": {
- "other": "{0} minučių",
- "one": "{0} minutės",
- "few": "{0} minučių",
- "many": "{0} minutės",
- },
- "past": {
- "other": "{0} minučių",
- "one": "{0} minutę",
- "few": "{0} minutes",
- "many": "{0} minutės",
- },
- },
- "second": {
- "future": {
- "other": "{0} sekundžių",
- "one": "{0} sekundės",
- "few": "{0} sekundžių",
- "many": "{0} sekundės",
- },
- "past": {
- "other": "{0} sekundžių",
- "one": "{0} sekundę",
- "few": "{0} sekundes",
- "many": "{0} sekundės",
- },
- },
- },
- "after": "po {0}",
- "before": "{0} nuo dabar",
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "LLLL": "YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]",
- "LLL": "YYYY [m.] MMMM D [d.], HH:mm [val.]",
- "LL": "YYYY [m.] MMMM D [d.]",
- "L": "YYYY-MM-DD",
- },
-}
diff --git a/pendulum/locales/lt/locale.py b/pendulum/locales/lt/locale.py
deleted file mode 100644
index fb017ef..0000000
--- a/pendulum/locales/lt/locale.py
+++ /dev/null
@@ -1,255 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-lt locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "few"
- if (
- ((n % 10) == (n % 10) and ((n % 10) >= 2 and (n % 10) <= 9))
- and (not ((n % 100) == (n % 100) and ((n % 100) >= 11 and (n % 100) <= 19)))
- )
- else "many"
- if (not (0 == 0 and (0 == 0)))
- else "one"
- if (
- ((n % 10) == (n % 10) and ((n % 10) == 1))
- and (not ((n % 100) == (n % 100) and ((n % 100) >= 11 and (n % 100) <= 19)))
- )
- else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "sk",
- 1: "pr",
- 2: "an",
- 3: "tr",
- 4: "kt",
- 5: "pn",
- 6: "št",
- },
- "narrow": {0: "S", 1: "P", 2: "A", 3: "T", 4: "K", 5: "P", 6: "Š"},
- "short": {0: "Sk", 1: "Pr", 2: "An", 3: "Tr", 4: "Kt", 5: "Pn", 6: "Št"},
- "wide": {
- 0: "sekmadienis",
- 1: "pirmadienis",
- 2: "antradienis",
- 3: "trečiadienis",
- 4: "ketvirtadienis",
- 5: "penktadienis",
- 6: "šeštadienis",
- },
- },
- "months": {
- "abbreviated": {
- 1: "saus.",
- 2: "vas.",
- 3: "kov.",
- 4: "bal.",
- 5: "geg.",
- 6: "birž.",
- 7: "liep.",
- 8: "rugp.",
- 9: "rugs.",
- 10: "spal.",
- 11: "lapkr.",
- 12: "gruod.",
- },
- "narrow": {
- 1: "S",
- 2: "V",
- 3: "K",
- 4: "B",
- 5: "G",
- 6: "B",
- 7: "L",
- 8: "R",
- 9: "R",
- 10: "S",
- 11: "L",
- 12: "G",
- },
- "wide": {
- 1: "sausio",
- 2: "vasario",
- 3: "kovo",
- 4: "balandžio",
- 5: "gegužės",
- 6: "birželio",
- 7: "liepos",
- 8: "rugpjūčio",
- 9: "rugsėjo",
- 10: "spalio",
- 11: "lapkričio",
- 12: "gruodžio",
- },
- },
- "units": {
- "year": {
- "one": "{0} metai",
- "few": "{0} metai",
- "many": "{0} metų",
- "other": "{0} metų",
- },
- "month": {
- "one": "{0} mėnuo",
- "few": "{0} mėnesiai",
- "many": "{0} mėnesio",
- "other": "{0} mėnesių",
- },
- "week": {
- "one": "{0} savaitė",
- "few": "{0} savaitės",
- "many": "{0} savaitės",
- "other": "{0} savaičių",
- },
- "day": {
- "one": "{0} diena",
- "few": "{0} dienos",
- "many": "{0} dienos",
- "other": "{0} dienų",
- },
- "hour": {
- "one": "{0} valanda",
- "few": "{0} valandos",
- "many": "{0} valandos",
- "other": "{0} valandų",
- },
- "minute": {
- "one": "{0} minutė",
- "few": "{0} minutės",
- "many": "{0} minutės",
- "other": "{0} minučių",
- },
- "second": {
- "one": "{0} sekundė",
- "few": "{0} sekundės",
- "many": "{0} sekundės",
- "other": "{0} sekundžių",
- },
- "microsecond": {
- "one": "{0} mikrosekundė",
- "few": "{0} mikrosekundės",
- "many": "{0} mikrosekundės",
- "other": "{0} mikrosekundžių",
- },
- },
- "relative": {
- "year": {
- "future": {
- "other": "po {0} metų",
- "one": "po {0} metų",
- "few": "po {0} metų",
- "many": "po {0} metų",
- },
- "past": {
- "other": "prieš {0} metų",
- "one": "prieš {0} metus",
- "few": "prieš {0} metus",
- "many": "prieš {0} metų",
- },
- },
- "month": {
- "future": {
- "other": "po {0} mėnesių",
- "one": "po {0} mėnesio",
- "few": "po {0} mėnesių",
- "many": "po {0} mėnesio",
- },
- "past": {
- "other": "prieš {0} mėnesių",
- "one": "prieš {0} mėnesį",
- "few": "prieš {0} mėnesius",
- "many": "prieš {0} mėnesio",
- },
- },
- "week": {
- "future": {
- "other": "po {0} savaičių",
- "one": "po {0} savaitės",
- "few": "po {0} savaičių",
- "many": "po {0} savaitės",
- },
- "past": {
- "other": "prieš {0} savaičių",
- "one": "prieš {0} savaitę",
- "few": "prieš {0} savaites",
- "many": "prieš {0} savaitės",
- },
- },
- "day": {
- "future": {
- "other": "po {0} dienų",
- "one": "po {0} dienos",
- "few": "po {0} dienų",
- "many": "po {0} dienos",
- },
- "past": {
- "other": "prieš {0} dienų",
- "one": "prieš {0} dieną",
- "few": "prieš {0} dienas",
- "many": "prieš {0} dienos",
- },
- },
- "hour": {
- "future": {
- "other": "po {0} valandų",
- "one": "po {0} valandos",
- "few": "po {0} valandų",
- "many": "po {0} valandos",
- },
- "past": {
- "other": "prieš {0} valandų",
- "one": "prieš {0} valandą",
- "few": "prieš {0} valandas",
- "many": "prieš {0} valandos",
- },
- },
- "minute": {
- "future": {
- "other": "po {0} minučių",
- "one": "po {0} minutės",
- "few": "po {0} minučių",
- "many": "po {0} minutės",
- },
- "past": {
- "other": "prieš {0} minučių",
- "one": "prieš {0} minutę",
- "few": "prieš {0} minutes",
- "many": "prieš {0} minutės",
- },
- },
- "second": {
- "future": {
- "other": "po {0} sekundžių",
- "one": "po {0} sekundės",
- "few": "po {0} sekundžių",
- "many": "po {0} sekundės",
- },
- "past": {
- "other": "prieš {0} sekundžių",
- "one": "prieš {0} sekundę",
- "few": "prieš {0} sekundes",
- "many": "prieš {0} sekundės",
- },
- },
- },
- "day_periods": {
- "midnight": "vidurnaktis",
- "am": "priešpiet",
- "noon": "perpiet",
- "pm": "popiet",
- "morning1": "rytas",
- "afternoon1": "popietė",
- "evening1": "vakaras",
- "night1": "naktis",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/nb/__init__.py b/pendulum/locales/nb/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/nb/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/nb/custom.py b/pendulum/locales/nb/custom.py
deleted file mode 100644
index 4c7cd6a..0000000
--- a/pendulum/locales/nb/custom.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-nn custom locale file.
-"""
-
-translations = {
- # Relative time
- "after": "{0} etter",
- "before": "{0} før",
- # Ordinals
- "ordinal": {"one": ".", "two": ".", "few": ".", "other": "."},
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "LLLL": "dddd Do MMMM YYYY HH:mm",
- "LLL": "Do MMMM YYYY HH:mm",
- "LL": "Do MMMM YYYY",
- "L": "DD.MM.YYYY",
- },
-}
diff --git a/pendulum/locales/nb/locale.py b/pendulum/locales/nb/locale.py
deleted file mode 100644
index c8297a8..0000000
--- a/pendulum/locales/nb/locale.py
+++ /dev/null
@@ -1,150 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-nb locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one" if (n == n and (n == 1)) else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "søn.",
- 1: "man.",
- 2: "tir.",
- 3: "ons.",
- 4: "tor.",
- 5: "fre.",
- 6: "lør.",
- },
- "narrow": {0: "S", 1: "M", 2: "T", 3: "O", 4: "T", 5: "F", 6: "L"},
- "short": {
- 0: "sø.",
- 1: "ma.",
- 2: "ti.",
- 3: "on.",
- 4: "to.",
- 5: "fr.",
- 6: "lø.",
- },
- "wide": {
- 0: "søndag",
- 1: "mandag",
- 2: "tirsdag",
- 3: "onsdag",
- 4: "torsdag",
- 5: "fredag",
- 6: "lørdag",
- },
- },
- "months": {
- "abbreviated": {
- 1: "jan.",
- 2: "feb.",
- 3: "mar.",
- 4: "apr.",
- 5: "mai",
- 6: "jun.",
- 7: "jul.",
- 8: "aug.",
- 9: "sep.",
- 10: "okt.",
- 11: "nov.",
- 12: "des.",
- },
- "narrow": {
- 1: "J",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "J",
- 7: "J",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "januar",
- 2: "februar",
- 3: "mars",
- 4: "april",
- 5: "mai",
- 6: "juni",
- 7: "juli",
- 8: "august",
- 9: "september",
- 10: "oktober",
- 11: "november",
- 12: "desember",
- },
- },
- "units": {
- "year": {"one": "{0} år", "other": "{0} år"},
- "month": {"one": "{0} måned", "other": "{0} måneder"},
- "week": {"one": "{0} uke", "other": "{0} uker"},
- "day": {"one": "{0} dag", "other": "{0} dager"},
- "hour": {"one": "{0} time", "other": "{0} timer"},
- "minute": {"one": "{0} minutt", "other": "{0} minutter"},
- "second": {"one": "{0} sekund", "other": "{0} sekunder"},
- "microsecond": {"one": "{0} mikrosekund", "other": "{0} mikrosekunder"},
- },
- "relative": {
- "year": {
- "future": {"other": "om {0} år", "one": "om {0} år"},
- "past": {"other": "for {0} år siden", "one": "for {0} år siden"},
- },
- "month": {
- "future": {"other": "om {0} måneder", "one": "om {0} måned"},
- "past": {
- "other": "for {0} måneder siden",
- "one": "for {0} måned siden",
- },
- },
- "week": {
- "future": {"other": "om {0} uker", "one": "om {0} uke"},
- "past": {"other": "for {0} uker siden", "one": "for {0} uke siden"},
- },
- "day": {
- "future": {"other": "om {0} dager", "one": "om {0} dag"},
- "past": {"other": "for {0} dager siden", "one": "for {0} dag siden"},
- },
- "hour": {
- "future": {"other": "om {0} timer", "one": "om {0} time"},
- "past": {"other": "for {0} timer siden", "one": "for {0} time siden"},
- },
- "minute": {
- "future": {"other": "om {0} minutter", "one": "om {0} minutt"},
- "past": {
- "other": "for {0} minutter siden",
- "one": "for {0} minutt siden",
- },
- },
- "second": {
- "future": {"other": "om {0} sekunder", "one": "om {0} sekund"},
- "past": {
- "other": "for {0} sekunder siden",
- "one": "for {0} sekund siden",
- },
- },
- },
- "day_periods": {
- "midnight": "midnatt",
- "am": "a.m.",
- "pm": "p.m.",
- "morning1": "morgenen",
- "morning2": "formiddagen",
- "afternoon1": "ettermiddagen",
- "evening1": "kvelden",
- "night1": "natten",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/nl/__init__.py b/pendulum/locales/nl/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/nl/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/nl/custom.py b/pendulum/locales/nl/custom.py
deleted file mode 100644
index 2ca5a85..0000000
--- a/pendulum/locales/nl/custom.py
+++ /dev/null
@@ -1,23 +0,0 @@
-"""
-nl custom locale file.
-"""
-
-translations = {
- "units": {"few_second": "enkele seconden"},
- # Relative time
- "ago": "{} geleden",
- "from_now": "over {}",
- "after": "{0} later",
- "before": "{0} eerder",
- # Ordinals
- "ordinal": {"other": "e"},
- # Date formats
- "date_formats": {
- "L": "DD-MM-YYYY",
- "LL": "D MMMM YYYY",
- "LLL": "D MMMM YYYY HH:mm",
- "LLLL": "dddd D MMMM YYYY HH:mm",
- "LT": "HH:mm",
- "LTS": "HH:mm:ss",
- },
-}
diff --git a/pendulum/locales/nl/locale.py b/pendulum/locales/nl/locale.py
deleted file mode 100644
index cb1570d..0000000
--- a/pendulum/locales/nl/locale.py
+++ /dev/null
@@ -1,134 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-nl locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one"
- if ((n == n and (n == 1)) and (0 == 0 and (0 == 0)))
- else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "zo",
- 1: "ma",
- 2: "di",
- 3: "wo",
- 4: "do",
- 5: "vr",
- 6: "za",
- },
- "narrow": {0: "Z", 1: "M", 2: "D", 3: "W", 4: "D", 5: "V", 6: "Z"},
- "short": {0: "zo", 1: "ma", 2: "di", 3: "wo", 4: "do", 5: "vr", 6: "za"},
- "wide": {
- 0: "zondag",
- 1: "maandag",
- 2: "dinsdag",
- 3: "woensdag",
- 4: "donderdag",
- 5: "vrijdag",
- 6: "zaterdag",
- },
- },
- "months": {
- "abbreviated": {
- 1: "jan.",
- 2: "feb.",
- 3: "mrt.",
- 4: "apr.",
- 5: "mei",
- 6: "jun.",
- 7: "jul.",
- 8: "aug.",
- 9: "sep.",
- 10: "okt.",
- 11: "nov.",
- 12: "dec.",
- },
- "narrow": {
- 1: "J",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "J",
- 7: "J",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "januari",
- 2: "februari",
- 3: "maart",
- 4: "april",
- 5: "mei",
- 6: "juni",
- 7: "juli",
- 8: "augustus",
- 9: "september",
- 10: "oktober",
- 11: "november",
- 12: "december",
- },
- },
- "units": {
- "year": {"one": "{0} jaar", "other": "{0} jaar"},
- "month": {"one": "{0} maand", "other": "{0} maanden"},
- "week": {"one": "{0} week", "other": "{0} weken"},
- "day": {"one": "{0} dag", "other": "{0} dagen"},
- "hour": {"one": "{0} uur", "other": "{0} uur"},
- "minute": {"one": "{0} minuut", "other": "{0} minuten"},
- "second": {"one": "{0} seconde", "other": "{0} seconden"},
- "microsecond": {"one": "{0} microseconde", "other": "{0} microseconden"},
- },
- "relative": {
- "year": {
- "future": {"other": "over {0} jaar", "one": "over {0} jaar"},
- "past": {"other": "{0} jaar geleden", "one": "{0} jaar geleden"},
- },
- "month": {
- "future": {"other": "over {0} maanden", "one": "over {0} maand"},
- "past": {"other": "{0} maanden geleden", "one": "{0} maand geleden"},
- },
- "week": {
- "future": {"other": "over {0} weken", "one": "over {0} week"},
- "past": {"other": "{0} weken geleden", "one": "{0} week geleden"},
- },
- "day": {
- "future": {"other": "over {0} dagen", "one": "over {0} dag"},
- "past": {"other": "{0} dagen geleden", "one": "{0} dag geleden"},
- },
- "hour": {
- "future": {"other": "over {0} uur", "one": "over {0} uur"},
- "past": {"other": "{0} uur geleden", "one": "{0} uur geleden"},
- },
- "minute": {
- "future": {"other": "over {0} minuten", "one": "over {0} minuut"},
- "past": {"other": "{0} minuten geleden", "one": "{0} minuut geleden"},
- },
- "second": {
- "future": {"other": "over {0} seconden", "one": "over {0} seconde"},
- "past": {"other": "{0} seconden geleden", "one": "{0} seconde geleden"},
- },
- },
- "day_periods": {
- "midnight": "middernacht",
- "am": "a.m.",
- "pm": "p.m.",
- "morning1": "‘s ochtends",
- "afternoon1": "‘s middags",
- "evening1": "‘s avonds",
- "night1": "‘s nachts",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/nn/__init__.py b/pendulum/locales/nn/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/nn/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/nn/custom.py b/pendulum/locales/nn/custom.py
deleted file mode 100644
index 4c7cd6a..0000000
--- a/pendulum/locales/nn/custom.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-nn custom locale file.
-"""
-
-translations = {
- # Relative time
- "after": "{0} etter",
- "before": "{0} før",
- # Ordinals
- "ordinal": {"one": ".", "two": ".", "few": ".", "other": "."},
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "LLLL": "dddd Do MMMM YYYY HH:mm",
- "LLL": "Do MMMM YYYY HH:mm",
- "LL": "Do MMMM YYYY",
- "L": "DD.MM.YYYY",
- },
-}
diff --git a/pendulum/locales/nn/locale.py b/pendulum/locales/nn/locale.py
deleted file mode 100644
index eb46e1d..0000000
--- a/pendulum/locales/nn/locale.py
+++ /dev/null
@@ -1,141 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-nn locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one" if (n == n and (n == 1)) else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "søn.",
- 1: "mån.",
- 2: "tys.",
- 3: "ons.",
- 4: "tor.",
- 5: "fre.",
- 6: "lau.",
- },
- "narrow": {0: "S", 1: "M", 2: "T", 3: "O", 4: "T", 5: "F", 6: "L"},
- "short": {
- 0: "sø.",
- 1: "må.",
- 2: "ty.",
- 3: "on.",
- 4: "to.",
- 5: "fr.",
- 6: "la.",
- },
- "wide": {
- 0: "søndag",
- 1: "måndag",
- 2: "tysdag",
- 3: "onsdag",
- 4: "torsdag",
- 5: "fredag",
- 6: "laurdag",
- },
- },
- "months": {
- "abbreviated": {
- 1: "jan.",
- 2: "feb.",
- 3: "mars",
- 4: "apr.",
- 5: "mai",
- 6: "juni",
- 7: "juli",
- 8: "aug.",
- 9: "sep.",
- 10: "okt.",
- 11: "nov.",
- 12: "des.",
- },
- "narrow": {
- 1: "J",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "J",
- 7: "J",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "januar",
- 2: "februar",
- 3: "mars",
- 4: "april",
- 5: "mai",
- 6: "juni",
- 7: "juli",
- 8: "august",
- 9: "september",
- 10: "oktober",
- 11: "november",
- 12: "desember",
- },
- },
- "units": {
- "year": {"one": "{0} år", "other": "{0} år"},
- "month": {"one": "{0} månad", "other": "{0} månadar"},
- "week": {"one": "{0} veke", "other": "{0} veker"},
- "day": {"one": "{0} dag", "other": "{0} dagar"},
- "hour": {"one": "{0} time", "other": "{0} timar"},
- "minute": {"one": "{0} minutt", "other": "{0} minutt"},
- "second": {"one": "{0} sekund", "other": "{0} sekund"},
- "microsecond": {"one": "{0} mikrosekund", "other": "{0} mikrosekund"},
- },
- "relative": {
- "year": {
- "future": {"other": "om {0} år", "one": "om {0} år"},
- "past": {"other": "for {0} år sidan", "one": "for {0} år sidan"},
- },
- "month": {
- "future": {"other": "om {0} månadar", "one": "om {0} månad"},
- "past": {
- "other": "for {0} månadar sidan",
- "one": "for {0} månad sidan",
- },
- },
- "week": {
- "future": {"other": "om {0} veker", "one": "om {0} veke"},
- "past": {"other": "for {0} veker sidan", "one": "for {0} veke sidan"},
- },
- "day": {
- "future": {"other": "om {0} dagar", "one": "om {0} dag"},
- "past": {"other": "for {0} dagar sidan", "one": "for {0} dag sidan"},
- },
- "hour": {
- "future": {"other": "om {0} timar", "one": "om {0} time"},
- "past": {"other": "for {0} timar sidan", "one": "for {0} time sidan"},
- },
- "minute": {
- "future": {"other": "om {0} minutt", "one": "om {0} minutt"},
- "past": {
- "other": "for {0} minutt sidan",
- "one": "for {0} minutt sidan",
- },
- },
- "second": {
- "future": {"other": "om {0} sekund", "one": "om {0} sekund"},
- "past": {
- "other": "for {0} sekund sidan",
- "one": "for {0} sekund sidan",
- },
- },
- },
- "day_periods": {"am": "formiddag", "pm": "ettermiddag"},
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/pl/__init__.py b/pendulum/locales/pl/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/pl/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/pl/custom.py b/pendulum/locales/pl/custom.py
deleted file mode 100644
index 9741b74..0000000
--- a/pendulum/locales/pl/custom.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""
-pl custom locale file.
-"""
-
-translations = {
- "units": {"few_second": "kilka sekund"},
- # Relative time
- "ago": "{} temu",
- "from_now": "za {}",
- "after": "{0} po",
- "before": "{0} przed",
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "L": "DD.MM.YYYY",
- "LL": "D MMMM YYYY",
- "LLL": "D MMMM YYYY HH:mm",
- "LLLL": "dddd, D MMMM YYYY HH:mm",
- },
-}
diff --git a/pendulum/locales/pl/locale.py b/pendulum/locales/pl/locale.py
deleted file mode 100644
index bf6af10..0000000
--- a/pendulum/locales/pl/locale.py
+++ /dev/null
@@ -1,279 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-pl locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "few"
- if (
- (
- (0 == 0 and (0 == 0))
- and ((n % 10) == (n % 10) and ((n % 10) >= 2 and (n % 10) <= 4))
- )
- and (not ((n % 100) == (n % 100) and ((n % 100) >= 12 and (n % 100) <= 14)))
- )
- else "many"
- if (
- (
- (
- ((0 == 0 and (0 == 0)) and (not (n == n and (n == 1))))
- and ((n % 10) == (n % 10) and ((n % 10) >= 0 and (n % 10) <= 1))
- )
- or (
- (0 == 0 and (0 == 0))
- and ((n % 10) == (n % 10) and ((n % 10) >= 5 and (n % 10) <= 9))
- )
- )
- or (
- (0 == 0 and (0 == 0))
- and ((n % 100) == (n % 100) and ((n % 100) >= 12 and (n % 100) <= 14))
- )
- )
- else "one"
- if ((n == n and (n == 1)) and (0 == 0 and (0 == 0)))
- else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "niedz.",
- 1: "pon.",
- 2: "wt.",
- 3: "śr.",
- 4: "czw.",
- 5: "pt.",
- 6: "sob.",
- },
- "narrow": {0: "n", 1: "p", 2: "w", 3: "ś", 4: "c", 5: "p", 6: "s"},
- "short": {
- 0: "nie",
- 1: "pon",
- 2: "wto",
- 3: "śro",
- 4: "czw",
- 5: "pią",
- 6: "sob",
- },
- "wide": {
- 0: "niedziela",
- 1: "poniedziałek",
- 2: "wtorek",
- 3: "środa",
- 4: "czwartek",
- 5: "piątek",
- 6: "sobota",
- },
- },
- "months": {
- "abbreviated": {
- 1: "sty",
- 2: "lut",
- 3: "mar",
- 4: "kwi",
- 5: "maj",
- 6: "cze",
- 7: "lip",
- 8: "sie",
- 9: "wrz",
- 10: "paź",
- 11: "lis",
- 12: "gru",
- },
- "narrow": {
- 1: "s",
- 2: "l",
- 3: "m",
- 4: "k",
- 5: "m",
- 6: "c",
- 7: "l",
- 8: "s",
- 9: "w",
- 10: "p",
- 11: "l",
- 12: "g",
- },
- "wide": {
- 1: "stycznia",
- 2: "lutego",
- 3: "marca",
- 4: "kwietnia",
- 5: "maja",
- 6: "czerwca",
- 7: "lipca",
- 8: "sierpnia",
- 9: "września",
- 10: "października",
- 11: "listopada",
- 12: "grudnia",
- },
- },
- "units": {
- "year": {
- "one": "{0} rok",
- "few": "{0} lata",
- "many": "{0} lat",
- "other": "{0} roku",
- },
- "month": {
- "one": "{0} miesiąc",
- "few": "{0} miesiące",
- "many": "{0} miesięcy",
- "other": "{0} miesiąca",
- },
- "week": {
- "one": "{0} tydzień",
- "few": "{0} tygodnie",
- "many": "{0} tygodni",
- "other": "{0} tygodnia",
- },
- "day": {
- "one": "{0} dzień",
- "few": "{0} dni",
- "many": "{0} dni",
- "other": "{0} dnia",
- },
- "hour": {
- "one": "{0} godzina",
- "few": "{0} godziny",
- "many": "{0} godzin",
- "other": "{0} godziny",
- },
- "minute": {
- "one": "{0} minuta",
- "few": "{0} minuty",
- "many": "{0} minut",
- "other": "{0} minuty",
- },
- "second": {
- "one": "{0} sekunda",
- "few": "{0} sekundy",
- "many": "{0} sekund",
- "other": "{0} sekundy",
- },
- "microsecond": {
- "one": "{0} mikrosekunda",
- "few": "{0} mikrosekundy",
- "many": "{0} mikrosekund",
- "other": "{0} mikrosekundy",
- },
- },
- "relative": {
- "year": {
- "future": {
- "other": "za {0} roku",
- "one": "za {0} rok",
- "few": "za {0} lata",
- "many": "za {0} lat",
- },
- "past": {
- "other": "{0} roku temu",
- "one": "{0} rok temu",
- "few": "{0} lata temu",
- "many": "{0} lat temu",
- },
- },
- "month": {
- "future": {
- "other": "za {0} miesiąca",
- "one": "za {0} miesiąc",
- "few": "za {0} miesiące",
- "many": "za {0} miesięcy",
- },
- "past": {
- "other": "{0} miesiąca temu",
- "one": "{0} miesiąc temu",
- "few": "{0} miesiące temu",
- "many": "{0} miesięcy temu",
- },
- },
- "week": {
- "future": {
- "other": "za {0} tygodnia",
- "one": "za {0} tydzień",
- "few": "za {0} tygodnie",
- "many": "za {0} tygodni",
- },
- "past": {
- "other": "{0} tygodnia temu",
- "one": "{0} tydzień temu",
- "few": "{0} tygodnie temu",
- "many": "{0} tygodni temu",
- },
- },
- "day": {
- "future": {
- "other": "za {0} dnia",
- "one": "za {0} dzień",
- "few": "za {0} dni",
- "many": "za {0} dni",
- },
- "past": {
- "other": "{0} dnia temu",
- "one": "{0} dzień temu",
- "few": "{0} dni temu",
- "many": "{0} dni temu",
- },
- },
- "hour": {
- "future": {
- "other": "za {0} godziny",
- "one": "za {0} godzinę",
- "few": "za {0} godziny",
- "many": "za {0} godzin",
- },
- "past": {
- "other": "{0} godziny temu",
- "one": "{0} godzinę temu",
- "few": "{0} godziny temu",
- "many": "{0} godzin temu",
- },
- },
- "minute": {
- "future": {
- "other": "za {0} minuty",
- "one": "za {0} minutę",
- "few": "za {0} minuty",
- "many": "za {0} minut",
- },
- "past": {
- "other": "{0} minuty temu",
- "one": "{0} minutę temu",
- "few": "{0} minuty temu",
- "many": "{0} minut temu",
- },
- },
- "second": {
- "future": {
- "other": "za {0} sekundy",
- "one": "za {0} sekundę",
- "few": "za {0} sekundy",
- "many": "za {0} sekund",
- },
- "past": {
- "other": "{0} sekundy temu",
- "one": "{0} sekundę temu",
- "few": "{0} sekundy temu",
- "many": "{0} sekund temu",
- },
- },
- },
- "day_periods": {
- "midnight": "o północy",
- "am": "AM",
- "noon": "w południe",
- "pm": "PM",
- "morning1": "rano",
- "morning2": "przed południem",
- "afternoon1": "po południu",
- "evening1": "wieczorem",
- "night1": "w nocy",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/pt_br/__init__.py b/pendulum/locales/pt_br/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/pt_br/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/pt_br/custom.py b/pendulum/locales/pt_br/custom.py
deleted file mode 100644
index 12aced7..0000000
--- a/pendulum/locales/pt_br/custom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-pt-br custom locale file.
-"""
-
-translations = {
- # Relative time
- "after": "após {0}",
- "before": "{0} atrás",
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "LLLL": "dddd, D [de] MMMM [de] YYYY [às] HH:mm",
- "LLL": "D [de] MMMM [de] YYYY [às] HH:mm",
- "LL": "D [de] MMMM [de] YYYY",
- "L": "DD/MM/YYYY",
- },
-}
diff --git a/pendulum/locales/pt_br/locale.py b/pendulum/locales/pt_br/locale.py
deleted file mode 100644
index 742c41f..0000000
--- a/pendulum/locales/pt_br/locale.py
+++ /dev/null
@@ -1,143 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-pt_br locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one"
- if ((n == n and (n >= 0 and n <= 2)) and (not (n == n and (n == 2))))
- else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "dom",
- 1: "seg",
- 2: "ter",
- 3: "qua",
- 4: "qui",
- 5: "sex",
- 6: "sáb",
- },
- "narrow": {0: "D", 1: "S", 2: "T", 3: "Q", 4: "Q", 5: "S", 6: "S"},
- "short": {
- 0: "dom",
- 1: "seg",
- 2: "ter",
- 3: "qua",
- 4: "qui",
- 5: "sex",
- 6: "sáb",
- },
- "wide": {
- 0: "domingo",
- 1: "segunda-feira",
- 2: "terça-feira",
- 3: "quarta-feira",
- 4: "quinta-feira",
- 5: "sexta-feira",
- 6: "sábado",
- },
- },
- "months": {
- "abbreviated": {
- 1: "jan",
- 2: "fev",
- 3: "mar",
- 4: "abr",
- 5: "mai",
- 6: "jun",
- 7: "jul",
- 8: "ago",
- 9: "set",
- 10: "out",
- 11: "nov",
- 12: "dez",
- },
- "narrow": {
- 1: "J",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "J",
- 7: "J",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "janeiro",
- 2: "fevereiro",
- 3: "março",
- 4: "abril",
- 5: "maio",
- 6: "junho",
- 7: "julho",
- 8: "agosto",
- 9: "setembro",
- 10: "outubro",
- 11: "novembro",
- 12: "dezembro",
- },
- },
- "units": {
- "year": {"one": "{0} ano", "other": "{0} anos"},
- "month": {"one": "{0} mês", "other": "{0} meses"},
- "week": {"one": "{0} semana", "other": "{0} semanas"},
- "day": {"one": "{0} dia", "other": "{0} dias"},
- "hour": {"one": "{0} hora", "other": "{0} horas"},
- "minute": {"one": "{0} minuto", "other": "{0} minutos"},
- "second": {"one": "{0} segundo", "other": "{0} segundos"},
- "microsecond": {"one": "{0} microssegundo", "other": "{0} microssegundos"},
- },
- "relative": {
- "year": {
- "future": {"other": "em {0} anos", "one": "em {0} ano"},
- "past": {"other": "há {0} anos", "one": "há {0} ano"},
- },
- "month": {
- "future": {"other": "em {0} meses", "one": "em {0} mês"},
- "past": {"other": "há {0} meses", "one": "há {0} mês"},
- },
- "week": {
- "future": {"other": "em {0} semanas", "one": "em {0} semana"},
- "past": {"other": "há {0} semanas", "one": "há {0} semana"},
- },
- "day": {
- "future": {"other": "em {0} dias", "one": "em {0} dia"},
- "past": {"other": "há {0} dias", "one": "há {0} dia"},
- },
- "hour": {
- "future": {"other": "em {0} horas", "one": "em {0} hora"},
- "past": {"other": "há {0} horas", "one": "há {0} hora"},
- },
- "minute": {
- "future": {"other": "em {0} minutos", "one": "em {0} minuto"},
- "past": {"other": "há {0} minutos", "one": "há {0} minuto"},
- },
- "second": {
- "future": {"other": "em {0} segundos", "one": "em {0} segundo"},
- "past": {"other": "há {0} segundos", "one": "há {0} segundo"},
- },
- },
- "day_periods": {
- "midnight": "meia-noite",
- "am": "AM",
- "noon": "meio-dia",
- "pm": "PM",
- "morning1": "da manhã",
- "afternoon1": "da tarde",
- "evening1": "da noite",
- "night1": "da madrugada",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/ru/__init__.py b/pendulum/locales/ru/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/ru/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/ru/custom.py b/pendulum/locales/ru/custom.py
deleted file mode 100644
index b4c89bb..0000000
--- a/pendulum/locales/ru/custom.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-ru custom locale file.
-"""
-
-translations = {
- # Relative time
- "ago": "{} назад",
- "from_now": "через {}",
- "after": "{0} после",
- "before": "{0} до",
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "L": "DD.MM.YYYY",
- "LL": "D MMMM YYYY г.",
- "LLL": "D MMMM YYYY г., HH:mm",
- "LLLL": "dddd, D MMMM YYYY г., HH:mm",
- },
-}
diff --git a/pendulum/locales/ru/locale.py b/pendulum/locales/ru/locale.py
deleted file mode 100644
index 3736e0b..0000000
--- a/pendulum/locales/ru/locale.py
+++ /dev/null
@@ -1,270 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-ru locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "few"
- if (
- (
- (0 == 0 and (0 == 0))
- and ((n % 10) == (n % 10) and ((n % 10) >= 2 and (n % 10) <= 4))
- )
- and (not ((n % 100) == (n % 100) and ((n % 100) >= 12 and (n % 100) <= 14)))
- )
- else "many"
- if (
- (
- ((0 == 0 and (0 == 0)) and ((n % 10) == (n % 10) and ((n % 10) == 0)))
- or (
- (0 == 0 and (0 == 0))
- and ((n % 10) == (n % 10) and ((n % 10) >= 5 and (n % 10) <= 9))
- )
- )
- or (
- (0 == 0 and (0 == 0))
- and ((n % 100) == (n % 100) and ((n % 100) >= 11 and (n % 100) <= 14))
- )
- )
- else "one"
- if (
- ((0 == 0 and (0 == 0)) and ((n % 10) == (n % 10) and ((n % 10) == 1)))
- and (not ((n % 100) == (n % 100) and ((n % 100) == 11)))
- )
- else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "вс",
- 1: "пн",
- 2: "вт",
- 3: "ср",
- 4: "чт",
- 5: "пт",
- 6: "сб",
- },
- "narrow": {0: "вс", 1: "пн", 2: "вт", 3: "ср", 4: "чт", 5: "пт", 6: "сб"},
- "short": {0: "вс", 1: "пн", 2: "вт", 3: "ср", 4: "чт", 5: "пт", 6: "сб"},
- "wide": {
- 0: "воскресенье",
- 1: "понедельник",
- 2: "вторник",
- 3: "среда",
- 4: "четверг",
- 5: "пятница",
- 6: "суббота",
- },
- },
- "months": {
- "abbreviated": {
- 1: "янв.",
- 2: "февр.",
- 3: "мар.",
- 4: "апр.",
- 5: "мая",
- 6: "июн.",
- 7: "июл.",
- 8: "авг.",
- 9: "сент.",
- 10: "окт.",
- 11: "нояб.",
- 12: "дек.",
- },
- "narrow": {
- 1: "Я",
- 2: "Ф",
- 3: "М",
- 4: "А",
- 5: "М",
- 6: "И",
- 7: "И",
- 8: "А",
- 9: "С",
- 10: "О",
- 11: "Н",
- 12: "Д",
- },
- "wide": {
- 1: "января",
- 2: "февраля",
- 3: "марта",
- 4: "апреля",
- 5: "мая",
- 6: "июня",
- 7: "июля",
- 8: "августа",
- 9: "сентября",
- 10: "октября",
- 11: "ноября",
- 12: "декабря",
- },
- },
- "units": {
- "year": {
- "one": "{0} год",
- "few": "{0} года",
- "many": "{0} лет",
- "other": "{0} года",
- },
- "month": {
- "one": "{0} месяц",
- "few": "{0} месяца",
- "many": "{0} месяцев",
- "other": "{0} месяца",
- },
- "week": {
- "one": "{0} неделя",
- "few": "{0} недели",
- "many": "{0} недель",
- "other": "{0} недели",
- },
- "day": {
- "one": "{0} день",
- "few": "{0} дня",
- "many": "{0} дней",
- "other": "{0} дня",
- },
- "hour": {
- "one": "{0} час",
- "few": "{0} часа",
- "many": "{0} часов",
- "other": "{0} часа",
- },
- "minute": {
- "one": "{0} минута",
- "few": "{0} минуты",
- "many": "{0} минут",
- "other": "{0} минуты",
- },
- "second": {
- "one": "{0} секунда",
- "few": "{0} секунды",
- "many": "{0} секунд",
- "other": "{0} секунды",
- },
- "microsecond": {
- "one": "{0} микросекунда",
- "few": "{0} микросекунды",
- "many": "{0} микросекунд",
- "other": "{0} микросекунды",
- },
- },
- "relative": {
- "year": {
- "future": {
- "other": "через {0} года",
- "one": "через {0} год",
- "few": "через {0} года",
- "many": "через {0} лет",
- },
- "past": {
- "other": "{0} года назад",
- "one": "{0} год назад",
- "few": "{0} года назад",
- "many": "{0} лет назад",
- },
- },
- "month": {
- "future": {
- "other": "через {0} месяца",
- "one": "через {0} месяц",
- "few": "через {0} месяца",
- "many": "через {0} месяцев",
- },
- "past": {
- "other": "{0} месяца назад",
- "one": "{0} месяц назад",
- "few": "{0} месяца назад",
- "many": "{0} месяцев назад",
- },
- },
- "week": {
- "future": {
- "other": "через {0} недели",
- "one": "через {0} неделю",
- "few": "через {0} недели",
- "many": "через {0} недель",
- },
- "past": {
- "other": "{0} недели назад",
- "one": "{0} неделю назад",
- "few": "{0} недели назад",
- "many": "{0} недель назад",
- },
- },
- "day": {
- "future": {
- "other": "через {0} дня",
- "one": "через {0} день",
- "few": "через {0} дня",
- "many": "через {0} дней",
- },
- "past": {
- "other": "{0} дня назад",
- "one": "{0} день назад",
- "few": "{0} дня назад",
- "many": "{0} дней назад",
- },
- },
- "hour": {
- "future": {
- "other": "через {0} часа",
- "one": "через {0} час",
- "few": "через {0} часа",
- "many": "через {0} часов",
- },
- "past": {
- "other": "{0} часа назад",
- "one": "{0} час назад",
- "few": "{0} часа назад",
- "many": "{0} часов назад",
- },
- },
- "minute": {
- "future": {
- "other": "через {0} минуты",
- "one": "через {0} минуту",
- "few": "через {0} минуты",
- "many": "через {0} минут",
- },
- "past": {
- "other": "{0} минуты назад",
- "one": "{0} минуту назад",
- "few": "{0} минуты назад",
- "many": "{0} минут назад",
- },
- },
- "second": {
- "future": {
- "other": "через {0} секунды",
- "one": "через {0} секунду",
- "few": "через {0} секунды",
- "many": "через {0} секунд",
- },
- "past": {
- "other": "{0} секунды назад",
- "one": "{0} секунду назад",
- "few": "{0} секунды назад",
- "many": "{0} секунд назад",
- },
- },
- },
- "day_periods": {
- "midnight": "полночь",
- "am": "AM",
- "noon": "полдень",
- "pm": "PM",
- "morning1": "утра",
- "afternoon1": "дня",
- "evening1": "вечера",
- "night1": "ночи",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/sk/__init__.py b/pendulum/locales/sk/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/sk/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/sk/custom.py b/pendulum/locales/sk/custom.py
deleted file mode 100644
index 71afb15..0000000
--- a/pendulum/locales/sk/custom.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-sk custom locale file.
-"""
-
-translations = {
- # Relative time
- "ago": "pred {}",
- "from_now": "o {}",
- "after": "{0} po",
- "before": "{0} pred",
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "LLLL": "dddd, D. MMMM YYYY HH:mm",
- "LLL": "D. MMMM YYYY HH:mm",
- "LL": "D. MMMM YYYY",
- "L": "DD.MM.YYYY",
- },
-}
diff --git a/pendulum/locales/sk/locale.py b/pendulum/locales/sk/locale.py
deleted file mode 100644
index 8d3459f..0000000
--- a/pendulum/locales/sk/locale.py
+++ /dev/null
@@ -1,266 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-sk locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "few"
- if ((n == n and (n >= 2 and n <= 4)) and (0 == 0 and (0 == 0)))
- else "many"
- if (not (0 == 0 and (0 == 0)))
- else "one"
- if ((n == n and (n == 1)) and (0 == 0 and (0 == 0)))
- else "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "ne",
- 1: "po",
- 2: "ut",
- 3: "st",
- 4: "št",
- 5: "pi",
- 6: "so",
- },
- "narrow": {
- 0: "n",
- 1: "p",
- 2: "u",
- 3: "s",
- 4: "š",
- 5: "p",
- 6: "s",
- },
- "short": {
- 0: "ne",
- 1: "po",
- 2: "ut",
- 3: "st",
- 4: "št",
- 5: "pi",
- 6: "so",
- },
- "wide": {
- 0: "nedeľa",
- 1: "pondelok",
- 2: "utorok",
- 3: "streda",
- 4: "štvrtok",
- 5: "piatok",
- 6: "sobota",
- },
- },
- "months": {
- "abbreviated": {
- 1: "jan",
- 2: "feb",
- 3: "mar",
- 4: "apr",
- 5: "máj",
- 6: "jún",
- 7: "júl",
- 8: "aug",
- 9: "sep",
- 10: "okt",
- 11: "nov",
- 12: "dec",
- },
- "narrow": {
- 1: "j",
- 2: "f",
- 3: "m",
- 4: "a",
- 5: "m",
- 6: "j",
- 7: "j",
- 8: "a",
- 9: "s",
- 10: "o",
- 11: "n",
- 12: "d",
- },
- "wide": {
- 1: "januára",
- 2: "februára",
- 3: "marca",
- 4: "apríla",
- 5: "mája",
- 6: "júna",
- 7: "júla",
- 8: "augusta",
- 9: "septembra",
- 10: "októbra",
- 11: "novembra",
- 12: "decembra",
- },
- },
- "units": {
- "year": {
- "one": "{0} rok",
- "few": "{0} roky",
- "many": "{0} roka",
- "other": "{0} rokov",
- },
- "month": {
- "one": "{0} mesiac",
- "few": "{0} mesiace",
- "many": "{0} mesiaca",
- "other": "{0} mesiacov",
- },
- "week": {
- "one": "{0} týždeň",
- "few": "{0} týždne",
- "many": "{0} týždňa",
- "other": "{0} týždňov",
- },
- "day": {
- "one": "{0} deň",
- "few": "{0} dni",
- "many": "{0} dňa",
- "other": "{0} dní",
- },
- "hour": {
- "one": "{0} hodina",
- "few": "{0} hodiny",
- "many": "{0} hodiny",
- "other": "{0} hodín",
- },
- "minute": {
- "one": "{0} minúta",
- "few": "{0} minúty",
- "many": "{0} minúty",
- "other": "{0} minút",
- },
- "second": {
- "one": "{0} sekunda",
- "few": "{0} sekundy",
- "many": "{0} sekundy",
- "other": "{0} sekúnd",
- },
- "microsecond": {
- "one": "{0} mikrosekunda",
- "few": "{0} mikrosekundy",
- "many": "{0} mikrosekundy",
- "other": "{0} mikrosekúnd",
- },
- },
- "relative": {
- "year": {
- "future": {
- "other": "o {0} rokov",
- "one": "o {0} rok",
- "few": "o {0} roky",
- "many": "o {0} roka",
- },
- "past": {
- "other": "pred {0} rokmi",
- "one": "pred {0} rokom",
- "few": "pred {0} rokmi",
- "many": "pred {0} roka",
- },
- },
- "month": {
- "future": {
- "other": "o {0} mesiacov",
- "one": "o {0} mesiac",
- "few": "o {0} mesiace",
- "many": "o {0} mesiaca",
- },
- "past": {
- "other": "pred {0} mesiacmi",
- "one": "pred {0} mesiacom",
- "few": "pred {0} mesiacmi",
- "many": "pred {0} mesiaca",
- },
- },
- "week": {
- "future": {
- "other": "o {0} týždňov",
- "one": "o {0} týždeň",
- "few": "o {0} týždne",
- "many": "o {0} týždňa",
- },
- "past": {
- "other": "pred {0} týždňami",
- "one": "pred {0} týždňom",
- "few": "pred {0} týždňami",
- "many": "pred {0} týždňa",
- },
- },
- "day": {
- "future": {
- "other": "o {0} dní",
- "one": "o {0} deň",
- "few": "o {0} dni",
- "many": "o {0} dňa",
- },
- "past": {
- "other": "pred {0} dňami",
- "one": "pred {0} dňom",
- "few": "pred {0} dňami",
- "many": "pred {0} dňa",
- },
- },
- "hour": {
- "future": {
- "other": "o {0} hodín",
- "one": "o {0} hodinu",
- "few": "o {0} hodiny",
- "many": "o {0} hodiny",
- },
- "past": {
- "other": "pred {0} hodinami",
- "one": "pred {0} hodinou",
- "few": "pred {0} hodinami",
- "many": "pred {0} hodinou",
- },
- },
- "minute": {
- "future": {
- "other": "o {0} minút",
- "one": "o {0} minútu",
- "few": "o {0} minúty",
- "many": "o {0} minúty",
- },
- "past": {
- "other": "pred {0} minútami",
- "one": "pred {0} minútou",
- "few": "pred {0} minútami",
- "many": "pred {0} minúty",
- },
- },
- "second": {
- "future": {
- "other": "o {0} sekúnd",
- "one": "o {0} sekundu",
- "few": "o {0} sekundy",
- "many": "o {0} sekundy",
- },
- "past": {
- "other": "pred {0} sekundami",
- "one": "pred {0} sekundou",
- "few": "pred {0} sekundami",
- "many": "pred {0} sekundy",
- },
- },
- },
- "day_periods": {
- "midnight": "o polnoci",
- "am": "AM",
- "noon": "napoludnie",
- "pm": "PM",
- "morning1": "ráno",
- "morning2": "dopoludnia",
- "afternoon1": "popoludní",
- "evening1": "večer",
- "night1": "v noci",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/sv/__init__.py b/pendulum/locales/sv/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/sv/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/sv/custom.py b/pendulum/locales/sv/custom.py
deleted file mode 100644
index 7158f4b..0000000
--- a/pendulum/locales/sv/custom.py
+++ /dev/null
@@ -1,20 +0,0 @@
-"""
-sv custom locale file.
-"""
-
-translations = {
- # Relative time
- "ago": "{} sedan",
- "from_now": "från nu {}",
- "after": "{0} efter",
- "before": "{0} innan",
- # Date formats
- "date_formats": {
- "LTS": "HH:mm:ss",
- "LT": "HH:mm",
- "L": "YYYY-MM-DD",
- "LL": "D MMMM YYYY",
- "LLL": "D MMMM YYYY, HH:mm",
- "LLLL": "dddd, D MMMM YYYY, HH:mm",
- },
-}
diff --git a/pendulum/locales/sv/locale.py b/pendulum/locales/sv/locale.py
deleted file mode 100644
index 5b74a6e..0000000
--- a/pendulum/locales/sv/locale.py
+++ /dev/null
@@ -1,222 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-sv locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "one"
- if ((n == n and (n == 1)) and (0 == 0 and (0 == 0)))
- else "other",
- "ordinal": lambda n: "one"
- if (
- ((n % 10) == (n % 10) and (((n % 10) == 1) or ((n % 10) == 2)))
- and (not ((n % 100) == (n % 100) and (((n % 100) == 11) or ((n % 100) == 12))))
- )
- else "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "sön",
- 1: "mån",
- 2: "tis",
- 3: "ons",
- 4: "tors",
- 5: "fre",
- 6: "lör",
- },
- "narrow": {
- 0: "S",
- 1: "M",
- 2: "T",
- 3: "O",
- 4: "T",
- 5: "F",
- 6: "L",
- },
- "short": {
- 0: "sö",
- 1: "må",
- 2: "ti",
- 3: "on",
- 4: "to",
- 5: "fr",
- 6: "lö",
- },
- "wide": {
- 0: "söndag",
- 1: "måndag",
- 2: "tisdag",
- 3: "onsdag",
- 4: "torsdag",
- 5: "fredag",
- 6: "lördag",
- },
- },
- "months": {
- "abbreviated": {
- 1: "jan.",
- 2: "feb.",
- 3: "mars",
- 4: "apr.",
- 5: "maj",
- 6: "juni",
- 7: "juli",
- 8: "aug.",
- 9: "sep.",
- 10: "okt.",
- 11: "nov.",
- 12: "dec.",
- },
- "narrow": {
- 1: "J",
- 2: "F",
- 3: "M",
- 4: "A",
- 5: "M",
- 6: "J",
- 7: "J",
- 8: "A",
- 9: "S",
- 10: "O",
- 11: "N",
- 12: "D",
- },
- "wide": {
- 1: "januari",
- 2: "februari",
- 3: "mars",
- 4: "april",
- 5: "maj",
- 6: "juni",
- 7: "juli",
- 8: "augusti",
- 9: "september",
- 10: "oktober",
- 11: "november",
- 12: "december",
- },
- },
- "units": {
- "year": {
- "one": "{0} år",
- "other": "{0} år",
- },
- "month": {
- "one": "{0} månad",
- "other": "{0} månader",
- },
- "week": {
- "one": "{0} vecka",
- "other": "{0} veckor",
- },
- "day": {
- "one": "{0} dygn",
- "other": "{0} dygn",
- },
- "hour": {
- "one": "{0} timme",
- "other": "{0} timmar",
- },
- "minute": {
- "one": "{0} minut",
- "other": "{0} minuter",
- },
- "second": {
- "one": "{0} sekund",
- "other": "{0} sekunder",
- },
- "microsecond": {
- "one": "{0} mikrosekund",
- "other": "{0} mikrosekunder",
- },
- },
- "relative": {
- "year": {
- "future": {
- "other": "om {0} år",
- "one": "om {0} år",
- },
- "past": {
- "other": "för {0} år sedan",
- "one": "för {0} år sedan",
- },
- },
- "month": {
- "future": {
- "other": "om {0} månader",
- "one": "om {0} månad",
- },
- "past": {
- "other": "för {0} månader sedan",
- "one": "för {0} månad sedan",
- },
- },
- "week": {
- "future": {
- "other": "om {0} veckor",
- "one": "om {0} vecka",
- },
- "past": {
- "other": "för {0} veckor sedan",
- "one": "för {0} vecka sedan",
- },
- },
- "day": {
- "future": {
- "other": "om {0} dagar",
- "one": "om {0} dag",
- },
- "past": {
- "other": "för {0} dagar sedan",
- "one": "för {0} dag sedan",
- },
- },
- "hour": {
- "future": {
- "other": "om {0} timmar",
- "one": "om {0} timme",
- },
- "past": {
- "other": "för {0} timmar sedan",
- "one": "för {0} timme sedan",
- },
- },
- "minute": {
- "future": {
- "other": "om {0} minuter",
- "one": "om {0} minut",
- },
- "past": {
- "other": "för {0} minuter sedan",
- "one": "för {0} minut sedan",
- },
- },
- "second": {
- "future": {
- "other": "om {0} sekunder",
- "one": "om {0} sekund",
- },
- "past": {
- "other": "för {0} sekunder sedan",
- "one": "för {0} sekund sedan",
- },
- },
- },
- "day_periods": {
- "midnight": "midnatt",
- "am": "fm",
- "pm": "em",
- "morning1": "på morgonen",
- "morning2": "på förmiddagen",
- "afternoon1": "på eftermiddagen",
- "evening1": "på kvällen",
- "night1": "på natten",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/locales/zh/__init__.py b/pendulum/locales/zh/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/locales/zh/__init__.py
+++ /dev/null
diff --git a/pendulum/locales/zh/custom.py b/pendulum/locales/zh/custom.py
deleted file mode 100644
index 69bc4ca..0000000
--- a/pendulum/locales/zh/custom.py
+++ /dev/null
@@ -1,18 +0,0 @@
-"""
-zh custom locale file.
-"""
-
-translations = {
- # Relative time
- "after": "{time}后",
- "before": "{time}前",
- # Date formats
- "date_formats": {
- "LTS": "Ah点m分s秒",
- "LT": "Ah点mm分",
- "LLLL": "YYYY年MMMD日ddddAh点mm分",
- "LLL": "YYYY年MMMD日Ah点mm分",
- "LL": "YYYY年MMMD日",
- "L": "YYYY-MM-DD",
- },
-}
diff --git a/pendulum/locales/zh/locale.py b/pendulum/locales/zh/locale.py
deleted file mode 100644
index 2df477f..0000000
--- a/pendulum/locales/zh/locale.py
+++ /dev/null
@@ -1,113 +0,0 @@
-from .custom import translations as custom_translations
-
-
-"""
-zh locale file.
-
-It has been generated automatically and must not be modified directly.
-"""
-
-
-locale = {
- "plural": lambda n: "other",
- "ordinal": lambda n: "other",
- "translations": {
- "days": {
- "abbreviated": {
- 0: "周日",
- 1: "周一",
- 2: "周二",
- 3: "周三",
- 4: "周四",
- 5: "周五",
- 6: "周六",
- },
- "narrow": {0: "日", 1: "一", 2: "二", 3: "三", 4: "四", 5: "五", 6: "六"},
- "short": {0: "周日", 1: "周一", 2: "周二", 3: "周三", 4: "周四", 5: "周五", 6: "周六"},
- "wide": {
- 0: "星期日",
- 1: "星期一",
- 2: "星期二",
- 3: "星期三",
- 4: "星期四",
- 5: "星期五",
- 6: "星期六",
- },
- },
- "months": {
- "abbreviated": {
- 1: "1月",
- 2: "2月",
- 3: "3月",
- 4: "4月",
- 5: "5月",
- 6: "6月",
- 7: "7月",
- 8: "8月",
- 9: "9月",
- 10: "10月",
- 11: "11月",
- 12: "12月",
- },
- "narrow": {
- 1: "1",
- 2: "2",
- 3: "3",
- 4: "4",
- 5: "5",
- 6: "6",
- 7: "7",
- 8: "8",
- 9: "9",
- 10: "10",
- 11: "11",
- 12: "12",
- },
- "wide": {
- 1: "一月",
- 2: "二月",
- 3: "三月",
- 4: "四月",
- 5: "五月",
- 6: "六月",
- 7: "七月",
- 8: "八月",
- 9: "九月",
- 10: "十月",
- 11: "十一月",
- 12: "十二月",
- },
- },
- "units": {
- "year": {"other": "{0}年"},
- "month": {"other": "{0}个月"},
- "week": {"other": "{0}周"},
- "day": {"other": "{0}天"},
- "hour": {"other": "{0}小时"},
- "minute": {"other": "{0}分钟"},
- "second": {"other": "{0}秒钟"},
- "microsecond": {"other": "{0}微秒"},
- },
- "relative": {
- "year": {"future": {"other": "{0}年后"}, "past": {"other": "{0}年前"}},
- "month": {"future": {"other": "{0}个月后"}, "past": {"other": "{0}个月前"}},
- "week": {"future": {"other": "{0}周后"}, "past": {"other": "{0}周前"}},
- "day": {"future": {"other": "{0}天后"}, "past": {"other": "{0}天前"}},
- "hour": {"future": {"other": "{0}小时后"}, "past": {"other": "{0}小时前"}},
- "minute": {"future": {"other": "{0}分钟后"}, "past": {"other": "{0}分钟前"}},
- "second": {"future": {"other": "{0}秒钟后"}, "past": {"other": "{0}秒钟前"}},
- },
- "day_periods": {
- "midnight": "午夜",
- "am": "上午",
- "pm": "下午",
- "morning1": "清晨",
- "morning2": "上午",
- "afternoon1": "下午",
- "afternoon2": "下午",
- "evening1": "晚上",
- "night1": "凌晨",
- },
- },
- "custom": custom_translations,
-}
diff --git a/pendulum/mixins/__init__.py b/pendulum/mixins/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/mixins/__init__.py
+++ /dev/null
diff --git a/pendulum/mixins/default.py b/pendulum/mixins/default.py
deleted file mode 100644
index 59f985e..0000000
--- a/pendulum/mixins/default.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from __future__ import annotations
-
-from pendulum.formatting import Formatter
-
-_formatter = Formatter()
-
-
-class FormattableMixin:
- _formatter: Formatter = _formatter
-
- def format(self, fmt: str, locale: str | None = None) -> str:
- """
- Formats the instance using the given format.
-
- :param fmt: The format to use
- :param locale: The locale to use
- """
- return self._formatter.format(self, fmt, locale)
-
- def for_json(self) -> str:
- """
- Methods for automatic json serialization by simplejson.
- """
- return str(self)
-
- def __format__(self, format_spec: str) -> str:
- if len(format_spec) > 0:
- if "%" in format_spec:
- return self.strftime(format_spec)
-
- return self.format(format_spec)
-
- return str(self)
-
- def __str__(self) -> str:
- return self.isoformat()
diff --git a/pendulum/parser.py b/pendulum/parser.py
deleted file mode 100644
index 77900e2..0000000
--- a/pendulum/parser.py
+++ /dev/null
@@ -1,124 +0,0 @@
-from __future__ import annotations
-
-import datetime
-import typing as t
-
-import pendulum
-
-from pendulum.parsing import _Interval
-from pendulum.parsing import parse as base_parse
-from pendulum.tz.timezone import UTC
-
-if t.TYPE_CHECKING:
- from pendulum.date import Date
- from pendulum.datetime import DateTime
- from pendulum.duration import Duration
- from pendulum.interval import Interval
- from pendulum.time import Time
-
-try:
- from pendulum.parsing._iso8601 import Duration as CDuration
-except ImportError:
- CDuration = None # type: ignore[misc, assignment]
-
-
-def parse(text: str, **options: t.Any) -> Date | Time | DateTime | Duration:
- # Use the mock now value if it exists
- options["now"] = options.get("now")
-
- return _parse(text, **options)
-
-
-def _parse(text: str, **options: t.Any) -> Date | DateTime | Time | Duration | Interval:
- """
- Parses a string with the given options.
-
- :param text: The string to parse.
- """
- # Handling special cases
- if text == "now":
- return pendulum.now()
-
- parsed = base_parse(text, **options)
-
- if isinstance(parsed, datetime.datetime):
- return pendulum.datetime(
- parsed.year,
- parsed.month,
- parsed.day,
- parsed.hour,
- parsed.minute,
- parsed.second,
- parsed.microsecond,
- tz=parsed.tzinfo or options.get("tz", UTC),
- )
-
- if isinstance(parsed, datetime.date):
- return pendulum.date(parsed.year, parsed.month, parsed.day)
-
- if isinstance(parsed, datetime.time):
- return pendulum.time(
- parsed.hour, parsed.minute, parsed.second, parsed.microsecond
- )
-
- if isinstance(parsed, _Interval):
- if parsed.duration is not None:
- duration = parsed.duration
-
- if parsed.start is not None:
- dt = pendulum.instance(parsed.start, tz=options.get("tz", UTC))
-
- return pendulum.interval(
- dt,
- dt.add(
- years=duration.years,
- months=duration.months,
- weeks=duration.weeks,
- days=duration.remaining_days,
- hours=duration.hours,
- minutes=duration.minutes,
- seconds=duration.remaining_seconds,
- microseconds=duration.microseconds,
- ),
- )
-
- dt = pendulum.instance(
- t.cast(datetime.datetime, parsed.end), tz=options.get("tz", UTC)
- )
-
- return pendulum.interval(
- dt.subtract(
- years=duration.years,
- months=duration.months,
- weeks=duration.weeks,
- days=duration.remaining_days,
- hours=duration.hours,
- minutes=duration.minutes,
- seconds=duration.remaining_seconds,
- microseconds=duration.microseconds,
- ),
- dt,
- )
-
- return pendulum.interval(
- pendulum.instance(
- t.cast(datetime.datetime, parsed.start), tz=options.get("tz", UTC)
- ),
- pendulum.instance(
- t.cast(datetime.datetime, parsed.end), tz=options.get("tz", UTC)
- ),
- )
-
- if CDuration and isinstance(parsed, CDuration):
- return pendulum.duration(
- years=parsed.years,
- months=parsed.months,
- weeks=parsed.weeks,
- days=parsed.days,
- hours=parsed.hours,
- minutes=parsed.minutes,
- seconds=parsed.seconds,
- microseconds=parsed.microseconds,
- )
-
- return parsed
diff --git a/pendulum/parsing/__init__.py b/pendulum/parsing/__init__.py
deleted file mode 100644
index 0e64065..0000000
--- a/pendulum/parsing/__init__.py
+++ /dev/null
@@ -1,233 +0,0 @@
-from __future__ import annotations
-
-import contextlib
-import copy
-import os
-import re
-import struct
-
-from datetime import date
-from datetime import datetime
-from datetime import time
-from typing import Any
-from typing import Optional
-from typing import cast
-
-from dateutil import parser
-
-from pendulum.parsing.exceptions import ParserError
-
-with_extensions = os.getenv("PENDULUM_EXTENSIONS", "1") == "1"
-
-try:
- if not with_extensions or struct.calcsize("P") == 4:
- raise ImportError()
-
- from pendulum.parsing._iso8601 import Duration
- from pendulum.parsing._iso8601 import parse_iso8601
-except ImportError:
- from pendulum.duration import Duration # type: ignore[misc]
- from pendulum.parsing.iso8601 import parse_iso8601 # type: ignore[misc]
-
-COMMON = re.compile(
- # Date (optional) # noqa: E800
- "^"
- "(?P<date>"
- " (?P<classic>" # Classic date (YYYY-MM-DD)
- r" (?P<year>\d{4})" # Year
- " (?P<monthday>"
- r" (?P<monthsep>[/:])?(?P<month>\d{2})" # Month (optional)
- r" ((?P<daysep>[/:])?(?P<day>\d{2}))" # Day (optional)
- " )?"
- " )"
- ")?"
- # Time (optional) # noqa: E800
- "(?P<time>"
- r" (?P<timesep>\ )?" # Separator (space)
- r" (?P<hour>\d{1,2}):(?P<minute>\d{1,2})?(?::(?P<second>\d{1,2}))?" # HH:mm:ss (optional mm and ss)
- # Subsecond part (optional)
- " (?P<subsecondsection>"
- " (?:[.|,])" # Subsecond separator (optional)
- r" (?P<subsecond>\d{1,9})" # Subsecond
- " )?"
- ")?"
- "$",
- re.VERBOSE,
-)
-
-DEFAULT_OPTIONS = {
- "day_first": False,
- "year_first": True,
- "strict": True,
- "exact": False,
- "now": None,
-}
-
-
-def parse(text: str, **options: Any) -> datetime | date | time | _Interval | Duration:
- """
- Parses a string with the given options.
-
- :param text: The string to parse.
- """
- _options: dict[str, Any] = copy.copy(DEFAULT_OPTIONS)
- _options.update(options)
-
- return _normalize(_parse(text, **_options), **_options)
-
-
-def _normalize(
- parsed: datetime | date | time | _Interval | Duration, **options: Any
-) -> datetime | date | time | _Interval | Duration:
- """
- Normalizes the parsed element.
-
- :param parsed: The parsed elements.
- """
- if options.get("exact"):
- return parsed
-
- if isinstance(parsed, time):
- now = cast(Optional[datetime], options["now"]) or datetime.now()
-
- return datetime(
- now.year,
- now.month,
- now.day,
- parsed.hour,
- parsed.minute,
- parsed.second,
- parsed.microsecond,
- )
- elif isinstance(parsed, date) and not isinstance(parsed, datetime):
- return datetime(parsed.year, parsed.month, parsed.day)
-
- return parsed
-
-
-def _parse(text: str, **options: Any) -> datetime | date | time | _Interval | Duration:
- # Trying to parse ISO8601
- with contextlib.suppress(ValueError):
- return parse_iso8601(text)
-
- with contextlib.suppress(ValueError):
- return _parse_iso8601_interval(text)
-
- with contextlib.suppress(ParserError):
- return _parse_common(text, **options)
-
- # We couldn't parse the string
- # so we fallback on the dateutil parser
- # If not strict
- if options.get("strict", True):
- raise ParserError(f"Unable to parse string [{text}]")
-
- try:
- dt = parser.parse(
- text, dayfirst=options["day_first"], yearfirst=options["year_first"]
- )
- except ValueError:
- raise ParserError(f"Invalid date string: {text}")
-
- return dt
-
-
-def _parse_common(text: str, **options: Any) -> datetime | date | time:
- """
- Tries to parse the string as a common datetime format.
-
- :param text: The string to parse.
- """
- m = COMMON.match(text)
- has_date = False
- year = 0
- month = 1
- day = 1
-
- if not m:
- raise ParserError("Invalid datetime string")
-
- if m.group("date"):
- # A date has been specified
- has_date = True
-
- year = int(m.group("year"))
-
- if not m.group("monthday"):
- # No month and day
- month = 1
- day = 1
- else:
- if options["day_first"]:
- month = int(m.group("day"))
- day = int(m.group("month"))
- else:
- month = int(m.group("month"))
- day = int(m.group("day"))
-
- if not m.group("time"):
- return date(year, month, day)
-
- # Grabbing hh:mm:ss
- hour = int(m.group("hour"))
-
- minute = int(m.group("minute"))
-
- if m.group("second"):
- second = int(m.group("second"))
- else:
- second = 0
-
- # Grabbing subseconds, if any
- microsecond = 0
- if m.group("subsecondsection"):
- # Limiting to 6 chars
- subsecond = m.group("subsecond")[:6]
-
- microsecond = int(f"{subsecond:0<6}")
-
- if has_date:
- return datetime(year, month, day, hour, minute, second, microsecond)
-
- return time(hour, minute, second, microsecond)
-
-
-class _Interval:
- """
- Special class to handle ISO 8601 intervals
- """
-
- def __init__(
- self,
- start: datetime | None = None,
- end: datetime | None = None,
- duration: Duration | None = None,
- ) -> None:
- self.start = start
- self.end = end
- self.duration = duration
-
-
-def _parse_iso8601_interval(text: str) -> _Interval:
- if "/" not in text:
- raise ParserError("Invalid interval")
-
- first, last = text.split("/")
- start = end = duration = None
-
- if first[0] == "P":
- # duration/end
- duration = parse_iso8601(first)
- end = parse_iso8601(last)
- elif last[0] == "P":
- # start/duration
- start = parse_iso8601(first)
- duration = parse_iso8601(last)
- else:
- # start/end
- start = parse_iso8601(first)
- end = parse_iso8601(last)
-
- return _Interval(
- cast(datetime, start), cast(datetime, end), cast(Duration, duration)
- )
diff --git a/pendulum/parsing/_iso8601.c b/pendulum/parsing/_iso8601.c
deleted file mode 100644
index 1322423..0000000
--- a/pendulum/parsing/_iso8601.c
+++ /dev/null
@@ -1,1361 +0,0 @@
-/* ------------------------------------------------------------------------- */
-
-#include <Python.h>
-#include <datetime.h>
-#include <structmember.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-
-#ifndef PyVarObject_HEAD_INIT
-#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
-#endif
-
-
-/* ------------------------------------------------------------------------- */
-
-#define EPOCH_YEAR 1970
-
-#define DAYS_PER_N_YEAR 365
-#define DAYS_PER_L_YEAR 366
-
-#define USECS_PER_SEC 1000000
-
-#define SECS_PER_MIN 60
-#define SECS_PER_HOUR (60 * SECS_PER_MIN)
-#define SECS_PER_DAY (SECS_PER_HOUR * 24)
-
-// 400-year chunks always have 146097 days (20871 weeks).
-#define DAYS_PER_400_YEARS 146097L
-#define SECS_PER_400_YEARS ((int64_t)DAYS_PER_400_YEARS * (int64_t)SECS_PER_DAY)
-
-// The number of seconds in an aligned 100-year chunk, for those that
-// do not begin with a leap year and those that do respectively.
-const int64_t SECS_PER_100_YEARS[2] = {
- (uint64_t)(76L * DAYS_PER_N_YEAR + 24L * DAYS_PER_L_YEAR) * SECS_PER_DAY,
- (uint64_t)(75L * DAYS_PER_N_YEAR + 25L * DAYS_PER_L_YEAR) * SECS_PER_DAY
-};
-
-// The number of seconds in an aligned 4-year chunk, for those that
-// do not begin with a leap year and those that do respectively.
-const int32_t SECS_PER_4_YEARS[2] = {
- (4 * DAYS_PER_N_YEAR + 0 * DAYS_PER_L_YEAR) * SECS_PER_DAY,
- (3 * DAYS_PER_N_YEAR + 1 * DAYS_PER_L_YEAR) * SECS_PER_DAY
-};
-
-// The number of seconds in non-leap and leap years respectively.
-const int32_t SECS_PER_YEAR[2] = {
- DAYS_PER_N_YEAR * SECS_PER_DAY,
- DAYS_PER_L_YEAR * SECS_PER_DAY
-};
-
-#define MONTHS_PER_YEAR 12
-
-// The month lengths in non-leap and leap years respectively.
-const int32_t DAYS_PER_MONTHS[2][13] = {
- {-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
- {-1, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
-};
-
-// The day offsets of the beginning of each (1-based) month in non-leap
-// and leap years respectively.
-// For example, in a leap year there are 335 days before December.
-const int32_t MONTHS_OFFSETS[2][14] = {
- {-1, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365},
- {-1, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}
-};
-
-const int DAY_OF_WEEK_TABLE[12] = {
- 0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4
-};
-
-#define TM_SUNDAY 0
-#define TM_MONDAY 1
-#define TM_TUESDAY 2
-#define TM_WEDNESDAY 3
-#define TM_THURSDAY 4
-#define TM_FRIDAY 5
-#define TM_SATURDAY 6
-
-#define TM_JANUARY 0
-#define TM_FEBRUARY 1
-#define TM_MARCH 2
-#define TM_APRIL 3
-#define TM_MAY 4
-#define TM_JUNE 5
-#define TM_JULY 6
-#define TM_AUGUST 7
-#define TM_SEPTEMBER 8
-#define TM_OCTOBER 9
-#define TM_NOVEMBER 10
-#define TM_DECEMBER 11
-
-// Parsing errors
-const int PARSER_INVALID_ISO8601 = 0;
-const int PARSER_INVALID_DATE = 1;
-const int PARSER_INVALID_TIME = 2;
-const int PARSER_INVALID_WEEK_DATE = 3;
-const int PARSER_INVALID_WEEK_NUMBER = 4;
-const int PARSER_INVALID_WEEKDAY_NUMBER = 5;
-const int PARSER_INVALID_ORDINAL_DAY_FOR_YEAR = 6;
-const int PARSER_INVALID_MONTH_OR_DAY = 7;
-const int PARSER_INVALID_MONTH = 8;
-const int PARSER_INVALID_DAY_FOR_MONTH = 9;
-const int PARSER_INVALID_HOUR = 10;
-const int PARSER_INVALID_MINUTE = 11;
-const int PARSER_INVALID_SECOND = 12;
-const int PARSER_INVALID_SUBSECOND = 13;
-const int PARSER_INVALID_TZ_OFFSET = 14;
-const int PARSER_INVALID_DURATION = 15;
-const int PARSER_INVALID_DURATION_FLOAT_YEAR_MONTH_NOT_SUPPORTED = 16;
-
-const char PARSER_ERRORS[17][80] = {
- "Invalid ISO 8601 string",
- "Invalid date",
- "Invalid time",
- "Invalid week date",
- "Invalid week number",
- "Invalid weekday number",
- "Invalid ordinal day for year",
- "Invalid month and/or day",
- "Invalid month",
- "Invalid day for month",
- "Invalid hour",
- "Invalid minute",
- "Invalid second",
- "Invalid subsecond",
- "Invalid timezone offset",
- "Invalid duration",
- "Float years and months are not supported"
-};
-
-/* ------------------------------------------------------------------------- */
-
-
-int p(int y) {
- return y + y/4 - y/100 + y/400;
-}
-
-int is_leap(int year) {
- return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
-}
-
-int week_day(int year, int month, int day) {
- int y;
- int w;
-
- y = year - (month < 3);
-
- w = (p(y) + DAY_OF_WEEK_TABLE[month - 1] + day) % 7;
-
- if (!w) {
- w = 7;
- }
-
- return w;
-}
-
-int days_in_year(int year) {
- if (is_leap(year)) {
- return DAYS_PER_L_YEAR;
- }
-
- return DAYS_PER_N_YEAR;
-}
-
-int is_long_year(int year) {
- return (p(year) % 7 == 4) || (p(year - 1) % 7 == 3);
-}
-
-
-/* ------------------------ Custom Types ------------------------------- */
-
-
-/*
- * class FixedOffset(tzinfo):
- */
-typedef struct {
- PyObject_HEAD
- int offset;
- char *tzname;
-} FixedOffset;
-
-/*
- * def __init__(self, offset):
- * self.offset = offset
-*/
-static int FixedOffset_init(FixedOffset *self, PyObject *args, PyObject *kwargs) {
- int offset;
- char *tzname = NULL;
-
- static char *kwlist[] = {"offset", "tzname", NULL};
-
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|s", kwlist, &offset, &tzname))
- return -1;
-
- self->offset = offset;
- self->tzname = tzname;
-
- return 0;
-}
-
-/*
- * def utcoffset(self, dt):
- * return timedelta(seconds=self.offset * 60)
- */
-static PyObject *FixedOffset_utcoffset(FixedOffset *self, PyObject *args) {
- return PyDelta_FromDSU(0, self->offset, 0);
-}
-
-/*
- * def dst(self, dt):
- * return timedelta(seconds=self.offset * 60)
- */
-static PyObject *FixedOffset_dst(FixedOffset *self, PyObject *args) {
- return PyDelta_FromDSU(0, self->offset, 0);
-}
-
-/*
- * def tzname(self, dt):
- * sign = '+'
- * if self.offset < 0:
- * sign = '-'
- * return f"{sign}{self.offset / 60}:{self.offset % 60}"
- */
-static PyObject *FixedOffset_tzname(FixedOffset *self, PyObject *args) {
- if (self->tzname != NULL) {
- return PyUnicode_FromString(self->tzname);
- }
-
- char sign = '+';
- int offset = self->offset;
-
- if (offset < 0) {
- sign = '-';
- offset *= -1;
- }
-
- return PyUnicode_FromFormat(
- "%c%02d:%02d",
- sign,
- offset / SECS_PER_HOUR,
- offset / SECS_PER_MIN % SECS_PER_MIN
- );
-}
-
-/*
- * def __repr__(self):
- * return self.tzname()
- */
-static PyObject *FixedOffset_repr(FixedOffset *self) {
- return FixedOffset_tzname(self, NULL);
-}
-
-/*
- * Class member / class attributes
- */
-static PyMemberDef FixedOffset_members[] = {
- {"offset", T_INT, offsetof(FixedOffset, offset), 0, "UTC offset"},
- {NULL}
-};
-
-/*
- * Class methods
- */
-static PyMethodDef FixedOffset_methods[] = {
- {"utcoffset", (PyCFunction)FixedOffset_utcoffset, METH_VARARGS, ""},
- {"dst", (PyCFunction)FixedOffset_dst, METH_VARARGS, ""},
- {"tzname", (PyCFunction)FixedOffset_tzname, METH_VARARGS, ""},
- {NULL}
-};
-
-static PyTypeObject FixedOffset_type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "FixedOffset_type", /* tp_name */
- sizeof(FixedOffset), /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_as_async */
- (reprfunc)FixedOffset_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)FixedOffset_repr, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
- "TZInfo with fixed offset", /* tp_doc */
-};
-
-/*
- * Instantiate new FixedOffset_type object
- * Skip overhead of calling PyObject_New and PyObject_Init.
- * Directly allocate object.
- */
-static PyObject *new_fixed_offset_ex(int offset, char *name, PyTypeObject *type) {
- FixedOffset *self = (FixedOffset *) (type->tp_alloc(type, 0));
-
- if (self != NULL) {
- self->offset = offset;
- self->tzname = name;
- }
-
- return (PyObject *) self;
-}
-
-#define new_fixed_offset(offset, name) new_fixed_offset_ex(offset, name, &FixedOffset_type)
-
-
-/*
- * class Duration():
- */
-typedef struct {
- PyObject_HEAD
- int years;
- int months;
- int weeks;
- int days;
- int hours;
- int minutes;
- int seconds;
- int microseconds;
-} Duration;
-
-/*
- * def __init__(self, years, months, days, hours, minutes, seconds, microseconds):
- * self.years = years
- * # ...
-*/
-static int Duration_init(Duration *self, PyObject *args, PyObject *kwargs) {
- int years;
- int months;
- int weeks;
- int days;
- int hours;
- int minutes;
- int seconds;
- int microseconds;
-
- if (!PyArg_ParseTuple(args, "iiiiiiii", &years, &months, &weeks, &days, &hours, &minutes, &seconds, &microseconds))
- return -1;
-
- self->years = years;
- self->months = months;
- self->weeks = weeks;
- self->days = days;
- self->hours = hours;
- self->minutes = minutes;
- self->seconds = seconds;
- self->microseconds = microseconds;
-
- return 0;
-}
-
-/*
- * def __repr__(self):
- * return '{} years {} months {} days {} hours {} minutes {} seconds {} microseconds'.format(
- * self.years, self.months, self.days, self.minutes, self.hours, self.seconds, self.microseconds
- * )
- */
-static PyObject *Duration_repr(Duration *self) {
- return PyUnicode_FromFormat(
- "%d years %d months %d weeks %d days %d hours %d minutes %d seconds %d microseconds",
- self->years,
- self->months,
- self->weeks,
- self->days,
- self->hours,
- self->minutes,
- self->seconds,
- self->microseconds
- );
-}
-
-/*
- * Instantiate new Duration_type object
- * Skip overhead of calling PyObject_New and PyObject_Init.
- * Directly allocate object.
- */
-static PyObject *new_duration_ex(int years, int months, int weeks, int days, int hours, int minutes, int seconds, int microseconds, PyTypeObject *type) {
- Duration *self = (Duration *) (type->tp_alloc(type, 0));
-
- if (self != NULL) {
- self->years = years;
- self->months = months;
- self->weeks = weeks;
- self->days = days;
- self->hours = hours;
- self->minutes = minutes;
- self->seconds = seconds;
- self->microseconds = microseconds;
- }
-
- return (PyObject *) self;
-}
-
-/*
- * Class member / class attributes
- */
-static PyMemberDef Duration_members[] = {
- {"years", T_INT, offsetof(Duration, years), 0, "years in duration"},
- {"months", T_INT, offsetof(Duration, months), 0, "months in duration"},
- {"weeks", T_INT, offsetof(Duration, weeks), 0, "weeks in duration"},
- {"days", T_INT, offsetof(Duration, days), 0, "days in duration"},
- {"remaining_days", T_INT, offsetof(Duration, days), 0, "days in duration"},
- {"hours", T_INT, offsetof(Duration, hours), 0, "hours in duration"},
- {"minutes", T_INT, offsetof(Duration, minutes), 0, "minutes in duration"},
- {"seconds", T_INT, offsetof(Duration, seconds), 0, "seconds in duration"},
- {"remaining_seconds", T_INT, offsetof(Duration, seconds), 0, "seconds in duration"},
- {"microseconds", T_INT, offsetof(Duration, microseconds), 0, "microseconds in duration"},
- {NULL}
-};
-
-static PyTypeObject Duration_type = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "Duration", /* tp_name */
- sizeof(Duration), /* tp_basicsize */
- 0, /* tp_itemsize */
- 0, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_as_async */
- (reprfunc)Duration_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- (reprfunc)Duration_repr, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /* tp_flags */
- "Duration", /* tp_doc */
-};
-
-#define new_duration(years, months, weeks, days, hours, minutes, seconds, microseconds) new_duration_ex(years, months, weeks, days, hours, minutes, seconds, microseconds, &Duration_type)
-
-typedef struct {
- int is_date;
- int is_time;
- int is_datetime;
- int is_duration;
- int is_period;
- int ambiguous;
- int year;
- int month;
- int day;
- int hour;
- int minute;
- int second;
- int microsecond;
- int offset;
- int has_offset;
- char *tzname;
- int years;
- int months;
- int weeks;
- int days;
- int hours;
- int minutes;
- int seconds;
- int microseconds;
- int error;
-} Parsed;
-
-
-Parsed* new_parsed() {
- Parsed *parsed;
-
- if((parsed = malloc(sizeof *parsed)) != NULL) {
- parsed->is_date = 0;
- parsed->is_time = 0;
- parsed->is_datetime = 0;
- parsed->is_duration = 0;
- parsed->is_period = 0;
-
- parsed->ambiguous = 0;
- parsed->year = 0;
- parsed->month = 1;
- parsed->day = 1;
- parsed->hour = 0;
- parsed->minute = 0;
- parsed->second = 0;
- parsed->microsecond = 0;
- parsed->offset = 0;
- parsed->has_offset = 0;
- parsed->tzname = NULL;
-
- parsed->years = 0;
- parsed->months = 0;
- parsed->weeks = 0;
- parsed->days = 0;
- parsed->hours = 0;
- parsed->minutes = 0;
- parsed->seconds = 0;
- parsed->microseconds = 0;
-
- parsed->error = -1;
- }
-
- return parsed;
-}
-
-
-/* -------------------------- Functions --------------------------*/
-
-Parsed* _parse_iso8601_datetime(char *str, Parsed *parsed) {
- char* c;
- int monthday = 0;
- int week = 0;
- int weekday = 1;
- int ordinal;
- int tz_sign = 0;
- int leap = 0;
- int separators = 0;
- int time = 0;
- int i;
- int j;
-
- // Assuming date only for now
- parsed->is_date = 1;
-
- c = str;
-
- for (i = 0; i < 4; i++) {
- if (*c >= '0' && *c <= '9') {
- parsed->year = 10 * parsed->year + *c++ - '0';
- } else {
- parsed->error = PARSER_INVALID_ISO8601;
-
- return NULL;
- }
- }
-
- leap = is_leap(parsed->year);
-
- // Optional separator
- if (*c == '-') {
- separators++;
- c++;
- }
-
- // Checking for week dates
- if (*c == 'W') {
- c++;
-
- i = 0;
- while (*c != '\0' && *c != ' ' && *c != 'T') {
- if (*c == '-') {
- separators++;
- c++;
- continue;
- }
-
- week = 10 * week + *c++ - '0';
-
- i++;
- }
-
- switch (i) {
- case 2:
- // Only week number
- break;
- case 3:
- // Week with weekday
- if (!(separators == 0 || separators == 2)) {
- // We should have 2 or no separator
- parsed->error = PARSER_INVALID_WEEK_DATE;
-
- return NULL;
- }
-
- weekday = week % 10;
- week /= 10;
-
- break;
- default:
- // Any other case is wrong
- parsed->error = PARSER_INVALID_WEEK_DATE;
-
- return NULL;
- }
-
- // Checks
- if (week > 53 || (week > 52 && !is_long_year(parsed->year))) {
- parsed->error = PARSER_INVALID_WEEK_NUMBER;
-
- return NULL;
- }
-
- if (weekday > 7) {
- parsed->error = PARSER_INVALID_WEEKDAY_NUMBER;
-
- return NULL;
- }
-
- // Calculating ordinal day
- ordinal = week * 7 + weekday - (week_day(parsed->year, 1, 4) + 3);
-
- if (ordinal < 1) {
- // Previous year
- ordinal += days_in_year(parsed->year - 1);
- parsed->year -= 1;
- leap = is_leap(parsed->year);
- }
-
- if (ordinal > days_in_year(parsed->year)) {
- // Next year
- ordinal -= days_in_year(parsed->year);
- parsed->year += 1;
- leap = is_leap(parsed->year);
- }
-
- for (j = 1; j < 14; j++) {
- if (ordinal <= MONTHS_OFFSETS[leap][j]) {
- parsed->day = ordinal - MONTHS_OFFSETS[leap][j - 1];
- parsed->month = j - 1;
-
- break;
- }
- }
- } else {
- // At this point we need to check the number
- // of characters until the end of the date part
- // (or the end of the string).
- //
- // If two, we have only a month if there is a separator, it may be a time otherwise.
- // If three, we have an ordinal date.
- // If four, we have a complete date
- i = 0;
- while (*c != '\0' && *c != ' ' && *c != 'T') {
- if (*c == '-') {
- separators++;
- c++;
- continue;
- }
-
- if (!(*c >= '0' && *c <='9')) {
- parsed->error = PARSER_INVALID_DATE;
-
- return NULL;
- }
-
- monthday = 10 * monthday + *c++ - '0';
-
- i++;
- }
-
- switch (i) {
- case 0:
- // No month/day specified (only a year)
- break;
- case 2:
- if (!separators) {
- // The date looks like 201207
- // which is invalid for a date
- // But it might be a time in the form hhmmss
- parsed->ambiguous = 1;
- } else if (separators > 1) {
- parsed->error = PARSER_INVALID_DATE;
-
- return NULL;
- }
-
- parsed->month = monthday;
- break;
- case 3:
- // Ordinal day
- if (separators > 1) {
- parsed->error = PARSER_INVALID_DATE;
-
- return NULL;
- }
-
- if (monthday < 1 || monthday > MONTHS_OFFSETS[leap][13]) {
- parsed->error = PARSER_INVALID_ORDINAL_DAY_FOR_YEAR;
-
- return NULL;
- }
-
- for (j = 1; j < 14; j++) {
- if (monthday <= MONTHS_OFFSETS[leap][j]) {
- parsed->day = monthday - MONTHS_OFFSETS[leap][j - 1];
- parsed->month = j - 1;
-
- break;
- }
- }
-
- break;
- case 4:
- // Month and day
- parsed->month = monthday / 100;
- parsed->day = monthday % 100;
-
- break;
- default:
- parsed->error = PARSER_INVALID_MONTH_OR_DAY;
-
- return NULL;
- }
- }
-
- // Checks
- if (separators && !monthday && !week) {
- parsed->error = PARSER_INVALID_DATE;
-
- return NULL;
- }
-
- if (parsed->month > 12) {
- parsed->error = PARSER_INVALID_MONTH;
-
- return NULL;
- }
-
- if (parsed->day > DAYS_PER_MONTHS[leap][parsed->month]) {
- parsed->error = PARSER_INVALID_DAY_FOR_MONTH;
-
- return NULL;
- }
-
- separators = 0;
- if (*c == 'T' || *c == ' ') {
- if (parsed->ambiguous) {
- parsed->error = PARSER_INVALID_DATE;
-
- return NULL;
- }
-
- // We have time so we have a datetime
- parsed->is_datetime = 1;
- parsed->is_date = 0;
-
- c++;
-
- // Grabbing time information
- i = 0;
- while (*c != '\0' && *c != '.' && *c != ',' && *c != 'Z' && *c != '+' && *c != '-') {
- if (*c == ':') {
- separators++;
- c++;
- continue;
- }
-
- if (!(*c >= '0' && *c <='9')) {
- parsed->error = PARSER_INVALID_TIME;
-
- return NULL;
- }
-
- time = 10 * time + *c++ - '0';
- i++;
- }
-
- switch (i) {
- case 2:
- // Hours only
- if (separators > 0) {
- // Extraneous separators
- parsed->error = PARSER_INVALID_TIME;
-
- return NULL;
- }
-
- parsed->hour = time;
- break;
- case 4:
- // Hours and minutes
- if (separators > 1) {
- // Extraneous separators
- parsed->error = PARSER_INVALID_TIME;
-
- return NULL;
- }
-
- parsed->hour = time / 100;
- parsed->minute = time % 100;
- break;
- case 6:
- // Hours, minutes and seconds
- if (!(separators == 0 || separators == 2)) {
- // We should have either two separators or none
- parsed->error = PARSER_INVALID_TIME;
-
- return NULL;
- }
-
- parsed->hour = time / 10000;
- parsed->minute = time / 100 % 100;
- parsed->second = time % 100;
- break;
- default:
- // Any other case is wrong
- parsed->error = PARSER_INVALID_TIME;
-
- return NULL;
- }
-
- // Checks
- if (parsed->hour > 23) {
- parsed->error = PARSER_INVALID_HOUR;
-
- return NULL;
- }
-
- if (parsed->minute > 59) {
- parsed->error = PARSER_INVALID_MINUTE;
-
- return NULL;
- }
-
- if (parsed->second > 59) {
- parsed->error = PARSER_INVALID_SECOND;
-
- return NULL;
- }
-
- // Subsecond
- if (*c == '.' || *c == ',') {
- c++;
-
- time = 0;
- i = 0;
- while (*c != '\0' && *c != 'Z' && *c != '+' && *c != '-') {
- if (!(*c >= '0' && *c <='9')) {
- parsed->error = PARSER_INVALID_SUBSECOND;
-
- return NULL;
- }
-
- time = 10 * time + *c++ - '0';
- i++;
- }
-
- // adjust to microseconds
- if (i > 6) {
- parsed->microsecond = time / pow(10, i - 6);
- } else if (i <= 6) {
- parsed->microsecond = time * pow(10, 6 - i);
- }
- }
-
- // Timezone
- if (*c == 'Z') {
- parsed->has_offset = 1;
- parsed->tzname = "UTC";
- c++;
- } else if (*c == '+' || *c == '-') {
- tz_sign = 1;
- if (*c == '-') {
- tz_sign = -1;
- }
-
- parsed->has_offset = 1;
- c++;
-
- i = 0;
- time = 0;
- separators = 0;
- while (*c != '\0') {
- if (*c == ':') {
- separators++;
- c++;
- continue;
- }
-
- if (!(*c >= '0' && *c <= '9')) {
- parsed->error = PARSER_INVALID_TZ_OFFSET;
-
- return NULL;
- }
-
- time = 10 * time + *c++ - '0';
- i++;
- }
-
- switch (i) {
- case 2:
- // hh Format
- if (separators) {
- // Extraneous separators
- parsed->error = PARSER_INVALID_TZ_OFFSET;
-
- return NULL;
- }
-
- parsed->offset = tz_sign * (time * 3600);
- break;
- case 4:
- // hhmm Format
- if (separators > 1) {
- // Extraneous separators
- parsed->error = PARSER_INVALID_TZ_OFFSET;
-
- return NULL;
- }
-
- parsed->offset = tz_sign * ((time / 100 * 3600) + (time % 100 * 60));
- break;
- default:
- // Wrong format
- parsed->error = PARSER_INVALID_TZ_OFFSET;
-
- return NULL;
- }
- }
- }
-
- // At this point we should be at the end of the string
- // If not, the string is invalid
- if (*c != '\0') {
- parsed->error = PARSER_INVALID_ISO8601;
-
- return NULL;
- }
-
- return parsed;
-}
-
-
-Parsed* _parse_iso8601_duration(char *str, Parsed *parsed) {
- char* c;
- int value = 0;
- int grabbed = 0;
- int in_time = 0;
- int in_fraction = 0;
- int fraction_length = 0;
- int has_fractional = 0;
- int fraction = 0;
- int has_ymd = 0;
- int has_week = 0;
- int has_month = 0;
- int has_day = 0;
- int has_hour = 0;
- int has_minute = 0;
- int has_second = 0;
-
- c = str;
-
- // Removing P operator
- c++;
-
- parsed->is_duration = 1;
-
- for (; *c != '\0'; c++) {
- switch (*c) {
- case 'Y':
- if (!grabbed || in_time || has_week || has_ymd) {
- // No value grabbed
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- if (fraction) {
- parsed->error = PARSER_INVALID_DURATION_FLOAT_YEAR_MONTH_NOT_SUPPORTED;
-
- return NULL;
- }
-
- parsed->years = value;
-
- grabbed = 0;
- value = 0;
- fraction = 0;
- in_fraction = 0;
- has_ymd = 1;
-
- break;
- case 'M':
- if (!grabbed || has_week) {
- // No value grabbed
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- if (in_time) {
- if (has_second) {
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- if (has_fractional) {
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- parsed->minutes = value;
- if (fraction) {
- parsed->seconds = fraction * 6;
- has_fractional = 1;
- }
-
- has_minute = 1;
- } else {
- if (fraction) {
- parsed->error = PARSER_INVALID_DURATION_FLOAT_YEAR_MONTH_NOT_SUPPORTED;
-
- return NULL;
- }
-
- if (has_month || has_day) {
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- parsed->months = value;
- has_ymd = 1;
- has_month = 1;
- }
-
- grabbed = 0;
- value = 0;
- fraction = 0;
- in_fraction = 0;
-
- break;
- case 'D':
- if (!grabbed || in_time || has_week) {
- // No value grabbed
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- if (has_day) {
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- parsed->days = value;
- if (fraction) {
- parsed->hours = fraction * 2.4;
- has_fractional = 1;
- }
-
- grabbed = 0;
- value = 0;
- fraction = 0;
- in_fraction = 0;
- has_ymd = 1;
- has_day = 1;
-
- break;
- case 'T':
- if (grabbed) {
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- in_time = 1;
-
- break;
- case 'H':
- if (!grabbed || !in_time || has_week) {
- // No value grabbed
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- if (has_hour || has_second || has_minute) {
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- if (has_fractional) {
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- parsed->hours = value;
- if (fraction) {
- parsed->minutes = fraction * 6;
- has_fractional = 1;
- }
-
- grabbed = 0;
- value = 0;
- fraction = 0;
- in_fraction = 0;
- has_hour = 1;
-
- break;
- case 'S':
- if (!grabbed || !in_time || has_week) {
- // No value grabbed
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- if (has_second) {
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- if (has_fractional) {
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- if (fraction) {
- parsed->seconds = value;
- if (fraction_length > 6) {
- parsed->microseconds = fraction / pow(10, fraction_length - 6);
- } else {
- parsed->microseconds = fraction * pow(10, 6 - fraction_length);
- }
- has_fractional = 1;
- } else {
- parsed->seconds = value;
- }
-
- grabbed = 0;
- value = 0;
- fraction = 0;
- in_fraction = 0;
- has_second = 1;
-
- break;
- case 'W':
- if (!grabbed || in_time || has_ymd) {
- // No value grabbed
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- parsed->weeks = value;
- if (fraction) {
- float days;
- days = fraction * 0.7;
- parsed->hours = (int) ((days - (int) days) * 24);
- parsed->days = (int) days;
- }
-
- grabbed = 0;
- value = 0;
- fraction = 0;
- in_fraction = 0;
- has_week = 1;
-
- break;
- case '.':
- if (!grabbed || has_fractional) {
- // No value grabbed
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- in_fraction = 1;
-
- break;
- case ',':
- if (!grabbed || has_fractional) {
- // No value grabbed
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
-
- in_fraction = 1;
-
- break;
- default:
- if (*c >= '0' && *c <='9') {
- if (in_fraction) {
- fraction = 10 * fraction + *c - '0';
- fraction_length++;
- } else {
- value = 10 * value + *c - '0';
- grabbed = 1;
- }
- break;
- }
-
- parsed->error = PARSER_INVALID_DURATION;
-
- return NULL;
- }
- }
-
- return parsed;
-}
-
-
-PyObject* parse_iso8601(PyObject *self, PyObject *args) {
- char* str;
- PyObject *obj;
- PyObject *tzinfo;
- Parsed *parsed = new_parsed();
-
- if (!PyArg_ParseTuple(args, "s", &str)) {
- PyErr_SetString(
- PyExc_ValueError, "Invalid parameters"
- );
- free(parsed);
- return NULL;
- }
-
- if (*str == 'P') {
- // Duration (or interval)
- if (_parse_iso8601_duration(str, parsed) == NULL) {
- PyErr_SetString(
- PyExc_ValueError, PARSER_ERRORS[parsed->error]
- );
-
- free(parsed);
- return NULL;
- }
- } else if (_parse_iso8601_datetime(str, parsed) == NULL) {
- PyErr_SetString(
- PyExc_ValueError, PARSER_ERRORS[parsed->error]
- );
-
- free(parsed);
- return NULL;
- }
-
- if (parsed->is_date) {
- // Date only
- if (parsed->ambiguous) {
- // We can "safely" assume that the ambiguous
- // date was actually a time in the form hhmmss
- parsed->hour = parsed->year / 100;
- parsed->minute = parsed->year % 100;
- parsed->second = parsed->month;
-
- obj = PyDateTimeAPI->Time_FromTime(
- parsed->hour, parsed->minute, parsed->second, parsed->microsecond,
- Py_BuildValue(""),
- PyDateTimeAPI->TimeType
- );
- } else {
- obj = PyDateTimeAPI->Date_FromDate(
- parsed->year, parsed->month, parsed->day,
- PyDateTimeAPI->DateType
- );
- }
- } else if (parsed->is_datetime) {
- if (!parsed->has_offset) {
- tzinfo = Py_BuildValue("");
- } else {
- tzinfo = new_fixed_offset(parsed->offset, parsed->tzname);
- }
-
- obj = PyDateTimeAPI->DateTime_FromDateAndTime(
- parsed->year,
- parsed->month,
- parsed->day,
- parsed->hour,
- parsed->minute,
- parsed->second,
- parsed->microsecond,
- tzinfo,
- PyDateTimeAPI->DateTimeType
- );
-
- Py_DECREF(tzinfo);
- } else if (parsed->is_duration) {
- obj = new_duration(
- parsed->years, parsed->months, parsed->weeks, parsed->days,
- parsed->hours, parsed->minutes, parsed->seconds, parsed->microseconds
- );
- } else {
- free(parsed);
- return NULL;
- }
-
- free(parsed);
-
- return obj;
-}
-
-
-/* ------------------------------------------------------------------------- */
-
-static PyMethodDef helpers_methods[] = {
- {
- "parse_iso8601",
- (PyCFunction) parse_iso8601,
- METH_VARARGS,
- PyDoc_STR("Parses a ISO8601 string into a tuple.")
- },
- {NULL}
-};
-
-
-/* ------------------------------------------------------------------------- */
-
-static struct PyModuleDef moduledef = {
- PyModuleDef_HEAD_INIT,
- "_iso8601",
- NULL,
- -1,
- helpers_methods,
- NULL,
- NULL,
- NULL,
- NULL,
-};
-
-PyMODINIT_FUNC
-PyInit__iso8601(void)
-{
- PyObject *module;
-
- PyDateTime_IMPORT;
-
- module = PyModule_Create(&moduledef);
-
- if (module == NULL)
- return NULL;
-
- // FixedOffset declaration
- FixedOffset_type.tp_new = PyType_GenericNew;
- FixedOffset_type.tp_base = PyDateTimeAPI->TZInfoType;
- FixedOffset_type.tp_methods = FixedOffset_methods;
- FixedOffset_type.tp_members = FixedOffset_members;
- FixedOffset_type.tp_init = (initproc)FixedOffset_init;
-
- if (PyType_Ready(&FixedOffset_type) < 0)
- return NULL;
-
- // Duration declaration
- Duration_type.tp_new = PyType_GenericNew;
- Duration_type.tp_members = Duration_members;
- Duration_type.tp_init = (initproc)Duration_init;
-
- if (PyType_Ready(&Duration_type) < 0)
- return NULL;
-
- Py_INCREF(&FixedOffset_type);
- Py_INCREF(&Duration_type);
-
- PyModule_AddObject(module, "TZFixedOffset", (PyObject *)&FixedOffset_type);
- PyModule_AddObject(module, "Duration", (PyObject *)&Duration_type);
-
- return module;
-}
diff --git a/pendulum/parsing/_iso8601.pyi b/pendulum/parsing/_iso8601.pyi
deleted file mode 100644
index b9ce5d4..0000000
--- a/pendulum/parsing/_iso8601.pyi
+++ /dev/null
@@ -1,22 +0,0 @@
-from __future__ import annotations
-
-from datetime import date
-from datetime import datetime
-from datetime import time
-
-class Duration:
-
- years: int = 0
- months: int = 0
- weeks: int = 0
- days: int = 0
- remaining_days: int = 0
- hours: int = 0
- minutes: int = 0
- seconds: int = 0
- remaining_seconds: int = 0
- microseconds: int = 0
-
-def parse_iso8601(
- text: str,
-) -> datetime | date | time | Duration: ...
diff --git a/pendulum/parsing/exceptions/__init__.py b/pendulum/parsing/exceptions/__init__.py
deleted file mode 100644
index 05195b5..0000000
--- a/pendulum/parsing/exceptions/__init__.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import annotations
-
-
-class ParserError(ValueError):
-
- pass
diff --git a/pendulum/parsing/iso8601.py b/pendulum/parsing/iso8601.py
deleted file mode 100644
index 907cf13..0000000
--- a/pendulum/parsing/iso8601.py
+++ /dev/null
@@ -1,454 +0,0 @@
-from __future__ import annotations
-
-import datetime
-import re
-
-from typing import cast
-
-from pendulum.constants import HOURS_PER_DAY
-from pendulum.constants import MINUTES_PER_HOUR
-from pendulum.constants import MONTHS_OFFSETS
-from pendulum.constants import SECONDS_PER_MINUTE
-from pendulum.duration import Duration
-from pendulum.helpers import days_in_year
-from pendulum.helpers import is_leap
-from pendulum.helpers import is_long_year
-from pendulum.helpers import week_day
-from pendulum.parsing.exceptions import ParserError
-from pendulum.tz.timezone import UTC
-from pendulum.tz.timezone import FixedTimezone
-
-ISO8601_DT = re.compile(
- # Date (optional) # noqa: E800
- "^"
- "(?P<date>"
- " (?P<classic>" # Classic date (YYYY-MM-DD) or ordinal (YYYY-DDD)
- r" (?P<year>\d{4})" # Year
- " (?P<monthday>"
- r" (?P<monthsep>-)?(?P<month>\d{2})" # Month (optional)
- r" ((?P<daysep>-)?(?P<day>\d{1,2}))?" # Day (optional)
- " )?"
- " )"
- " |"
- " (?P<isocalendar>" # Calendar date (2016-W05 or 2016-W05-5)
- r" (?P<isoyear>\d{4})" # Year
- " (?P<weeksep>-)?" # Separator (optional)
- " W" # W separator
- r" (?P<isoweek>\d{2})" # Week number
- " (?P<weekdaysep>-)?" # Separator (optional)
- r" (?P<isoweekday>\d)?" # Weekday (optional)
- " )"
- ")?"
- # Time (optional) # noqa: E800
- "(?P<time>"
- r" (?P<timesep>[T\ ])?" # Separator (T or space)
- r" (?P<hour>\d{1,2})(?P<minsep>:)?(?P<minute>\d{1,2})?(?P<secsep>:)?(?P<second>\d{1,2})?" # HH:mm:ss (optional mm and ss)
- # Subsecond part (optional)
- " (?P<subsecondsection>"
- " (?:[.,])" # Subsecond separator (optional)
- r" (?P<subsecond>\d{1,9})" # Subsecond
- " )?"
- # Timezone offset
- " (?P<tz>"
- r" (?:[-+])\d{2}:?(?:\d{2})?|Z" # Offset (+HH:mm or +HHmm or +HH or Z)
- " )?"
- ")?"
- "$",
- re.VERBOSE,
-)
-
-ISO8601_DURATION = re.compile(
- "^P" # Duration P indicator
- # Years, months and days (optional) # noqa: E800
- "(?P<w>"
- r" (?P<weeks>\d+(?:[.,]\d+)?W)"
- ")?"
- "(?P<ymd>"
- r" (?P<years>\d+(?:[.,]\d+)?Y)?"
- r" (?P<months>\d+(?:[.,]\d+)?M)?"
- r" (?P<days>\d+(?:[.,]\d+)?D)?"
- ")?"
- "(?P<hms>"
- " (?P<timesep>T)" # Separator (T)
- r" (?P<hours>\d+(?:[.,]\d+)?H)?"
- r" (?P<minutes>\d+(?:[.,]\d+)?M)?"
- r" (?P<seconds>\d+(?:[.,]\d+)?S)?"
- ")?"
- "$",
- re.VERBOSE,
-)
-
-
-def parse_iso8601(
- text: str,
-) -> datetime.datetime | datetime.date | datetime.time | Duration:
- """
- ISO 8601 compliant parser.
-
- :param text: The string to parse
- :type text: str
-
- :rtype: datetime.datetime or datetime.time or datetime.date
- """
- parsed = _parse_iso8601_duration(text)
- if parsed is not None:
- return parsed
-
- m = ISO8601_DT.match(text)
- if not m:
- raise ParserError("Invalid ISO 8601 string")
-
- ambiguous_date = False
- is_date = False
- is_time = False
- year = 0
- month = 1
- day = 1
- minute = 0
- second = 0
- microsecond = 0
- tzinfo: FixedTimezone | None = None
-
- if m.group("date"):
- # A date has been specified
- is_date = True
-
- if m.group("isocalendar"):
- # We have a ISO 8601 string defined
- # by week number
- if (
- m.group("weeksep")
- and not m.group("weekdaysep")
- and m.group("isoweekday")
- ):
- raise ParserError(f"Invalid date string: {text}")
-
- if not m.group("weeksep") and m.group("weekdaysep"):
- raise ParserError(f"Invalid date string: {text}")
-
- try:
- date = _get_iso_8601_week(
- m.group("isoyear"), m.group("isoweek"), m.group("isoweekday")
- )
- except ParserError:
- raise
- except ValueError:
- raise ParserError(f"Invalid date string: {text}")
-
- year = date["year"]
- month = date["month"]
- day = date["day"]
- else:
- # We have a classic date representation
- year = int(m.group("year"))
-
- if not m.group("monthday"):
- # No month and day
- month = 1
- day = 1
- else:
- if m.group("month") and m.group("day"):
- # Month and day
- if not m.group("daysep") and len(m.group("day")) == 1:
- # Ordinal day
- ordinal = int(m.group("month") + m.group("day"))
- leap = is_leap(year)
- months_offsets = MONTHS_OFFSETS[leap]
-
- if ordinal > months_offsets[13]:
- raise ParserError("Ordinal day is out of range")
-
- for i in range(1, 14):
- if ordinal <= months_offsets[i]:
- day = ordinal - months_offsets[i - 1]
- month = i - 1
-
- break
- else:
- month = int(m.group("month"))
- day = int(m.group("day"))
- else:
- # Only month
- if not m.group("monthsep"):
- # The date looks like 201207
- # which is invalid for a date
- # But it might be a time in the form hhmmss
- ambiguous_date = True
-
- month = int(m.group("month"))
- day = 1
-
- if not m.group("time"):
- # No time has been specified
- if ambiguous_date:
- # We can "safely" assume that the ambiguous date
- # was actually a time in the form hhmmss
- hhmmss = f"{str(year)}{str(month):0>2}"
-
- return datetime.time(int(hhmmss[:2]), int(hhmmss[2:4]), int(hhmmss[4:]))
-
- return datetime.date(year, month, day)
-
- if ambiguous_date:
- raise ParserError(f"Invalid date string: {text}")
-
- if is_date and not m.group("timesep"):
- raise ParserError(f"Invalid date string: {text}")
-
- if not is_date:
- is_time = True
-
- # Grabbing hh:mm:ss
- hour = int(m.group("hour"))
- minsep = m.group("minsep")
-
- if m.group("minute"):
- minute = int(m.group("minute"))
- elif minsep:
- raise ParserError("Invalid ISO 8601 time part")
-
- secsep = m.group("secsep")
- if secsep and not minsep and m.group("minute"):
- # minute/second separator but no hour/minute separator
- raise ParserError("Invalid ISO 8601 time part")
-
- if m.group("second"):
- if not secsep and minsep:
- # No minute/second separator but hour/minute separator
- raise ParserError("Invalid ISO 8601 time part")
-
- second = int(m.group("second"))
- elif secsep:
- raise ParserError("Invalid ISO 8601 time part")
-
- # Grabbing subseconds, if any
- if m.group("subsecondsection"):
- # Limiting to 6 chars
- subsecond = m.group("subsecond")[:6]
-
- microsecond = int(f"{subsecond:0<6}")
-
- # Grabbing timezone, if any
- tz = m.group("tz")
- if tz:
- if tz == "Z":
- tzinfo = UTC
- else:
- negative = bool(tz.startswith("-"))
- tz = tz[1:]
- if ":" not in tz:
- if len(tz) == 2:
- tz = f"{tz}00"
-
- off_hour = tz[0:2]
- off_minute = tz[2:4]
- else:
- off_hour, off_minute = tz.split(":")
-
- offset = ((int(off_hour) * 60) + int(off_minute)) * 60
-
- if negative:
- offset = -1 * offset
-
- tzinfo = FixedTimezone(offset)
-
- if is_time:
- return datetime.time(hour, minute, second, microsecond)
-
- return datetime.datetime(
- year, month, day, hour, minute, second, microsecond, tzinfo=tzinfo
- )
-
-
-def _parse_iso8601_duration(text: str, **options: str) -> Duration | None:
- m = ISO8601_DURATION.match(text)
- if not m:
- return None
-
- years = 0
- months = 0
- weeks = 0
- days: int | float = 0
- hours: int | float = 0
- minutes: int | float = 0
- seconds: int | float = 0
- microseconds: int | float = 0
- fractional = False
-
- _days: str | float
- _hour: str | int | None
- _minutes: str | int | None
- _seconds: str | int | None
- if m.group("w"):
- # Weeks
- if m.group("ymd") or m.group("hms"):
- # Specifying anything more than weeks is not supported
- raise ParserError("Invalid duration string")
-
- _weeks = m.group("weeks")
- if not _weeks:
- raise ParserError("Invalid duration string")
-
- _weeks = _weeks.replace(",", ".").replace("W", "")
- if "." in _weeks:
- _weeks, portion = _weeks.split(".")
- weeks = int(_weeks)
- _days = int(portion) / 10 * 7
- days, hours = int(_days // 1), int(_days % 1 * HOURS_PER_DAY)
- else:
- weeks = int(_weeks)
-
- if m.group("ymd"):
- # Years, months and/or days
- _years = m.group("years")
- _months = m.group("months")
- _days = m.group("days")
-
- # Checking order
- years_start = m.start("years") if _years else -3
- months_start = m.start("months") if _months else years_start + 1
- days_start = m.start("days") if _days else months_start + 1
-
- # Check correct order
- if not (years_start < months_start < days_start):
- raise ParserError("Invalid duration")
-
- if _years:
- _years = _years.replace(",", ".").replace("Y", "")
- if "." in _years:
- raise ParserError("Float years in duration are not supported")
- else:
- years = int(_years)
-
- if _months:
- if fractional:
- raise ParserError("Invalid duration")
-
- _months = _months.replace(",", ".").replace("M", "")
- if "." in _months:
- raise ParserError("Float months in duration are not supported")
- else:
- months = int(_months)
-
- if _days:
- if fractional:
- raise ParserError("Invalid duration")
-
- _days = _days.replace(",", ".").replace("D", "")
-
- if "." in _days:
- fractional = True
-
- _days, _hours = _days.split(".")
- days = int(_days)
- hours = int(_hours) / 10 * HOURS_PER_DAY
- else:
- days = int(_days)
-
- if m.group("hms"):
- # Hours, minutes and/or seconds
- _hours = m.group("hours") or 0
- _minutes = m.group("minutes") or 0
- _seconds = m.group("seconds") or 0
-
- # Checking order
- hours_start = m.start("hours") if _hours else -3
- minutes_start = m.start("minutes") if _minutes else hours_start + 1
- seconds_start = m.start("seconds") if _seconds else minutes_start + 1
-
- # Check correct order
- if not (hours_start < minutes_start < seconds_start):
- raise ParserError("Invalid duration")
-
- if _hours:
- if fractional:
- raise ParserError("Invalid duration")
-
- _hours = cast(str, _hours).replace(",", ".").replace("H", "")
-
- if "." in _hours:
- fractional = True
-
- _hours, _mins = _hours.split(".")
- hours += int(_hours)
- minutes += int(_mins) / 10 * MINUTES_PER_HOUR
- else:
- hours += int(_hours)
-
- if _minutes:
- if fractional:
- raise ParserError("Invalid duration")
-
- _minutes = cast(str, _minutes).replace(",", ".").replace("M", "")
-
- if "." in _minutes:
- fractional = True
-
- _minutes, _secs = _minutes.split(".")
- minutes += int(_minutes)
- seconds += int(_secs) / 10 * SECONDS_PER_MINUTE
- else:
- minutes += int(_minutes)
-
- if _seconds:
- if fractional:
- raise ParserError("Invalid duration")
-
- _seconds = cast(str, _seconds).replace(",", ".").replace("S", "")
-
- if "." in _seconds:
- _seconds, _microseconds = _seconds.split(".")
- seconds += int(_seconds)
- microseconds += int(f"{_microseconds[:6]:0<6}")
- else:
- seconds += int(_seconds)
-
- return Duration(
- years=years,
- months=months,
- weeks=weeks,
- days=days,
- hours=hours,
- minutes=minutes,
- seconds=seconds,
- microseconds=microseconds,
- )
-
-
-def _get_iso_8601_week(
- year: int | str, week: int | str, weekday: int | str
-) -> dict[str, int]:
- if not weekday:
- weekday = 1
- else:
- weekday = int(weekday)
-
- year = int(year)
- week = int(week)
-
- if week > 53 or week > 52 and not is_long_year(year):
- raise ParserError("Invalid week for week date")
-
- if weekday > 7:
- raise ParserError("Invalid weekday for week date")
-
- # We can't rely on strptime directly here since
- # it does not support ISO week date
- ordinal = week * 7 + weekday - (week_day(year, 1, 4) + 3)
-
- if ordinal < 1:
- # Previous year
- ordinal += days_in_year(year - 1)
- year -= 1
-
- if ordinal > days_in_year(year):
- # Next year
- ordinal -= days_in_year(year)
- year += 1
-
- fmt = "%Y-%j"
- string = f"{year}-{ordinal}"
-
- dt = datetime.datetime.strptime(string, fmt)
-
- return {"year": dt.year, "month": dt.month, "day": dt.day}
diff --git a/pendulum/py.typed b/pendulum/py.typed
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/py.typed
+++ /dev/null
diff --git a/pendulum/testing/__init__.py b/pendulum/testing/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/testing/__init__.py
+++ /dev/null
diff --git a/pendulum/testing/traveller.py b/pendulum/testing/traveller.py
deleted file mode 100644
index 3c1d885..0000000
--- a/pendulum/testing/traveller.py
+++ /dev/null
@@ -1,139 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-from typing import cast
-
-from pendulum.datetime import DateTime
-from pendulum.utils._compat import PYPY
-
-if TYPE_CHECKING:
- from types import TracebackType
-
-
-class BaseTraveller:
- def __init__(self, datetime_class: type[DateTime] = DateTime) -> None:
- self._datetime_class: type[DateTime] = datetime_class
-
- def freeze(self: BaseTraveller) -> BaseTraveller:
- raise NotImplementedError()
-
- def travel_back(self: BaseTraveller) -> BaseTraveller:
- raise NotImplementedError()
-
- def travel(
- self,
- years: int = 0,
- months: int = 0,
- weeks: int = 0,
- days: int = 0,
- hours: int = 0,
- minutes: int = 0,
- seconds: int = 0,
- microseconds: int = 0,
- ) -> BaseTraveller:
- raise NotImplementedError()
-
- def travel_to(self, dt: DateTime) -> BaseTraveller:
- raise NotImplementedError()
-
-
-if not PYPY:
- import time_machine
-
- class Traveller(BaseTraveller):
- def __init__(self, datetime_class: type[DateTime] = DateTime) -> None:
- super().__init__(datetime_class)
-
- self._started: bool = False
- self._traveller: time_machine.travel | None = None
- self._coordinates: time_machine.Coordinates | None = None
-
- def freeze(self) -> Traveller:
- if self._started:
- cast(time_machine.Coordinates, self._coordinates).move_to(
- self._datetime_class.now(), tick=False
- )
- else:
- self._start(freeze=True)
-
- return self
-
- def travel_back(self) -> Traveller:
- if not self._started:
- return self
-
- cast(time_machine.travel, self._traveller).stop()
- self._coordinates = None
- self._traveller = None
- self._started = False
-
- return self
-
- def travel(
- self,
- years: int = 0,
- months: int = 0,
- weeks: int = 0,
- days: int = 0,
- hours: int = 0,
- minutes: int = 0,
- seconds: int = 0,
- microseconds: int = 0,
- *,
- freeze: bool = False,
- ) -> Traveller:
- self._start(freeze=freeze)
-
- cast(time_machine.Coordinates, self._coordinates).move_to(
- self._datetime_class.now().add(
- years=years,
- months=months,
- weeks=weeks,
- days=days,
- hours=hours,
- minutes=minutes,
- seconds=seconds,
- microseconds=microseconds,
- )
- )
-
- return self
-
- def travel_to(self, dt: DateTime, *, freeze: bool = False) -> Traveller:
- self._start(freeze=freeze)
-
- cast(time_machine.Coordinates, self._coordinates).move_to(dt)
-
- return self
-
- def _start(self, freeze: bool = False) -> None:
- if self._started:
- return
-
- if not self._traveller:
- self._traveller = time_machine.travel(
- self._datetime_class.now(), tick=not freeze
- )
-
- self._coordinates = self._traveller.start()
-
- self._started = True
-
- def __enter__(self) -> Traveller:
- self._start()
-
- return self
-
- def __exit__(
- self,
- exc_type: type[BaseException] | None,
- exc_val: BaseException | None,
- exc_tb: TracebackType,
- ) -> None:
- self.travel_back()
-
-else:
-
- class Traveller(BaseTraveller): # type: ignore[no-redef]
-
- ...
diff --git a/pendulum/time.py b/pendulum/time.py
deleted file mode 100644
index f979e25..0000000
--- a/pendulum/time.py
+++ /dev/null
@@ -1,303 +0,0 @@
-from __future__ import annotations
-
-import datetime
-
-from datetime import time
-from datetime import timedelta
-from typing import TYPE_CHECKING
-from typing import Optional
-from typing import cast
-from typing import overload
-
-import pendulum
-
-from pendulum.constants import SECS_PER_HOUR
-from pendulum.constants import SECS_PER_MIN
-from pendulum.constants import USECS_PER_SEC
-from pendulum.duration import AbsoluteDuration
-from pendulum.duration import Duration
-from pendulum.mixins.default import FormattableMixin
-
-if TYPE_CHECKING:
- from typing import Literal
-
-
-class Time(FormattableMixin, time):
- """
- Represents a time instance as hour, minute, second, microsecond.
- """
-
- # String formatting
- def __repr__(self) -> str:
- us = ""
- if self.microsecond:
- us = f", {self.microsecond}"
-
- tzinfo = ""
- if self.tzinfo:
- tzinfo = f", tzinfo={repr(self.tzinfo)}"
-
- return (
- f"{self.__class__.__name__}"
- f"({self.hour}, {self.minute}, {self.second}{us}{tzinfo})"
- )
-
- # Comparisons
-
- def closest(self, dt1: Time | time, dt2: Time | time) -> Time:
- """
- Get the closest time from the instance.
- """
- dt1 = self.__class__(dt1.hour, dt1.minute, dt1.second, dt1.microsecond)
- dt2 = self.__class__(dt2.hour, dt2.minute, dt2.second, dt2.microsecond)
-
- if self.diff(dt1).in_seconds() < self.diff(dt2).in_seconds():
- return dt1
-
- return dt2
-
- def farthest(self, dt1: Time | time, dt2: Time | time) -> Time:
- """
- Get the farthest time from the instance.
- """
- dt1 = self.__class__(dt1.hour, dt1.minute, dt1.second, dt1.microsecond)
- dt2 = self.__class__(dt2.hour, dt2.minute, dt2.second, dt2.microsecond)
-
- if self.diff(dt1).in_seconds() > self.diff(dt2).in_seconds():
- return dt1
-
- return dt2
-
- # ADDITIONS AND SUBSTRACTIONS
-
- def add(
- self, hours: int = 0, minutes: int = 0, seconds: int = 0, microseconds: int = 0
- ) -> Time:
- """
- Add duration to the instance.
-
- :param hours: The number of hours
- :param minutes: The number of minutes
- :param seconds: The number of seconds
- :param microseconds: The number of microseconds
- """
- from pendulum.datetime import DateTime
-
- return (
- DateTime.EPOCH.at(self.hour, self.minute, self.second, self.microsecond)
- .add(
- hours=hours, minutes=minutes, seconds=seconds, microseconds=microseconds
- )
- .time()
- )
-
- def subtract(
- self, hours: int = 0, minutes: int = 0, seconds: int = 0, microseconds: int = 0
- ) -> Time:
- """
- Add duration to the instance.
-
- :param hours: The number of hours
- :type hours: int
-
- :param minutes: The number of minutes
- :type minutes: int
-
- :param seconds: The number of seconds
- :type seconds: int
-
- :param microseconds: The number of microseconds
- :type microseconds: int
-
- :rtype: Time
- """
- from pendulum.datetime import DateTime
-
- return (
- DateTime.EPOCH.at(self.hour, self.minute, self.second, self.microsecond)
- .subtract(
- hours=hours, minutes=minutes, seconds=seconds, microseconds=microseconds
- )
- .time()
- )
-
- def add_timedelta(self, delta: datetime.timedelta) -> Time:
- """
- Add timedelta duration to the instance.
-
- :param delta: The timedelta instance
- """
- if delta.days:
- raise TypeError("Cannot add timedelta with days to Time.")
-
- return self.add(seconds=delta.seconds, microseconds=delta.microseconds)
-
- def subtract_timedelta(self, delta: datetime.timedelta) -> Time:
- """
- Remove timedelta duration from the instance.
-
- :param delta: The timedelta instance
- """
- if delta.days:
- raise TypeError("Cannot subtract timedelta with days to Time.")
-
- return self.subtract(seconds=delta.seconds, microseconds=delta.microseconds)
-
- def __add__(self, other: datetime.timedelta) -> Time:
- if not isinstance(other, timedelta):
- return NotImplemented
-
- return self.add_timedelta(other)
-
- @overload
- def __sub__(self, other: time) -> pendulum.Duration:
- ...
-
- @overload
- def __sub__(self, other: datetime.timedelta) -> Time:
- ...
-
- def __sub__(self, other: time | datetime.timedelta) -> pendulum.Duration | Time:
- if not isinstance(other, (Time, time, timedelta)):
- return NotImplemented
-
- if isinstance(other, timedelta):
- return self.subtract_timedelta(other)
-
- if isinstance(other, time):
- if other.tzinfo is not None:
- raise TypeError("Cannot subtract aware times to or from Time.")
-
- other = self.__class__(
- other.hour, other.minute, other.second, other.microsecond
- )
-
- return other.diff(self, False)
-
- @overload
- def __rsub__(self, other: time) -> pendulum.Duration:
- ...
-
- @overload
- def __rsub__(self, other: datetime.timedelta) -> Time:
- ...
-
- def __rsub__(self, other: time | datetime.timedelta) -> pendulum.Duration | Time:
- if not isinstance(other, (Time, time)):
- return NotImplemented
-
- if isinstance(other, time):
- if other.tzinfo is not None:
- raise TypeError("Cannot subtract aware times to or from Time.")
-
- other = self.__class__(
- other.hour, other.minute, other.second, other.microsecond
- )
-
- return other.__sub__(self)
-
- # DIFFERENCES
-
- def diff(self, dt: time | None = None, abs: bool = True) -> Duration:
- """
- Returns the difference between two Time objects as an Duration.
-
- :param dt: The time to subtract from
- :param abs: Whether to return an absolute duration or not
- """
- if dt is None:
- dt = pendulum.now().time()
- else:
- dt = self.__class__(dt.hour, dt.minute, dt.second, dt.microsecond)
-
- us1 = (
- self.hour * SECS_PER_HOUR + self.minute * SECS_PER_MIN + self.second
- ) * USECS_PER_SEC
-
- us2 = (
- dt.hour * SECS_PER_HOUR + dt.minute * SECS_PER_MIN + dt.second
- ) * USECS_PER_SEC
-
- klass = Duration
- if abs:
- klass = AbsoluteDuration
-
- return klass(microseconds=us2 - us1)
-
- def diff_for_humans(
- self,
- other: time | None = None,
- absolute: bool = False,
- locale: str | None = None,
- ) -> str:
- """
- Get the difference in a human readable format in the current locale.
-
- :param dt: The time to subtract from
- :param absolute: removes time difference modifiers ago, after, etc
- :param locale: The locale to use for localization
- """
- is_now = other is None
-
- if is_now:
- other = pendulum.now().time()
-
- diff = self.diff(other)
-
- return pendulum.format_diff(diff, is_now, absolute, locale)
-
- # Compatibility methods
-
- def replace(
- self,
- hour: int | None = None,
- minute: int | None = None,
- second: int | None = None,
- microsecond: int | None = None,
- tzinfo: bool | datetime.tzinfo | Literal[True] | None = True,
- fold: int = 0,
- ) -> Time:
- if tzinfo is True:
- tzinfo = self.tzinfo
-
- hour = hour if hour is not None else self.hour
- minute = minute if minute is not None else self.minute
- second = second if second is not None else self.second
- microsecond = microsecond if microsecond is not None else self.microsecond
-
- t = super().replace(
- hour,
- minute,
- second,
- microsecond,
- tzinfo=cast(Optional[datetime.tzinfo], tzinfo),
- fold=fold,
- )
- return self.__class__(
- t.hour, t.minute, t.second, t.microsecond, tzinfo=t.tzinfo
- )
-
- def __getnewargs__(self) -> tuple[Time]:
- return (self,)
-
- def _get_state(
- self, protocol: int = 3
- ) -> tuple[int, int, int, int, datetime.tzinfo | None]:
- tz = self.tzinfo
-
- return self.hour, self.minute, self.second, self.microsecond, tz
-
- def __reduce__(
- self,
- ) -> tuple[type[Time], tuple[int, int, int, int, datetime.tzinfo | None]]:
- return self.__reduce_ex__(2)
-
- def __reduce_ex__( # type: ignore[override]
- self, protocol: int
- ) -> tuple[type[Time], tuple[int, int, int, int, datetime.tzinfo | None]]:
- return self.__class__, self._get_state(protocol)
-
-
-Time.min = Time(0, 0, 0)
-Time.max = Time(23, 59, 59, 999999)
-Time.resolution = Duration(microseconds=1)
diff --git a/pendulum/tz/__init__.py b/pendulum/tz/__init__.py
deleted file mode 100644
index 45c9855..0000000
--- a/pendulum/tz/__init__.py
+++ /dev/null
@@ -1,80 +0,0 @@
-from __future__ import annotations
-
-import sys
-
-from pendulum.tz.local_timezone import get_local_timezone
-from pendulum.tz.local_timezone import set_local_timezone
-from pendulum.tz.local_timezone import test_local_timezone
-from pendulum.tz.timezone import UTC
-from pendulum.tz.timezone import FixedTimezone
-from pendulum.tz.timezone import Timezone
-
-if sys.version_info >= (3, 9):
- from importlib import resources
-else:
- import importlib_resources as resources
-
-PRE_TRANSITION = "pre"
-POST_TRANSITION = "post"
-TRANSITION_ERROR = "error"
-
-_timezones = None
-
-_tz_cache: dict[int, FixedTimezone] = {}
-
-
-def timezones() -> tuple[str, ...]:
- global _timezones
-
- if _timezones is None:
- with resources.files("tzdata").joinpath("zones").open() as f:
- _timezones = tuple(tz.strip() for tz in f.readlines())
-
- return _timezones
-
-
-def timezone(name: str | int) -> Timezone | FixedTimezone:
- """
- Return a Timezone instance given its name.
- """
- if isinstance(name, int):
- return fixed_timezone(name)
-
- if name.lower() == "utc":
- return UTC
-
- return Timezone(name)
-
-
-def fixed_timezone(offset: int) -> FixedTimezone:
- """
- Return a Timezone instance given its offset in seconds.
- """
- if offset in _tz_cache:
- return _tz_cache[offset]
-
- tz = FixedTimezone(offset)
- _tz_cache[offset] = tz
-
- return tz
-
-
-def local_timezone() -> Timezone | FixedTimezone:
- """
- Return the local timezone.
- """
- return get_local_timezone()
-
-
-__all__ = [
- "UTC",
- "Timezone",
- "FixedTimezone",
- "set_local_timezone",
- "get_local_timezone",
- "test_local_timezone",
- "timezone",
- "fixed_timezone",
- "local_timezone",
- "timezones",
-]
diff --git a/pendulum/tz/data/__init__.py b/pendulum/tz/data/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/tz/data/__init__.py
+++ /dev/null
diff --git a/pendulum/tz/data/windows.py b/pendulum/tz/data/windows.py
deleted file mode 100644
index 65aa6c3..0000000
--- a/pendulum/tz/data/windows.py
+++ /dev/null
@@ -1,139 +0,0 @@
-from __future__ import annotations
-
-windows_timezones = {
- "AUS Central Standard Time": "Australia/Darwin",
- "AUS Eastern Standard Time": "Australia/Sydney",
- "Afghanistan Standard Time": "Asia/Kabul",
- "Alaskan Standard Time": "America/Anchorage",
- "Aleutian Standard Time": "America/Adak",
- "Altai Standard Time": "Asia/Barnaul",
- "Arab Standard Time": "Asia/Riyadh",
- "Arabian Standard Time": "Asia/Dubai",
- "Arabic Standard Time": "Asia/Baghdad",
- "Argentina Standard Time": "America/Buenos_Aires",
- "Astrakhan Standard Time": "Europe/Astrakhan",
- "Atlantic Standard Time": "America/Halifax",
- "Aus Central W. Standard Time": "Australia/Eucla",
- "Azerbaijan Standard Time": "Asia/Baku",
- "Azores Standard Time": "Atlantic/Azores",
- "Bahia Standard Time": "America/Bahia",
- "Bangladesh Standard Time": "Asia/Dhaka",
- "Belarus Standard Time": "Europe/Minsk",
- "Bougainville Standard Time": "Pacific/Bougainville",
- "Canada Central Standard Time": "America/Regina",
- "Cape Verde Standard Time": "Atlantic/Cape_Verde",
- "Caucasus Standard Time": "Asia/Yerevan",
- "Cen. Australia Standard Time": "Australia/Adelaide",
- "Central America Standard Time": "America/Guatemala",
- "Central Asia Standard Time": "Asia/Almaty",
- "Central Brazilian Standard Time": "America/Cuiaba",
- "Central Europe Standard Time": "Europe/Budapest",
- "Central European Standard Time": "Europe/Warsaw",
- "Central Pacific Standard Time": "Pacific/Guadalcanal",
- "Central Standard Time": "America/Chicago",
- "Central Standard Time (Mexico)": "America/Mexico_City",
- "Chatham Islands Standard Time": "Pacific/Chatham",
- "China Standard Time": "Asia/Shanghai",
- "Cuba Standard Time": "America/Havana",
- "Dateline Standard Time": "Etc/GMT+12",
- "E. Africa Standard Time": "Africa/Nairobi",
- "E. Australia Standard Time": "Australia/Brisbane",
- "E. Europe Standard Time": "Europe/Chisinau",
- "E. South America Standard Time": "America/Sao_Paulo",
- "Easter Island Standard Time": "Pacific/Easter",
- "Eastern Standard Time": "America/New_York",
- "Eastern Standard Time (Mexico)": "America/Cancun",
- "Egypt Standard Time": "Africa/Cairo",
- "Ekaterinburg Standard Time": "Asia/Yekaterinburg",
- "FLE Standard Time": "Europe/Kiev",
- "Fiji Standard Time": "Pacific/Fiji",
- "GMT Standard Time": "Europe/London",
- "GTB Standard Time": "Europe/Bucharest",
- "Georgian Standard Time": "Asia/Tbilisi",
- "Greenland Standard Time": "America/Godthab",
- "Greenwich Standard Time": "Atlantic/Reykjavik",
- "Haiti Standard Time": "America/Port-au-Prince",
- "Hawaiian Standard Time": "Pacific/Honolulu",
- "India Standard Time": "Asia/Calcutta",
- "Iran Standard Time": "Asia/Tehran",
- "Israel Standard Time": "Asia/Jerusalem",
- "Jordan Standard Time": "Asia/Amman",
- "Kaliningrad Standard Time": "Europe/Kaliningrad",
- "Korea Standard Time": "Asia/Seoul",
- "Libya Standard Time": "Africa/Tripoli",
- "Line Islands Standard Time": "Pacific/Kiritimati",
- "Lord Howe Standard Time": "Australia/Lord_Howe",
- "Magadan Standard Time": "Asia/Magadan",
- "Magallanes Standard Time": "America/Punta_Arenas",
- "Marquesas Standard Time": "Pacific/Marquesas",
- "Mauritius Standard Time": "Indian/Mauritius",
- "Middle East Standard Time": "Asia/Beirut",
- "Montevideo Standard Time": "America/Montevideo",
- "Morocco Standard Time": "Africa/Casablanca",
- "Mountain Standard Time": "America/Denver",
- "Mountain Standard Time (Mexico)": "America/Chihuahua",
- "Myanmar Standard Time": "Asia/Rangoon",
- "N. Central Asia Standard Time": "Asia/Novosibirsk",
- "Namibia Standard Time": "Africa/Windhoek",
- "Nepal Standard Time": "Asia/Katmandu",
- "New Zealand Standard Time": "Pacific/Auckland",
- "Newfoundland Standard Time": "America/St_Johns",
- "Norfolk Standard Time": "Pacific/Norfolk",
- "North Asia East Standard Time": "Asia/Irkutsk",
- "North Asia Standard Time": "Asia/Krasnoyarsk",
- "North Korea Standard Time": "Asia/Pyongyang",
- "Omsk Standard Time": "Asia/Omsk",
- "Pacific SA Standard Time": "America/Santiago",
- "Pacific Standard Time": "America/Los_Angeles",
- "Pacific Standard Time (Mexico)": "America/Tijuana",
- "Pakistan Standard Time": "Asia/Karachi",
- "Paraguay Standard Time": "America/Asuncion",
- "Romance Standard Time": "Europe/Paris",
- "Russia Time Zone 10": "Asia/Srednekolymsk",
- "Russia Time Zone 11": "Asia/Kamchatka",
- "Russia Time Zone 3": "Europe/Samara",
- "Russian Standard Time": "Europe/Moscow",
- "SA Eastern Standard Time": "America/Cayenne",
- "SA Pacific Standard Time": "America/Bogota",
- "SA Western Standard Time": "America/La_Paz",
- "SE Asia Standard Time": "Asia/Bangkok",
- "Saint Pierre Standard Time": "America/Miquelon",
- "Sakhalin Standard Time": "Asia/Sakhalin",
- "Samoa Standard Time": "Pacific/Apia",
- "Sao Tome Standard Time": "Africa/Sao_Tome",
- "Saratov Standard Time": "Europe/Saratov",
- "Singapore Standard Time": "Asia/Singapore",
- "South Africa Standard Time": "Africa/Johannesburg",
- "Sri Lanka Standard Time": "Asia/Colombo",
- "Sudan Standard Time": "Africa/Khartoum",
- "Syria Standard Time": "Asia/Damascus",
- "Taipei Standard Time": "Asia/Taipei",
- "Tasmania Standard Time": "Australia/Hobart",
- "Tocantins Standard Time": "America/Araguaina",
- "Tokyo Standard Time": "Asia/Tokyo",
- "Tomsk Standard Time": "Asia/Tomsk",
- "Tonga Standard Time": "Pacific/Tongatapu",
- "Transbaikal Standard Time": "Asia/Chita",
- "Turkey Standard Time": "Europe/Istanbul",
- "Turks And Caicos Standard Time": "America/Grand_Turk",
- "US Eastern Standard Time": "America/Indianapolis",
- "US Mountain Standard Time": "America/Phoenix",
- "UTC": "Etc/GMT",
- "UTC+12": "Etc/GMT-12",
- "UTC+13": "Etc/GMT-13",
- "UTC-02": "Etc/GMT+2",
- "UTC-08": "Etc/GMT+8",
- "UTC-09": "Etc/GMT+9",
- "UTC-11": "Etc/GMT+11",
- "Ulaanbaatar Standard Time": "Asia/Ulaanbaatar",
- "Venezuela Standard Time": "America/Caracas",
- "Vladivostok Standard Time": "Asia/Vladivostok",
- "W. Australia Standard Time": "Australia/Perth",
- "W. Central Africa Standard Time": "Africa/Lagos",
- "W. Europe Standard Time": "Europe/Berlin",
- "W. Mongolia Standard Time": "Asia/Hovd",
- "West Asia Standard Time": "Asia/Tashkent",
- "West Bank Standard Time": "Asia/Hebron",
- "West Pacific Standard Time": "Pacific/Port_Moresby",
- "Yakutsk Standard Time": "Asia/Yakutsk",
-}
diff --git a/pendulum/tz/exceptions.py b/pendulum/tz/exceptions.py
deleted file mode 100644
index b8833ac..0000000
--- a/pendulum/tz/exceptions.py
+++ /dev/null
@@ -1,32 +0,0 @@
-from __future__ import annotations
-
-from typing import TYPE_CHECKING
-
-if TYPE_CHECKING:
- from datetime import datetime
-
-
-class TimezoneError(ValueError):
- pass
-
-
-class InvalidTimezone(TimezoneError):
- pass
-
-
-class NonExistingTime(TimezoneError):
- message = "The datetime {} does not exist."
-
- def __init__(self, dt: datetime) -> None:
- message = self.message.format(dt)
-
- super().__init__(message)
-
-
-class AmbiguousTime(TimezoneError):
- message = "The datetime {} is ambiguous."
-
- def __init__(self, dt: datetime) -> None:
- message = self.message.format(dt)
-
- super().__init__(message)
diff --git a/pendulum/tz/local_timezone.py b/pendulum/tz/local_timezone.py
deleted file mode 100644
index 41cf81b..0000000
--- a/pendulum/tz/local_timezone.py
+++ /dev/null
@@ -1,260 +0,0 @@
-from __future__ import annotations
-
-import contextlib
-import os
-import re
-import sys
-
-from contextlib import contextmanager
-from typing import Iterator
-from typing import cast
-
-from pendulum.tz.exceptions import InvalidTimezone
-from pendulum.tz.timezone import FixedTimezone
-from pendulum.tz.timezone import Timezone
-
-if sys.platform == "win32":
- try:
- import _winreg as winreg
- except (ImportError, AttributeError):
- import winreg
-
-_mock_local_timezone = None
-_local_timezone = None
-
-
-def get_local_timezone() -> Timezone | FixedTimezone:
- global _local_timezone
-
- if _mock_local_timezone is not None:
- return _mock_local_timezone
-
- if _local_timezone is None:
- tz = _get_system_timezone()
-
- _local_timezone = tz
-
- return _local_timezone
-
-
-def set_local_timezone(mock: str | Timezone | None = None) -> None:
- global _mock_local_timezone
-
- _mock_local_timezone = mock
-
-
-@contextmanager
-def test_local_timezone(mock: Timezone) -> Iterator[None]:
- set_local_timezone(mock)
-
- yield
-
- set_local_timezone()
-
-
-def _get_system_timezone() -> Timezone:
- if sys.platform == "win32":
- return _get_windows_timezone()
- elif "darwin" in sys.platform:
- return _get_darwin_timezone()
-
- return _get_unix_timezone()
-
-
-if sys.platform == "win32":
-
- def _get_windows_timezone() -> Timezone:
- from pendulum.tz.data.windows import windows_timezones
-
- # Windows is special. It has unique time zone names (in several
- # meanings of the word) available, but unfortunately, they can be
- # translated to the language of the operating system, so we need to
- # do a backwards lookup, by going through all time zones and see which
- # one matches.
- handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
-
- tz_local_key_name = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation"
- localtz = winreg.OpenKey(handle, tz_local_key_name)
-
- timezone_info = {}
- size = winreg.QueryInfoKey(localtz)[1]
- for i in range(size):
- data = winreg.EnumValue(localtz, i)
- timezone_info[data[0]] = data[1]
-
- localtz.Close()
-
- if "TimeZoneKeyName" in timezone_info:
- # Windows 7 (and Vista?)
-
- # For some reason this returns a string with loads of NUL bytes at
- # least on some systems. I don't know if this is a bug somewhere, I
- # just work around it.
- tzkeyname = timezone_info["TimeZoneKeyName"].split("\x00", 1)[0]
- else:
- # Windows 2000 or XP
-
- # This is the localized name:
- tzwin = timezone_info["StandardName"]
-
- # Open the list of timezones to look up the real name:
- tz_key_name = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
- tzkey = winreg.OpenKey(handle, tz_key_name)
-
- # Now, match this value to Time Zone information
- tzkeyname = None
- for i in range(winreg.QueryInfoKey(tzkey)[0]):
- subkey = winreg.EnumKey(tzkey, i)
- sub = winreg.OpenKey(tzkey, subkey)
-
- info = {}
- size = winreg.QueryInfoKey(sub)[1]
- for i in range(size):
- data = winreg.EnumValue(sub, i)
- info[data[0]] = data[1]
-
- sub.Close()
- with contextlib.suppress(KeyError):
- # This timezone didn't have proper configuration.
- # Ignore it.
- if info["Std"] == tzwin:
- tzkeyname = subkey
- break
-
- tzkey.Close()
- handle.Close()
-
- if tzkeyname is None:
- raise LookupError("Can not find Windows timezone configuration")
-
- timezone = windows_timezones.get(tzkeyname)
- if timezone is None:
- # Nope, that didn't work. Try adding "Standard Time",
- # it seems to work a lot of times:
- timezone = windows_timezones.get(tzkeyname + " Standard Time")
-
- # Return what we have.
- if timezone is None:
- raise LookupError("Unable to find timezone " + tzkeyname)
-
- return Timezone(timezone)
-
-else:
-
- def _get_windows_timezone() -> Timezone:
- ...
-
-
-def _get_darwin_timezone() -> Timezone:
- # link will be something like /usr/share/zoneinfo/America/Los_Angeles.
- link = os.readlink("/etc/localtime")
- tzname = link[link.rfind("zoneinfo/") + 9 :]
-
- return Timezone(tzname)
-
-
-def _get_unix_timezone(_root: str = "/") -> Timezone:
- tzenv = os.environ.get("TZ")
- if tzenv:
- with contextlib.suppress(ValueError):
- return _tz_from_env(tzenv)
-
- # Now look for distribution specific configuration files
- # that contain the timezone name.
- tzpath = os.path.join(_root, "etc/timezone")
- if os.path.isfile(tzpath):
- with open(tzpath, "rb") as tzfile:
- tzfile_data = tzfile.read()
-
- # Issue #3 was that /etc/timezone was a zoneinfo file.
- # That's a misconfiguration, but we need to handle it gracefully:
- if tzfile_data[:5] != b"TZif2":
- etctz = tzfile_data.strip().decode()
- # Get rid of host definitions and comments:
- if " " in etctz:
- etctz, dummy = etctz.split(" ", 1)
- if "#" in etctz:
- etctz, dummy = etctz.split("#", 1)
-
- return Timezone(etctz.replace(" ", "_"))
-
- # CentOS has a ZONE setting in /etc/sysconfig/clock,
- # OpenSUSE has a TIMEZONE setting in /etc/sysconfig/clock and
- # Gentoo has a TIMEZONE setting in /etc/conf.d/clock
- # We look through these files for a timezone:
- zone_re = re.compile(r'\s*ZONE\s*=\s*"')
- timezone_re = re.compile(r'\s*TIMEZONE\s*=\s*"')
- end_re = re.compile('"')
-
- for filename in ("etc/sysconfig/clock", "etc/conf.d/clock"):
- tzpath = os.path.join(_root, filename)
- if not os.path.isfile(tzpath):
- continue
-
- with open(tzpath) as tzfile:
- data = tzfile.readlines()
-
- for line in data:
- # Look for the ZONE= setting.
- match = zone_re.match(line)
- if match is None:
- # No ZONE= setting. Look for the TIMEZONE= setting.
- match = timezone_re.match(line)
-
- if match is not None:
- # Some setting existed
- line = line[match.end() :]
- etctz = line[
- : cast(
- re.Match, end_re.search(line) # type: ignore[type-arg]
- ).start()
- ]
-
- parts = list(reversed(etctz.replace(" ", "_").split(os.path.sep)))
- tzpath_parts: list[str] = []
- while parts:
- tzpath_parts.insert(0, parts.pop(0))
-
- with contextlib.suppress(InvalidTimezone):
- return Timezone(os.path.join(*tzpath_parts))
-
- # systemd distributions use symlinks that include the zone name,
- # see manpage of localtime(5) and timedatectl(1)
- tzpath = os.path.join(_root, "etc", "localtime")
- if os.path.isfile(tzpath) and os.path.islink(tzpath):
- parts = list(
- reversed(os.path.realpath(tzpath).replace(" ", "_").split(os.path.sep))
- )
- tzpath_parts: list[str] = [] # type: ignore[no-redef]
- while parts:
- tzpath_parts.insert(0, parts.pop(0))
- with contextlib.suppress(InvalidTimezone):
- return Timezone(os.path.join(*tzpath_parts))
-
- # No explicit setting existed. Use localtime
- for filename in ("etc/localtime", "usr/local/etc/localtime"):
- tzpath = os.path.join(_root, filename)
-
- if not os.path.isfile(tzpath):
- continue
-
- with open(tzpath, "rb") as f:
- return cast(Timezone, Timezone.from_file(f))
-
- raise RuntimeError("Unable to find any timezone configuration")
-
-
-def _tz_from_env(tzenv: str) -> Timezone:
- if tzenv[0] == ":":
- tzenv = tzenv[1:]
-
- # TZ specifies a file
- if os.path.isfile(tzenv):
- with open(tzenv, "rb") as f:
- return cast(Timezone, Timezone.from_file(f))
-
- # TZ specifies a zoneinfo zone.
- try:
- return Timezone(tzenv)
- except ValueError:
- raise
diff --git a/pendulum/tz/timezone.py b/pendulum/tz/timezone.py
deleted file mode 100644
index f689004..0000000
--- a/pendulum/tz/timezone.py
+++ /dev/null
@@ -1,217 +0,0 @@
-from __future__ import annotations
-
-import datetime as datetime_
-
-from abc import ABC
-from abc import abstractmethod
-from typing import cast
-
-from pendulum.tz.exceptions import AmbiguousTime
-from pendulum.tz.exceptions import InvalidTimezone
-from pendulum.tz.exceptions import NonExistingTime
-from pendulum.utils._compat import zoneinfo
-
-POST_TRANSITION = "post"
-PRE_TRANSITION = "pre"
-TRANSITION_ERROR = "error"
-
-
-class PendulumTimezone(ABC):
- @property
- @abstractmethod
- def name(self) -> str:
- raise NotImplementedError
-
- @abstractmethod
- def convert(
- self, dt: datetime_.datetime, raise_on_unknown_times: bool = False
- ) -> datetime_.datetime:
- raise NotImplementedError
-
- @abstractmethod
- def datetime(
- self,
- year: int,
- month: int,
- day: int,
- hour: int = 0,
- minute: int = 0,
- second: int = 0,
- microsecond: int = 0,
- ) -> datetime_.datetime:
- raise NotImplementedError
-
-
-class Timezone(zoneinfo.ZoneInfo, PendulumTimezone): # type: ignore[misc]
- """
- Represents a named timezone.
-
- The accepted names are those provided by the IANA time zone database.
-
- >>> from pendulum.tz.timezone import Timezone
- >>> tz = Timezone('Europe/Paris')
- """
-
- def __new__(cls, key: str) -> Timezone:
- try:
- return cast(Timezone, super().__new__(cls, key))
- except zoneinfo.ZoneInfoNotFoundError:
- raise InvalidTimezone(key)
-
- @property
- def name(self) -> str:
- return cast(str, self.key)
-
- def convert(
- self, dt: datetime_.datetime, raise_on_unknown_times: bool = False
- ) -> datetime_.datetime:
- """
- Converts a datetime in the current timezone.
-
- If the datetime is naive, it will be normalized.
-
- >>> from datetime import datetime
- >>> from pendulum import timezone
- >>> paris = timezone('Europe/Paris')
- >>> dt = datetime(2013, 3, 31, 2, 30, fold=1)
- >>> in_paris = paris.convert(dt)
- >>> in_paris.isoformat()
- '2013-03-31T03:30:00+02:00'
-
- If the datetime is aware, it will be properly converted.
-
- >>> new_york = timezone('America/New_York')
- >>> in_new_york = new_york.convert(in_paris)
- >>> in_new_york.isoformat()
- '2013-03-30T21:30:00-04:00'
- """
- if dt.tzinfo is None:
- offset_before = (
- self.utcoffset(dt.replace(fold=0)) if dt.fold else self.utcoffset(dt)
- )
- offset_after = (
- self.utcoffset(dt) if dt.fold else self.utcoffset(dt.replace(fold=1))
- )
-
- if offset_after > offset_before:
- # Skipped time
- if raise_on_unknown_times:
- raise NonExistingTime(dt)
-
- dt += (
- (offset_after - offset_before)
- if dt.fold
- else (offset_before - offset_after)
- )
- elif offset_before > offset_after and raise_on_unknown_times:
- # Repeated time
- raise AmbiguousTime(dt)
-
- return dt.replace(tzinfo=self)
-
- return dt.astimezone(self)
-
- def datetime(
- self,
- year: int,
- month: int,
- day: int,
- hour: int = 0,
- minute: int = 0,
- second: int = 0,
- microsecond: int = 0,
- ) -> datetime_.datetime:
- """
- Return a normalized datetime for the current timezone.
- """
- return self.convert(
- datetime_.datetime(
- year, month, day, hour, minute, second, microsecond, fold=1
- )
- )
-
- def __repr__(self) -> str:
- return f"{self.__class__.__name__}('{self.name}')"
-
-
-class FixedTimezone(datetime_.tzinfo, PendulumTimezone):
- def __init__(self, offset: int, name: str | None = None) -> None:
- sign = "-" if offset < 0 else "+"
-
- minutes = offset / 60
- hour, minute = divmod(abs(int(minutes)), 60)
-
- if not name:
- name = f"{sign}{hour:02d}:{minute:02d}"
-
- self._name = name
- self._offset = offset
- self._utcoffset = datetime_.timedelta(seconds=offset)
-
- @property
- def name(self) -> str:
- return self._name
-
- def convert(
- self, dt: datetime_.datetime, raise_on_unknown_times: bool = False
- ) -> datetime_.datetime:
- if dt.tzinfo is None:
- return dt.__class__(
- dt.year,
- dt.month,
- dt.day,
- dt.hour,
- dt.minute,
- dt.second,
- dt.microsecond,
- tzinfo=self,
- fold=0,
- )
-
- return dt.astimezone(self)
-
- def datetime(
- self,
- year: int,
- month: int,
- day: int,
- hour: int = 0,
- minute: int = 0,
- second: int = 0,
- microsecond: int = 0,
- ) -> datetime_.datetime:
- return self.convert(
- datetime_.datetime(
- year, month, day, hour, minute, second, microsecond, fold=1
- )
- )
-
- @property
- def offset(self) -> int:
- return self._offset
-
- def utcoffset(self, dt: datetime_.datetime | None) -> datetime_.timedelta:
- return self._utcoffset
-
- def dst(self, dt: datetime_.datetime | None) -> datetime_.timedelta:
- return datetime_.timedelta()
-
- def fromutc(self, dt: datetime_.datetime) -> datetime_.datetime:
- # Use the stdlib datetime's add method to avoid infinite recursion
- return (datetime_.datetime.__add__(dt, self._utcoffset)).replace(tzinfo=self)
-
- def tzname(self, dt: datetime_.datetime | None) -> str | None:
- return self._name
-
- def __getinitargs__(self) -> tuple[int, str]:
- return self._offset, self._name
-
- def __repr__(self) -> str:
- name = ""
- if self._name:
- name = f', name="{self._name}"'
-
- return f"{self.__class__.__name__}({self._offset}{name})"
-
-
-UTC = Timezone("UTC")
diff --git a/pendulum/utils/__init__.py b/pendulum/utils/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/pendulum/utils/__init__.py
+++ /dev/null
diff --git a/pendulum/utils/_compat.py b/pendulum/utils/_compat.py
deleted file mode 100644
index 8f32f9e..0000000
--- a/pendulum/utils/_compat.py
+++ /dev/null
@@ -1,13 +0,0 @@
-from __future__ import annotations
-
-import sys
-
-PYPY = hasattr(sys, "pypy_version_info")
-PY38 = sys.version_info[:2] >= (3, 8)
-
-try:
- from backports import zoneinfo
-except ImportError:
- import zoneinfo # type: ignore[no-redef]
-
-__all__ = ["zoneinfo"]