diff --git a/.gitignore b/.gitignore index 9d6052a..b0426c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ /pyRFC3339-1.0.tar.gz /pyRFC3339-1.1.tar.gz -/pyrfc3339-2.0.1.tar.gz diff --git a/pyrfc3339-use-pytest-in-tests.patch b/pyrfc3339-use-pytest-in-tests.patch deleted file mode 100644 index c216f53..0000000 --- a/pyrfc3339-use-pytest-in-tests.patch +++ /dev/null @@ -1,195 +0,0 @@ -commit a863d1a3c90944b90685680af4dad5d8c7dbc0da -Author: Matthew Davis -Date: Fri Jan 28 16:42:42 2022 -0500 - - Converted tests from python-nose to pytest - -diff --git a/tests.py b/tests.py -index 831daab..d4c7622 100644 ---- a/tests.py -+++ b/tests.py -@@ -8,12 +8,11 @@ from copy import deepcopy - - from pyrfc3339 import generate, parse - from pyrfc3339.utils import timezone -+import unittest -+import pytest - import pytz - --from nose.tools import eq_, raises -- -- --class TestCore(): -+class TestCore(unittest.TestCase): - ''' - This test suite contains tests to address cases not tested in the doctests, - as well as additional tests for end-to-end verification. -@@ -24,8 +23,11 @@ class TestCore(): - Test rounding of timezone values to the nearest second. - - ''' -- eq_(timezone(5429), '+01:30') -- eq_(timezone(5431), '+01:31') -+ if not timezone(5429) == '+01:30': -+ raise AssertionError("%r != %r" % (timezone(5429), '+01:30')) -+ -+ if not timezone(5431) == '+01:31': -+ raise AssertionError("%r != %r" % (timezone(5431), '+01:31')) - - def test_zero_offset(self): - ''' -@@ -34,11 +36,13 @@ class TestCore(): - ''' - timestamp = '2009-01-01T10:02:03+00:00' - dt = parse(timestamp) -- eq_(dt.tzinfo, pytz.utc) -+ if not dt.tzinfo == pytz.utc: -+ raise AssertionError("%r != %r" % (dt.tzinfo, pytz.utc)) - - timestamp = '2009-01-01T10:02:03-00:00' - dt = parse(timestamp) -- eq_(dt.tzinfo, pytz.utc) -+ if not dt.tzinfo == pytz.utc: -+ raise AssertionError("%r != %r" % (dt.tzinfo, pytz.utc)) - - def test_deepcopy(self): - ''' -@@ -56,7 +60,8 @@ class TestCore(): - ''' - timestamp = '2009-01-01T10:02:03.25Z' - dt = parse(timestamp) -- eq_(dt.microsecond, 250000) -+ if not dt.microsecond == 250000: -+ raise AssertionError("%r != %r" % (dt.microsecond, 250000)) - - def test_generate_microseconds(self): - ''' -@@ -65,7 +70,8 @@ class TestCore(): - ''' - dt = datetime(2009, 1, 1, 10, 2, 3, 500000, pytz.utc) - timestamp = generate(dt, microseconds=True) -- eq_(timestamp, '2009-01-01T10:02:03.500000Z') -+ if not timestamp == '2009-01-01T10:02:03.500000Z': -+ raise AssertionError("%r != %r" % (timestamp, '2009-01-01T10:02:03.500000Z')) - - def test_mixed_case(self): - ''' -@@ -76,7 +82,8 @@ class TestCore(): - dt1 = parse('2009-01-01t10:01:02z') - dt2 = datetime(2009, 1, 1, 10, 1, 2, tzinfo=pytz.utc) - -- eq_(dt1, dt2) -+ if not dt1 == dt2: -+ raise AssertionError("%r != %r" % (dt1, dt2)) - - def test_parse_naive_utc(self): - ''' -@@ -84,15 +91,17 @@ class TestCore(): - - ''' - dt1 = parse('2009-01-01T10:01:02Z', produce_naive=True) -- eq_(dt1.tzinfo, None) -+ if not dt1.tzinfo == None: -+ raise AssertionError("%r != %r" % (dt1.tzinfo, None)) - -- @raises(ValueError) - def test_parse_naive_local(self): - ''' - Test that parsing a local timestamp to a naive datetime fails. - - ''' -- parse('2009-01-01T10:01:02-04:00', produce_naive=True) -+ with self.assertRaises(ValueError) as context: -+ parse('2009-01-01T10:01:02-04:00', produce_naive=True) -+ - - def test_generate_utc_parse_utc(self): - ''' -@@ -103,7 +112,8 @@ class TestCore(): - dt1 = dt1.replace(tzinfo=pytz.utc) - - dt2 = parse(generate(dt1, microseconds=True)) -- eq_(dt1, dt2) -+ if not dt1 == dt2: -+ raise AssertionError("%r != %r" % (dt1, dt2)) - - def test_generate_local_parse_local(self): - ''' -@@ -113,7 +123,8 @@ class TestCore(): - eastern = pytz.timezone('US/Eastern') - dt1 = eastern.localize(datetime.utcnow()) - dt2 = parse(generate(dt1, utc=False, microseconds=True), utc=False) -- eq_(dt1, dt2) -+ if not dt1 == dt2: -+ raise AssertionError("%r != %r" % (dt1, dt2)) - - def test_generate_local_parse_utc(self): - ''' -@@ -123,10 +134,12 @@ class TestCore(): - eastern = pytz.timezone('US/Eastern') - dt1 = eastern.localize(datetime.utcnow()) - dt2 = parse(generate(dt1, utc=False, microseconds=True)) -- eq_(dt1, dt2) -+ if not dt1 == dt2: -+ raise AssertionError("%r != %r" % (dt1, dt2)) - - --class TestExhaustiveRoundtrip(): -+@pytest.mark.parametrize('tz_name', pytz.all_timezones) -+class TestExhaustiveRoundtrip: - ''' - This test suite exhaustively tests parsing and generation by generating - a local RFC 3339 timestamp for every timezone supported by pytz, -@@ -135,36 +148,32 @@ class TestExhaustiveRoundtrip(): - - slow = True - -- def test_local_roundtrip(self): -- for tz_name in pytz.all_timezones: -- yield self.local_roundtrip, tz_name -- -- def local_roundtrip(self, tz_name): -+ def test_local_roundtrip(self, tz_name): - ''' - Generates a local datetime using the given timezone, - produces a local timestamp from the datetime, parses the timestamp - to a local datetime, and verifies that the two datetimes are equal. - - ''' -- tzinfo = pytz.timezone(tz_name) -- dt1 = tzinfo.localize(datetime.utcnow()) -- timestamp = generate(dt1, utc=False, microseconds=True) -- dt2 = parse(timestamp, utc=False) -- eq_(dt1, dt2) -- -- def test_utc_roundtrip(self): -- for tz_name in pytz.all_timezones: -- yield self.utc_roundtrip, tz_name -+ if not tz_name == 'leapseconds': -+ tzinfo = pytz.timezone(tz_name) -+ dt1 = tzinfo.localize(datetime.utcnow()) -+ timestamp = generate(dt1, utc=False, microseconds=True) -+ dt2 = parse(timestamp, utc=False) -+ if not dt1 == dt2: -+ raise AssertionError("%r != %r" % (dt1, dt2)) - -- def utc_roundtrip(self, tz_name): -+ def test_utc_roundtrip(self, tz_name): - ''' - Generates a local datetime using the given timezone, - produces a local timestamp from the datetime, parses the timestamp - to a UTC datetime, and verifies that the two datetimes are equal. - - ''' -- tzinfo = pytz.timezone(tz_name) -- dt1 = tzinfo.localize(datetime.utcnow()) -- timestamp = generate(dt1, utc=False, microseconds=True) -- dt2 = parse(timestamp) -- eq_(dt1, dt2) -+ if not tz_name == 'leapseconds': -+ tzinfo = pytz.timezone(tz_name) -+ dt1 = tzinfo.localize(datetime.utcnow()) -+ timestamp = generate(dt1, utc=False, microseconds=True) -+ dt2 = parse(timestamp) -+ if not dt1 == dt2: -+ raise AssertionError("%r != %r" % (dt1, dt2)) diff --git a/python-pyrfc3339.spec b/python-pyrfc3339.spec index 8727d46..d5bb68c 100644 --- a/python-pyrfc3339.spec +++ b/python-pyrfc3339.spec @@ -1,118 +1,102 @@ -%global srcname pyrfc3339 +%global srcname pyRFC3339 +%if 0%{?rhel} && (0%{?rhel} <= 7) +%bcond_without python2 +%else +%bcond_with python2 +%endif + +%global py3_prefix python%{python3_pkgversion} Name: python-pyrfc3339 -Version: 2.0.1 -Release: 6%{?dist} +Version: 1.1 +Release: 7%{?dist} Summary: Generate and parse RFC 3339 timestamps License: MIT URL: https://pypi.python.org/pypi/pyRFC3339 Source0: %{pypi_source} # release tarballs do not contain unit tests (pyrfc3339/tests/tests.py) -# https://github.com/kurtraschke/pyRFC3339/blob/master/pyrfc3339/tests/test_all.py -# v2.0.1: git commit 53c2d1587d3a -Source1: https://raw.githubusercontent.com/kurtraschke/pyRFC3339/53c2d1587d3aac1734ddd4d4006a815df2d80f36/pyrfc3339/tests/test_all.py +# https://raw.githubusercontent.com/kurtraschke/pyRFC3339/master/pyrfc3339/tests/tests.py +# v1.1: git commit e30cc155 +Source1: https://raw.githubusercontent.com/kurtraschke/pyRFC3339/e30cc1555adce0ecc7bd65509a2249d47e5a41b4/pyrfc3339/tests/tests.py BuildArch: noarch - -BuildRequires: python3-devel +%if %{with python2} +BuildRequires: python2-devel +BuildRequires: python-setuptools # --- unit tests --- -# Specified manually because upstream release tarballs do not contain unit tests -BuildRequires: python3-pytest +BuildRequires: python-nose +BuildRequires: pytz +%endif + +BuildRequires: %{py3_prefix}-devel +BuildRequires: %{py3_prefix}-setuptools +# --- unit tests --- +BuildRequires: %{py3_prefix}-nose +BuildRequires: %{py3_prefix}-pytz %description This package contains a python library to parse and generate RFC 3339-compliant timestamps using Python datetime.datetime objects. -%package -n python3-pyrfc3339 +%if %{with python2} +%package -n python2-pyrfc3339 +Summary: %{summary} +%{?python_provide:%python_provide python2-pyrfc3339} + +%description -n python2-pyrfc3339 +This package contains a Python 2 library to parse and generate +RFC 3339-compliant timestamps using Python datetime.datetime objects. +%endif + +%package -n %{py3_prefix}-pyrfc3339 Summary: Generate and parse RFC 3339 timestamps %{?python_provide:%python_provide python3-pyrfc3339} -%description -n python3-pyrfc3339 +%description -n %{py3_prefix}-pyrfc3339 This package contains a Python 3 library to parse and generate RFC 3339-compliant timestamps using Python datetime.datetime objects. -%generate_buildrequires -%pyproject_buildrequires %prep -%autosetup -n %{srcname}-%{version} -N -cp -a %{SOURCE1} . +%autosetup -n %{srcname}-%{version} %build -%pyproject_wheel +%if %{with python2} +%py2_build +%endif +%py3_build %install -%pyproject_install -%pyproject_save_files pyrfc3339 +%if %{with python2} +%py2_install +%endif +%py3_install %check -%pytest -v test_all.py +cp -a %{SOURCE1} . +%if %{with python2} +nosetests-2.7 tests.py +%endif +nosetests-%{python3_version} tests.py -%files -n python3-pyrfc3339 -f %{pyproject_files} +%if %{with python2} +%files -n python2-pyrfc3339 %doc README.rst +%license LICENSE.txt +%{python2_sitelib}/pyrfc3339 +%{python2_sitelib}/%{srcname}-%{version}-*.egg-info +%endif + +%files -n %{py3_prefix}-pyrfc3339 +%doc README.rst +%license LICENSE.txt +%{python3_sitelib}/pyrfc3339 +%{python3_sitelib}/%{srcname}-%{version}-*.egg-info + %changelog -* Fri Sep 19 2025 Python Maint - 2.0.1-6 -- Rebuilt for Python 3.14.0rc3 bytecode - -* Fri Aug 15 2025 Python Maint - 2.0.1-5 -- Rebuilt for Python 3.14.0rc2 bytecode - -* Fri Jul 25 2025 Fedora Release Engineering - 2.0.1-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild - -* Mon Jun 02 2025 Python Maint - 2.0.1-3 -- Rebuilt for Python 3.14 - -* Sat Jan 18 2025 Fedora Release Engineering - 2.0.1-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild - -* Fri Jan 03 2025 Felix Schwarz - 2.0.1-1 -- update to 2.0.1 - -* Fri Jul 19 2024 Fedora Release Engineering - 1.1-20 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild - -* Fri Jun 07 2024 Python Maint - 1.1-19 -- Rebuilt for Python 3.13 - -* Fri Jan 26 2024 Fedora Release Engineering - 1.1-18 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Mon Jan 22 2024 Fedora Release Engineering - 1.1-17 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Fri Jul 21 2023 Fedora Release Engineering - 1.1-16 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild - -* Tue Jun 13 2023 Python Maint - 1.1-15 -- Rebuilt for Python 3.12 - -* Fri Jan 20 2023 Fedora Release Engineering - 1.1-14 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild - -* Fri Jul 22 2022 Fedora Release Engineering - 1.1-13 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild - -* Mon Jun 13 2022 Python Maint - 1.1-12 -- Rebuilt for Python 3.11 - -* Thu Apr 07 2022 Matthew Davis - 1.1-11 -- Converted tests from python-nose to pytest -- Removed Python 2 support -- Converted to pyproject macros - -* Fri Jan 21 2022 Fedora Release Engineering - 1.1-10 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild - -* Fri Jul 23 2021 Fedora Release Engineering - 1.1-9 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild - -* Fri Jun 04 2021 Python Maint - 1.1-8 -- Rebuilt for Python 3.10 - * Wed Jan 27 2021 Fedora Release Engineering - 1.1-7 - Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild diff --git a/sources b/sources index bb55905..8423dc9 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (pyrfc3339-2.0.1.tar.gz) = b1c6768842a8fc8917280264e4fa3e2e1223399184bd7639fbb12d3bd4755ea2cadfb291efe2bf1f3b7e89e50fcb1f89a46a9e81a94cca3a5ca0aa8c0b698c69 +SHA512 (pyRFC3339-1.1.tar.gz) = 958b7761fab590aa42bb57a955c5d834441f717796a452b60df21663099dcf2fc046afe60f8157fd0f1edfd95c5e9c9c5349ab10ca4078d210fc63d848496a2f diff --git a/test_all.py b/test_all.py deleted file mode 100644 index ed47f20..0000000 --- a/test_all.py +++ /dev/null @@ -1,155 +0,0 @@ -""" -Test suite for pyRFC3339. - -""" - -import unittest -import zoneinfo -from datetime import datetime, timezone -from zoneinfo import ZoneInfo - -from pyrfc3339 import generate, parse - - -class TestCore(unittest.TestCase): - """ - This test case contains tests to address cases not tested in the doctests, - as well as additional tests for end-to-end verification. - - """ - - def test_zero_offset(self) -> None: - """ - Both +00:00 and -00:00 are equivalent to the offset 'Z' (UTC). - - """ - timestamp = "2009-01-01T10:02:03+00:00" - dt = parse(timestamp) - self.assertEqual(dt.tzinfo, timezone.utc) - - timestamp = "2009-01-01T10:02:03-00:00" - dt = parse(timestamp) - self.assertEqual(dt.tzinfo, timezone.utc) - - def test_parse_microseconds(self) -> None: - """ - Test parsing timestamps with microseconds. - - """ - timestamp = "2009-01-01T10:02:03.25Z" - dt = parse(timestamp) - self.assertEqual(dt.microsecond, 250000) - - def test_generate_microseconds(self) -> None: - """ - Test generating timestamps with microseconds. - - """ - dt = datetime(2009, 1, 1, 10, 2, 3, 500000, tzinfo=timezone.utc) - timestamp = generate(dt, microseconds=True) - self.assertEqual(timestamp, "2009-01-01T10:02:03.500000Z") - - def test_mixed_case(self) -> None: - """ - Timestamps may use either 'T' or 't' and either 'Z' or 'z' - according to :RFC:`3339`. - - """ - dt1 = parse("2009-01-01t10:01:02z") - dt2 = datetime(2009, 1, 1, 10, 1, 2, tzinfo=timezone.utc) - - self.assertEqual(dt1, dt2) - - def test_parse_naive_utc(self) -> None: - """ - Test parsing a UTC timestamp to a naive datetime. - - """ - dt1 = parse("2009-01-01T10:01:02Z", produce_naive=True) - self.assertEqual(dt1.tzinfo, None) - - def test_parse_naive_local(self) -> None: - """ - Test that parsing a local timestamp to a naive datetime fails. - - """ - with self.assertRaises(ValueError): - parse("2009-01-01T10:01:02-04:00", produce_naive=True) - - def test_generate_utc_parse_utc(self) -> None: - """ - Generate a UTC timestamp and parse it into a UTC datetime. - - """ - dt1 = datetime.now(timezone.utc) - - dt2 = parse(generate(dt1, microseconds=True)) - self.assertEqual(dt1, dt2) - - def test_generate_local_parse_local(self) -> None: - """ - Generate a local timestamp and parse it into a local datetime. - - """ - eastern = ZoneInfo("US/Eastern") - dt1 = datetime.now(eastern) - dt2 = parse(generate(dt1, utc=False, microseconds=True), utc=False) - self.assertEqual(dt1, dt2) - - def test_generate_local_parse_utc(self) -> None: - """ - Generate a local timestamp and parse it into a UTC datetime. - - """ - eastern = ZoneInfo("US/Eastern") - dt1 = datetime.now(eastern) - dt2 = parse(generate(dt1, utc=False, microseconds=True)) - self.assertEqual(dt1, dt2) - - @unittest.skip("fails due to python/cpython#120713") - def test_three_digit_year(self) -> None: - dt = datetime(999, 1, 1, 0, 0, 0, tzinfo=timezone.utc) - self.assertEqual(generate(dt), "0999-01-01T00:00:00Z") - - -class TestExhaustiveRoundtrip(unittest.TestCase): - """ - This test case exhaustively tests parsing and generation by generating - a local RFC 3339 timestamp for every timezone supported by `zoneinfo`, - parsing that timestamp into a local datetime and a UTC datetime - and asserting that those represent the same instant. - - """ - - def setUp(self) -> None: - self.available_timezones = zoneinfo.available_timezones() - - def test_local_roundtrip(self) -> None: - """ - Generates a local datetime using the given timezone, - produces a local timestamp from the datetime, parses the timestamp - to a local datetime, and verifies that the two datetimes are equal. - - """ - for tz_name in self.available_timezones: - with self.subTest(tz=tz_name): - tzinfo = ZoneInfo(tz_name) - dt1 = datetime.now(tzinfo) - timestamp = generate(dt1, utc=False, microseconds=True) - dt2 = parse(timestamp, utc=False) - self.assertEqual(dt1, dt2) - - def test_utc_roundtrip(self) -> None: - """ - Generates a local datetime using the given timezone, - produces a local timestamp from the datetime, parses the timestamp - to a UTC datetime, and verifies that the two datetimes are equal. - - """ - for tz_name in self.available_timezones: - with self.subTest(tz=tz_name): - tzinfo = ZoneInfo(tz_name) - dt1 = datetime.now(tzinfo) - timestamp = generate(dt1, utc=False, microseconds=True) - dt2 = parse(timestamp) - self.assertEqual(dt1, dt2) diff --git a/tests.py b/tests.py new file mode 100644 index 0000000..831daab --- /dev/null +++ b/tests.py @@ -0,0 +1,170 @@ +''' +Test suite for pyRFC3339. + +''' + +from datetime import datetime +from copy import deepcopy + +from pyrfc3339 import generate, parse +from pyrfc3339.utils import timezone +import pytz + +from nose.tools import eq_, raises + + +class TestCore(): + ''' + This test suite contains tests to address cases not tested in the doctests, + as well as additional tests for end-to-end verification. + + ''' + def test_timezone_rounding(self): + ''' + Test rounding of timezone values to the nearest second. + + ''' + eq_(timezone(5429), '+01:30') + eq_(timezone(5431), '+01:31') + + def test_zero_offset(self): + ''' + Both +00:00 and -00:00 are equivalent to the offset 'Z' (UTC). + + ''' + timestamp = '2009-01-01T10:02:03+00:00' + dt = parse(timestamp) + eq_(dt.tzinfo, pytz.utc) + + timestamp = '2009-01-01T10:02:03-00:00' + dt = parse(timestamp) + eq_(dt.tzinfo, pytz.utc) + + def test_deepcopy(self): + ''' + Tests that deepcopy works and doesn't crash + + ''' + timestamp = '2009-01-01T10:02:03+02:00' + dt = parse(timestamp) + deepcopy(dt) + + def test_parse_microseconds(self): + ''' + Test parsing timestamps with microseconds. + + ''' + timestamp = '2009-01-01T10:02:03.25Z' + dt = parse(timestamp) + eq_(dt.microsecond, 250000) + + def test_generate_microseconds(self): + ''' + Test generating timestamps with microseconds. + + ''' + dt = datetime(2009, 1, 1, 10, 2, 3, 500000, pytz.utc) + timestamp = generate(dt, microseconds=True) + eq_(timestamp, '2009-01-01T10:02:03.500000Z') + + def test_mixed_case(self): + ''' + Timestamps may use either 'T' or 't' and either 'Z' or 'z' + according to :RFC:`3339`. + + ''' + dt1 = parse('2009-01-01t10:01:02z') + dt2 = datetime(2009, 1, 1, 10, 1, 2, tzinfo=pytz.utc) + + eq_(dt1, dt2) + + def test_parse_naive_utc(self): + ''' + Test parsing a UTC timestamp to a naive datetime. + + ''' + dt1 = parse('2009-01-01T10:01:02Z', produce_naive=True) + eq_(dt1.tzinfo, None) + + @raises(ValueError) + def test_parse_naive_local(self): + ''' + Test that parsing a local timestamp to a naive datetime fails. + + ''' + parse('2009-01-01T10:01:02-04:00', produce_naive=True) + + def test_generate_utc_parse_utc(self): + ''' + Generate a UTC timestamp and parse it into a UTC datetime. + + ''' + dt1 = datetime.utcnow() + dt1 = dt1.replace(tzinfo=pytz.utc) + + dt2 = parse(generate(dt1, microseconds=True)) + eq_(dt1, dt2) + + def test_generate_local_parse_local(self): + ''' + Generate a local timestamp and parse it into a local datetime. + + ''' + eastern = pytz.timezone('US/Eastern') + dt1 = eastern.localize(datetime.utcnow()) + dt2 = parse(generate(dt1, utc=False, microseconds=True), utc=False) + eq_(dt1, dt2) + + def test_generate_local_parse_utc(self): + ''' + Generate a local timestamp and parse it into a UTC datetime. + + ''' + eastern = pytz.timezone('US/Eastern') + dt1 = eastern.localize(datetime.utcnow()) + dt2 = parse(generate(dt1, utc=False, microseconds=True)) + eq_(dt1, dt2) + + +class TestExhaustiveRoundtrip(): + ''' + This test suite exhaustively tests parsing and generation by generating + a local RFC 3339 timestamp for every timezone supported by pytz, + and parsing that timestamp into a local datetime and a UTC datetime. + ''' + + slow = True + + def test_local_roundtrip(self): + for tz_name in pytz.all_timezones: + yield self.local_roundtrip, tz_name + + def local_roundtrip(self, tz_name): + ''' + Generates a local datetime using the given timezone, + produces a local timestamp from the datetime, parses the timestamp + to a local datetime, and verifies that the two datetimes are equal. + + ''' + tzinfo = pytz.timezone(tz_name) + dt1 = tzinfo.localize(datetime.utcnow()) + timestamp = generate(dt1, utc=False, microseconds=True) + dt2 = parse(timestamp, utc=False) + eq_(dt1, dt2) + + def test_utc_roundtrip(self): + for tz_name in pytz.all_timezones: + yield self.utc_roundtrip, tz_name + + def utc_roundtrip(self, tz_name): + ''' + Generates a local datetime using the given timezone, + produces a local timestamp from the datetime, parses the timestamp + to a UTC datetime, and verifies that the two datetimes are equal. + + ''' + tzinfo = pytz.timezone(tz_name) + dt1 = tzinfo.localize(datetime.utcnow()) + timestamp = generate(dt1, utc=False, microseconds=True) + dt2 = parse(timestamp) + eq_(dt1, dt2)