Skip to content
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
7 changes: 5 additions & 2 deletions babel/messages/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from babel.core import Locale, UnknownLocaleError
from babel.dates import format_datetime
from babel.messages.plurals import get_plural
from babel.util import LOCALTZ, FixedOffsetTimezone, _cmp, distinct
from babel.util import LOCALTZ, _cmp, distinct

if TYPE_CHECKING:
from typing_extensions import TypeAlias
Expand Down Expand Up @@ -118,7 +118,10 @@ def _parse_datetime_header(value: str) -> datetime.datetime:
net_mins_offset *= plus_minus

# Create an offset object
tzoffset = FixedOffsetTimezone(net_mins_offset)
tzoffset = datetime.timezone(
offset=datetime.timedelta(minutes=net_mins_offset),
name=f'Etc/GMT{net_mins_offset:+d}',
)

# Store the offset in a datetime object
dt = dt.replace(tzinfo=tzoffset)
Expand Down
14 changes: 12 additions & 2 deletions babel/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,20 @@ def wraptext(text: str, width: int = 70, initial_indent: str = '', subsequent_in


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

def __init__(self, offset: float, name: str | None = None) -> None:
DEPRECATED: Use the standard library `datetime.timezone` instead.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Drive-by review, I'll try to review this thoroughly later) We could also add a module getter that raises a deprecation warning when this class is accessed/imported (or even when it's instantiated maybe?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, why not!

"""
# TODO (Babel 3.x): Remove this class

def __init__(self, offset: float, name: str | None = None) -> None:
warnings.warn(
"`FixedOffsetTimezone` is deprecated and will be removed in a future version of Babel. "
"Use the standard library `datetime.timezone` class.",
DeprecationWarning,
stacklevel=2,
)
self._offset = datetime.timedelta(minutes=offset)
if name is None:
name = 'Etc/GMT%+d' % offset
Expand Down
4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,7 @@ markers = [
]
filterwarnings = [
# The doctest for format_number would raise this, but we don't really want to see it.
"ignore:babel.numbers.format_decimal:DeprecationWarning"
"ignore:babel.numbers.format_decimal:DeprecationWarning",
# FixedOffsetTimezone is still being tested, but we don't want to see the deprecation warning.
"ignore:.*FixedOffsetTimezone:DeprecationWarning",
]
22 changes: 18 additions & 4 deletions tests/messages/test_catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

import copy
import datetime
import pickle
import unittest
from io import StringIO

Expand Down Expand Up @@ -524,10 +525,10 @@ def test_catalog_update():

def test_datetime_parsing():
val1 = catalog._parse_datetime_header('2006-06-28 23:24+0200')
assert val1.year == 2006
assert val1.month == 6
assert val1.day == 28
assert val1.tzinfo.zone == 'Etc/GMT+120'
assert val1.timetuple()[:5] == (2006, 6, 28, 23, 24)
assert val1.utctimetuple()[:5] == (2006, 6, 28, 21, 24)
assert val1.tzinfo.tzname(None) == 'Etc/GMT+120'
assert val1 == datetime.datetime(2006, 6, 28, 21, 24, tzinfo=UTC)

val2 = catalog._parse_datetime_header('2006-06-28 23:24')
assert val2.year == 2006
Expand Down Expand Up @@ -562,3 +563,16 @@ def test_update_catalog_comments():

# Auto comments will be obliterated here
assert all(message.user_comments for message in catalog if message.id)


def test_catalog_tz_pickleable():
"""
Test that catalogs with timezoned times are pickleable.
This would previously fail with `FixedOffsetTimezone.__init__() missing 1 required positional argument: 'offset'`
when trying to load the pickled data.
"""
pickle.loads(pickle.dumps(pofile.read_po(StringIO(r"""
msgid ""
msgstr ""
"POT-Creation-Date: 2007-04-01 15:30+0200\n"
"""))))
Loading