summaryrefslogtreecommitdiffstats
path: root/pendulum/__init__.py
diff options
context:
space:
mode:
Diffstat (limited to 'pendulum/__init__.py')
-rw-r--r--pendulum/__init__.py678
1 files changed, 363 insertions, 315 deletions
diff --git a/pendulum/__init__.py b/pendulum/__init__.py
index a85ed88..4491244 100644
--- a/pendulum/__init__.py
+++ b/pendulum/__init__.py
@@ -1,315 +1,363 @@
-from __future__ import absolute_import
-
-import datetime as _datetime
-
-from typing import Optional
-from typing import Union
-
-from .__version__ import __version__
-from .constants import DAYS_PER_WEEK
-from .constants import FRIDAY
-from .constants import HOURS_PER_DAY
-from .constants import MINUTES_PER_HOUR
-from .constants import MONDAY
-from .constants import MONTHS_PER_YEAR
-from .constants import SATURDAY
-from .constants import SECONDS_PER_DAY
-from .constants import SECONDS_PER_HOUR
-from .constants import SECONDS_PER_MINUTE
-from .constants import SUNDAY
-from .constants import THURSDAY
-from .constants import TUESDAY
-from .constants import WEDNESDAY
-from .constants import WEEKS_PER_YEAR
-from .constants import YEARS_PER_CENTURY
-from .constants import YEARS_PER_DECADE
-from .date import Date
-from .datetime import DateTime
-from .duration import Duration
-from .formatting import Formatter
-from .helpers import format_diff
-from .helpers import get_locale
-from .helpers import get_test_now
-from .helpers import has_test_now
-from .helpers import locale
-from .helpers import set_locale
-from .helpers import set_test_now
-from .helpers import test
-from .helpers import week_ends_at
-from .helpers import week_starts_at
-from .parser import parse
-from .period import Period
-from .time import Time
-from .tz import POST_TRANSITION
-from .tz import PRE_TRANSITION
-from .tz import TRANSITION_ERROR
-from .tz import UTC
-from .tz import local_timezone
-from .tz import set_local_timezone
-from .tz import test_local_timezone
-from .tz import timezone
-from .tz import timezones
-from .tz.timezone import Timezone as _Timezone
-from .utils._compat import _HAS_FOLD
-
-
-_TEST_NOW = None # type: Optional[DateTime]
-_LOCALE = "en"
-_WEEK_STARTS_AT = MONDAY
-_WEEK_ENDS_AT = SUNDAY
-
-_formatter = Formatter()
-
-
-def _safe_timezone(obj):
- # type: (Optional[Union[str, float, _datetime.tzinfo, _Timezone]]) -> _Timezone
- """
- Creates a timezone instance
- from a string, Timezone, TimezoneInfo or integer offset.
- """
- if isinstance(obj, _Timezone):
- 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):
- # pytz
- if hasattr(obj, "localize"):
- obj = obj.zone
- elif obj.tzname(None) == "UTC":
- return UTC
- else:
- offset = obj.utcoffset(None)
-
- if offset is None:
- offset = _datetime.timedelta(0)
-
- obj = int(offset.total_seconds())
-
- return timezone(obj)
-
-
-# Public API
-def datetime(
- year, # type: int
- month, # type: int
- day, # type: int
- hour=0, # type: int
- minute=0, # type: int
- second=0, # type: int
- microsecond=0, # type: int
- tz=UTC, # type: Optional[Union[str, float, _Timezone]]
- dst_rule=POST_TRANSITION, # type: str
-): # type: (...) -> DateTime
- """
- Creates a new DateTime instance from a specific date and time.
- """
- if tz is not None:
- tz = _safe_timezone(tz)
-
- if not _HAS_FOLD:
- dt = naive(year, month, day, hour, minute, second, microsecond)
- else:
- dt = _datetime.datetime(year, month, day, hour, minute, second, microsecond)
- if tz is not None:
- dt = tz.convert(dt, dst_rule=dst_rule)
-
- return DateTime(
- dt.year,
- dt.month,
- dt.day,
- dt.hour,
- dt.minute,
- dt.second,
- dt.microsecond,
- tzinfo=dt.tzinfo,
- fold=dt.fold,
- )
-
-
-def local(
- year, month, day, hour=0, minute=0, second=0, microsecond=0
-): # type: (int, int, int, int, int, int, int) -> DateTime
- """
- Return a DateTime in the local timezone.
- """
- return datetime(
- year, month, day, hour, minute, second, microsecond, tz=local_timezone()
- )
-
-
-def naive(
- year, month, day, hour=0, minute=0, second=0, microsecond=0
-): # type: (int, int, int, int, int, int, int) -> DateTime
- """
- Return a naive DateTime.
- """
- return DateTime(year, month, day, hour, minute, second, microsecond)
-
-
-def date(year, month, day): # type: (int, int, int) -> Date
- """
- Create a new Date instance.
- """
- return Date(year, month, day)
-
-
-def time(hour, minute=0, second=0, microsecond=0): # type: (int, int, int, int) -> Time
- """
- Create a new Time instance.
- """
- return Time(hour, minute, second, microsecond)
-
-
-def instance(
- dt, tz=UTC
-): # type: (_datetime.datetime, Optional[Union[str, _Timezone]]) -> 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
-
- # Checking for pytz/tzinfo
- if isinstance(tz, _datetime.tzinfo) and not isinstance(tz, _Timezone):
- # pytz
- if hasattr(tz, "localize") and tz.zone:
- tz = tz.zone
- else:
- # We have no sure way to figure out
- # the timezone name, we fallback
- # on a fixed offset
- tz = tz.utcoffset(dt).total_seconds() / 3600
-
- return datetime(
- dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond, tz=tz
- )
-
-
-def now(tz=None): # type: (Optional[Union[str, _Timezone]]) -> DateTime
- """
- Get a DateTime instance for the current date and time.
- """
- if has_test_now():
- test_instance = get_test_now()
- _tz = _safe_timezone(tz)
-
- if tz is not None and _tz != test_instance.timezone:
- test_instance = test_instance.in_tz(_tz)
-
- return test_instance
-
- 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 = _safe_timezone(tz)
- dt = tz.convert(dt)
-
- return DateTime(
- dt.year,
- dt.month,
- dt.day,
- dt.hour,
- dt.minute,
- dt.second,
- dt.microsecond,
- tzinfo=dt.tzinfo,
- fold=dt.fold if _HAS_FOLD else 0,
- )
-
-
-def today(tz="local"): # type: (Union[str, _Timezone]) -> DateTime
- """
- Create a DateTime instance for today.
- """
- return now(tz).start_of("day")
-
-
-def tomorrow(tz="local"): # type: (Union[str, _Timezone]) -> DateTime
- """
- Create a DateTime instance for today.
- """
- return today(tz).add(days=1)
-
-
-def yesterday(tz="local"): # type: (Union[str, _Timezone]) -> DateTime
- """
- Create a DateTime instance for today.
- """
- return today(tz).subtract(days=1)
-
-
-def from_format(
- string, fmt, tz=UTC, locale=None, # noqa
-): # type: (str, str, Union[str, _Timezone], Optional[str]) -> DateTime
- """
- Creates a DateTime instance from a specific format.
- """
- parts = _formatter.parse(string, fmt, now(), locale=locale)
- if parts["tz"] is None:
- parts["tz"] = tz
-
- return datetime(**parts)
-
-
-def from_timestamp(
- timestamp, tz=UTC
-): # type: (Union[int, float], Union[str, _Timezone]) -> 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=0, # type: float
- seconds=0, # type: float
- microseconds=0, # type: float
- milliseconds=0, # type: float
- minutes=0, # type: float
- hours=0, # type: float
- weeks=0, # type: float
- years=0, # type: float
- months=0, # type: float
-): # type: (...) -> 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 period(start, end, absolute=False): # type: (DateTime, DateTime, bool) -> Period
- """
- Create a Period instance.
- """
- return Period(start, end, absolute=absolute)
+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",
+]