Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unify datetime imports #945

Merged
merged 2 commits into from
Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
247 changes: 157 additions & 90 deletions babel/dates.py

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions babel/localtime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

import sys
import time
from datetime import datetime, timedelta, tzinfo
import datetime
from threading import RLock

if sys.platform == 'win32':
Expand All @@ -23,34 +23,34 @@
_cached_tz = None
_cache_lock = RLock()

STDOFFSET = timedelta(seconds=-time.timezone)
STDOFFSET = datetime.timedelta(seconds=-time.timezone)
if time.daylight:
DSTOFFSET = timedelta(seconds=-time.altzone)
DSTOFFSET = datetime.timedelta(seconds=-time.altzone)
else:
DSTOFFSET = STDOFFSET

DSTDIFF = DSTOFFSET - STDOFFSET
ZERO = timedelta(0)
ZERO = datetime.timedelta(0)


class _FallbackLocalTimezone(tzinfo):
class _FallbackLocalTimezone(datetime.tzinfo):

def utcoffset(self, dt: datetime) -> timedelta:
def utcoffset(self, dt: datetime.datetime) -> datetime.timedelta:
if self._isdst(dt):
return DSTOFFSET
else:
return STDOFFSET

def dst(self, dt: datetime) -> timedelta:
def dst(self, dt: datetime.datetime) -> datetime.timedelta:
if self._isdst(dt):
return DSTDIFF
else:
return ZERO

def tzname(self, dt: datetime) -> str:
def tzname(self, dt: datetime.datetime) -> str:
return time.tzname[self._isdst(dt)]

def _isdst(self, dt: datetime) -> bool:
def _isdst(self, dt: datetime.datetime) -> bool:
tt = (dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.weekday(), 0, -1)
Expand All @@ -59,7 +59,7 @@ def _isdst(self, dt: datetime) -> bool:
return tt.tm_isdst > 0


def get_localzone() -> tzinfo:
def get_localzone() -> datetime.tzinfo:
"""Returns the current underlying local timezone object.
Generally this function does not need to be used, it's a
better idea to use the :data:`LOCALTZ` singleton instead.
Expand Down
6 changes: 3 additions & 3 deletions babel/localtime/_unix.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import os
import re

from datetime import tzinfo
import datetime

from babel.localtime._helpers import (
_get_tzinfo_from_file,
_get_tzinfo_or_raise,
_get_tzinfo,
)

def _tz_from_env(tzenv: str) -> tzinfo:
def _tz_from_env(tzenv: str) -> datetime.tzinfo:
if tzenv[0] == ':':
tzenv = tzenv[1:]

Expand All @@ -21,7 +21,7 @@ def _tz_from_env(tzenv: str) -> tzinfo:
return _get_tzinfo_or_raise(tzenv)


def _get_localzone(_root: str = '/') -> tzinfo:
def _get_localzone(_root: str = '/') -> datetime.tzinfo:
"""Tries to find the local timezone configuration.
This method prefers finding the timezone name and passing that to
zoneinfo or pytz, over passing in the localtime file, as in the later
Expand Down
4 changes: 2 additions & 2 deletions babel/localtime/_win32.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
except ImportError:
winreg = None

from datetime import tzinfo
import datetime
from babel.core import get_global
from babel.localtime._helpers import _get_tzinfo_or_raise
from typing import Any, Dict, cast
Expand Down Expand Up @@ -89,7 +89,7 @@ def get_localzone_name() -> str:
return timezone


def _get_localzone() -> tzinfo:
def _get_localzone() -> datetime.tzinfo:
if winreg is None:
raise LookupError(
'Runtime support not available')
Expand Down
21 changes: 11 additions & 10 deletions babel/messages/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from collections import OrderedDict
from collections.abc import Generator, Iterable, Iterator
from datetime import datetime, time as time_
import datetime
from difflib import get_close_matches
from email import message_from_string
from copy import copy
Expand Down Expand Up @@ -45,10 +45,10 @@
''', re.VERBOSE)


def _parse_datetime_header(value: str) -> datetime:
def _parse_datetime_header(value: str) -> datetime.datetime:
match = re.match(r'^(?P<datetime>.*?)(?P<tzoffset>[+-]\d{4})?$', value)

dt = datetime.strptime(match.group('datetime'), '%Y-%m-%d %H:%M')
dt = datetime.datetime.strptime(match.group('datetime'), '%Y-%m-%d %H:%M')

# Separate the offset into a sign component, hours, and # minutes
tzoffset = match.group('tzoffset')
Expand Down Expand Up @@ -261,8 +261,8 @@ def __init__(
version: str | None = None,
copyright_holder: str | None = None,
msgid_bugs_address: str | None = None,
creation_date: datetime | str | None = None,
revision_date: datetime | time_ | float | str | None = None,
creation_date: datetime.datetime | str | None = None,
revision_date: datetime.datetime | datetime.time | float | str | None = None,
last_translator: str | None = None,
language_team: str | None = None,
charset: str | None = None,
Expand Down Expand Up @@ -306,13 +306,13 @@ def __init__(
self.charset = charset or 'utf-8'

if creation_date is None:
creation_date = datetime.now(LOCALTZ)
elif isinstance(creation_date, datetime) and not creation_date.tzinfo:
creation_date = datetime.datetime.now(LOCALTZ)
elif isinstance(creation_date, datetime.datetime) and not creation_date.tzinfo:
creation_date = creation_date.replace(tzinfo=LOCALTZ)
self.creation_date = creation_date
if revision_date is None:
revision_date = 'YEAR-MO-DA HO:MI+ZONE'
elif isinstance(revision_date, datetime) and not revision_date.tzinfo:
elif isinstance(revision_date, datetime.datetime) and not revision_date.tzinfo:
revision_date = revision_date.replace(tzinfo=LOCALTZ)
self.revision_date = revision_date
self.fuzzy = fuzzy
Expand Down Expand Up @@ -354,7 +354,7 @@ def _get_locale_identifier(self) -> str | None:

def _get_header_comment(self) -> str:
comment = self._header_comment
year = datetime.now(LOCALTZ).strftime('%Y')
year = datetime.datetime.now(LOCALTZ).strftime('%Y')
if hasattr(self.revision_date, 'strftime'):
year = self.revision_date.strftime('%Y')
comment = comment.replace('PROJECT', self.project) \
Expand Down Expand Up @@ -409,7 +409,7 @@ def _get_mime_headers(self) -> list[tuple[str, str]]:
headers.append(('POT-Creation-Date',
format_datetime(self.creation_date, 'yyyy-MM-dd HH:mmZ',
locale='en')))
if isinstance(self.revision_date, (datetime, time_, int, float)):
if isinstance(self.revision_date, (datetime.datetime, datetime.time, int, float)):
headers.append(('PO-Revision-Date',
format_datetime(self.revision_date,
'yyyy-MM-dd HH:mmZ', locale='en')))
Expand Down Expand Up @@ -481,6 +481,7 @@ def _set_mime_headers(self, headers: Iterable[tuple[str, str]]) -> None:
Here's an example of the output for such a catalog template:

>>> from babel.dates import UTC
>>> from datetime import datetime
>>> created = datetime(1990, 4, 1, 15, 30, tzinfo=UTC)
>>> catalog = Catalog(project='Foobar', version='1.0',
... creation_date=created)
Expand Down
6 changes: 3 additions & 3 deletions babel/messages/frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import tempfile
from collections import OrderedDict
from configparser import RawConfigParser
from datetime import datetime
import datetime
from io import StringIO

from babel import __version__ as VERSION
Expand Down Expand Up @@ -662,7 +662,7 @@ def run(self):
catalog = read_po(infile, locale=self.locale)

catalog.locale = self._locale
catalog.revision_date = datetime.now(LOCALTZ)
catalog.revision_date = datetime.datetime.now(LOCALTZ)
catalog.fuzzy = False

with open(self.output_file, 'wb') as outfile:
Expand Down Expand Up @@ -818,7 +818,7 @@ def run(self):
catalog = read_po(infile, locale=self.locale)

catalog.locale = self._locale
catalog.revision_date = datetime.now(LOCALTZ)
catalog.revision_date = datetime.datetime.now(LOCALTZ)
catalog.fuzzy = False

with open(filename, 'wb') as outfile:
Expand Down
24 changes: 12 additions & 12 deletions babel/numbers.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import re
from typing import TYPE_CHECKING, Any, overload
import warnings
from datetime import date as date_, datetime as datetime_
import datetime

from babel.core import Locale, default_locale, get_global
from babel.localedata import LocaleDataDict
Expand Down Expand Up @@ -200,8 +200,8 @@ def get_currency_unit_pattern(
@overload
def get_territory_currencies(
territory: str,
start_date: date_ | None = ...,
end_date: date_ | None = ...,
start_date: datetime.date | None = ...,
end_date: datetime.date | None = ...,
tender: bool = ...,
non_tender: bool = ...,
include_details: Literal[False] = ...,
Expand All @@ -212,8 +212,8 @@ def get_territory_currencies(
@overload
def get_territory_currencies(
territory: str,
start_date: date_ | None = ...,
end_date: date_ | None = ...,
start_date: datetime.date | None = ...,
end_date: datetime.date | None = ...,
tender: bool = ...,
non_tender: bool = ...,
include_details: Literal[True] = ...,
Expand All @@ -223,8 +223,8 @@ def get_territory_currencies(

def get_territory_currencies(
territory: str,
start_date: date_ | None = None,
end_date: date_ | None = None,
start_date: datetime.date | None = None,
end_date: datetime.date | None = None,
tender: bool = True,
non_tender: bool = False,
include_details: bool = False,
Expand Down Expand Up @@ -280,12 +280,12 @@ def get_territory_currencies(
"""
currencies = get_global('territory_currencies')
if start_date is None:
start_date = date_.today()
elif isinstance(start_date, datetime_):
start_date = datetime.date.today()
elif isinstance(start_date, datetime.datetime):
start_date = start_date.date()
if end_date is None:
end_date = start_date
elif isinstance(end_date, datetime_):
elif isinstance(end_date, datetime.datetime):
end_date = end_date.date()

curs = currencies.get(territory.upper(), ())
Expand All @@ -298,9 +298,9 @@ def _is_active(start, end):
result = []
for currency_code, start, end, is_tender in curs:
if start:
start = date_(*start)
start = datetime.date(*start)
if end:
end = date_(*end)
end = datetime.date(*end)
if ((is_tender and tender) or
(not is_tender and non_tender)) and _is_active(start, end):
if include_details:
Expand Down
33 changes: 19 additions & 14 deletions babel/support.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,8 @@
import gettext
import locale
import os
import datetime
from collections.abc import Iterator
from datetime import (
date as _date,
datetime as _datetime,
time as _time,
timedelta as _timedelta,
tzinfo
)
from typing import TYPE_CHECKING, Any, Callable

from babel.core import Locale
Expand Down Expand Up @@ -52,7 +46,7 @@ class Format:
u'1.234'
"""

def __init__(self, locale: Locale | str, tzinfo: tzinfo | None = None) -> None:
def __init__(self, locale: Locale | str, tzinfo: datetime.tzinfo | None = None) -> None:
"""Initialize the formatter.

:param locale: the locale identifier or `Locale` instance
Expand All @@ -61,7 +55,11 @@ def __init__(self, locale: Locale | str, tzinfo: tzinfo | None = None) -> None:
self.locale = Locale.parse(locale)
self.tzinfo = tzinfo

def date(self, date: _date | None = None, format: _PredefinedTimeFormat | str = 'medium') -> str:
def date(
self,
date: datetime.date | None = None,
format: _PredefinedTimeFormat | str = 'medium',
) -> str:
"""Return a date formatted according to the given pattern.

>>> from datetime import date
Expand All @@ -71,18 +69,25 @@ def date(self, date: _date | None = None, format: _PredefinedTimeFormat | str =
"""
return format_date(date, format, locale=self.locale)

def datetime(self, datetime: _date | None = None, format: _PredefinedTimeFormat | str = 'medium') -> str:
def datetime(
self,
datetime: datetime.date | None = None,
format: _PredefinedTimeFormat | str = 'medium',
) -> str:
"""Return a date and time formatted according to the given pattern.

>>> from datetime import datetime
>>> fmt = Format('en_US', tzinfo=get_timezone('US/Eastern'))
>>> fmt.datetime(datetime(2007, 4, 1, 15, 30))
u'Apr 1, 2007, 11:30:00 AM'
"""
return format_datetime(datetime, format, tzinfo=self.tzinfo,
locale=self.locale)
return format_datetime(datetime, format, tzinfo=self.tzinfo, locale=self.locale)

def time(self, time: _time | _datetime | None = None, format: _PredefinedTimeFormat | str = 'medium') -> str:
def time(
self,
time: datetime.time | datetime.datetime | None = None,
format: _PredefinedTimeFormat | str = 'medium',
) -> str:
"""Return a time formatted according to the given pattern.

>>> from datetime import datetime
Expand All @@ -94,7 +99,7 @@ def time(self, time: _time | _datetime | None = None, format: _PredefinedTimeFor

def timedelta(
self,
delta: _timedelta | int,
delta: datetime.timedelta | int,
granularity: Literal["year", "month", "week", "day", "hour", "minute", "second"] = "second",
threshold: float = 0.85,
format: Literal["narrow", "short", "medium", "long"] = "long",
Expand Down
12 changes: 6 additions & 6 deletions babel/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from babel import localtime, dates

from collections.abc import Generator, Iterable
from datetime import datetime as datetime_, timedelta, tzinfo
import datetime
from typing import IO, Any, TypeVar

missing = object()
Expand Down Expand Up @@ -225,12 +225,12 @@ def wraptext(text: str, width: int = 70, initial_indent: str = '', subsequent_in
odict = collections.OrderedDict


class FixedOffsetTimezone(tzinfo):
class FixedOffsetTimezone(datetime.tzinfo):
"""Fixed offset in minutes east from UTC."""

def __init__(self, offset: float, name: str | None = None) -> None:

self._offset = timedelta(minutes=offset)
self._offset = datetime.timedelta(minutes=offset)
if name is None:
name = 'Etc/GMT%+d' % offset
self.zone = name
Expand All @@ -241,13 +241,13 @@ def __str__(self) -> str:
def __repr__(self) -> str:
return f'<FixedOffset "{self.zone}" {self._offset}>'

def utcoffset(self, dt: datetime_) -> timedelta:
def utcoffset(self, dt: datetime.datetime) -> datetime.timedelta:
return self._offset

def tzname(self, dt: datetime_) -> str:
def tzname(self, dt: datetime.datetime) -> str:
return self.zone

def dst(self, dt: datetime_) -> timedelta:
def dst(self, dt: datetime.datetime) -> datetime.timedelta:
return ZERO


Expand Down