From 81568e9bc445d6da60a47c86ad11524afd646028 Mon Sep 17 00:00:00 2001 From: Emanuele Giaquinta Date: Mon, 25 Dec 2023 19:45:11 +0100 Subject: [PATCH] Improve datetime tests - remove code duplication in timezone tests - add missing coverage for some timezone libraries - fix UTC+00:20 timezone test with pendulum 3 - enable timezone tests with pendulum 3 on python 3.12 - enable timezone tests with zoneinfo on windows Signed-off-by: Emanuele Giaquinta --- tests/requirements.txt | 3 +- tests/test_datetime.py | 276 +++++++++-------------------------------- 2 files changed, 60 insertions(+), 219 deletions(-) diff --git a/tests/requirements.txt b/tests/requirements.txt index cd320326..56ac4f4a 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,10 +1,11 @@ arrow numpy -pendulum;python_version<"3.12" +pendulum psutil;sys_platform!="windows" pytest pytz xxhash==1.4.3;sys_platform!="windows" and python_version<"3.9" # creates non-compact ASCII for test_str_ascii msgpack pydantic +tzdata types-pytz diff --git a/tests/test_datetime.py b/tests/test_datetime.py index b7278c53..3dce72d8 100644 --- a/tests/test_datetime.py +++ b/tests/test_datetime.py @@ -4,20 +4,34 @@ import sys import msgpack +import pendulum import pytest import pytz from dateutil import tz import ormsgpack -try: - import pendulum -except ImportError: - pendulum = None # type: ignore - if sys.version_info >= (3, 9): import zoneinfo + ZoneInfo = zoneinfo.ZoneInfo + ZoneInfoUTC = zoneinfo.ZoneInfo("UTC") +else: + ZoneInfo = None + ZoneInfoUTC = None + + +TIMEZONE_PARAMS = ( + pytest.param(pendulum.timezone, id="pendulum"), + pytest.param(pytz.timezone, id="pytz"), + pytest.param(tz.gettz, id="dateutil"), + pytest.param( + ZoneInfo, + id="zoneinfo", + marks=pytest.mark.skipif(ZoneInfo is None, reason="zoneinfo not available"), + ), +) + def test_datetime_naive(): """ @@ -88,100 +102,31 @@ def test_datetime_tz_assume(): ) == msgpack.packb(["2018-01-01T02:03:04+08:00"]) -def test_datetime_timezone_utc(): - """ - datetime.datetime UTC - """ - assert ormsgpack.packb( - [datetime.datetime(2018, 6, 1, 2, 3, 4, 0, tzinfo=datetime.timezone.utc)] - ) == msgpack.packb(["2018-06-01T02:03:04+00:00"]) - - -def test_datetime_pytz_utc(): - """ - datetime.datetime UTC - """ - assert ormsgpack.packb( - [datetime.datetime(2018, 6, 1, 2, 3, 4, 0, tzinfo=pytz.UTC)] - ) == msgpack.packb(["2018-06-01T02:03:04+00:00"]) - - -@pytest.mark.skipif( - sys.version_info < (3, 9) or sys.platform.startswith("win"), - reason="zoneinfo not available", +@pytest.mark.parametrize( + "timezone", + ( + pytest.param(datetime.timezone.utc, id="datetime"), + pytest.param(pendulum.UTC, id="pendulum"), + pytest.param(pytz.UTC, id="pytz"), + pytest.param(tz.UTC, id="dateutil"), + pytest.param( + ZoneInfoUTC, + id="zoneinfo", + marks=pytest.mark.skipif(ZoneInfo is None, reason="zoneinfo not available"), + ), + ), ) -def test_datetime_zoneinfo_positive(): - assert ormsgpack.packb( - [ - datetime.datetime( - 2018, - 1, - 1, - 2, - 3, - 4, - 0, - tzinfo=zoneinfo.ZoneInfo("Asia/Shanghai"), - ) - ] - ) == msgpack.packb(["2018-01-01T02:03:04+08:00"]) - - -@pytest.mark.skipif( - sys.version_info < (3, 9) or sys.platform.startswith("win"), - reason="zoneinfo not available", -) -def test_datetime_zoneinfo_negative(): - assert ormsgpack.packb( - [ - datetime.datetime( - 2018, - 6, - 1, - 2, - 3, - 4, - 0, - tzinfo=zoneinfo.ZoneInfo("America/New_York"), - ) - ] - ) == msgpack.packb(["2018-06-01T02:03:04-04:00"]) - - -@pytest.mark.skipif(pendulum is None, reason="pendulum install broken on win") -def test_datetime_pendulum_utc(): +def test_datetime_utc(timezone): """ datetime.datetime UTC """ assert ormsgpack.packb( - [datetime.datetime(2018, 6, 1, 2, 3, 4, 0, tzinfo=pendulum.UTC)] + [datetime.datetime(2018, 6, 1, 2, 3, 4, 0, tzinfo=timezone)] ) == msgpack.packb(["2018-06-01T02:03:04+00:00"]) -def test_datetime_arrow_positive(): - """ - datetime.datetime positive UTC - """ - assert ormsgpack.packb( - [datetime.datetime(2018, 1, 1, 2, 3, 4, 0, tzinfo=tz.gettz("Asia/Shanghai"))] - ) == msgpack.packb(["2018-01-01T02:03:04+08:00"]) - - -def test_datetime_pytz_positive(): - """ - datetime.datetime positive UTC - """ - assert ormsgpack.packb( - [ - datetime.datetime( - 2018, 1, 1, 2, 3, 4, 0, tzinfo=pytz.timezone("Asia/Shanghai") - ) - ] - ) == msgpack.packb(["2018-01-01T02:03:04+08:00"]) - - -@pytest.mark.skipif(pendulum is None, reason="pendulum install broken on win") -def test_datetime_pendulum_positive(): +@pytest.mark.parametrize("timezone", TIMEZONE_PARAMS) +def test_datetime_positive(timezone): """ datetime.datetime positive UTC """ @@ -195,27 +140,14 @@ def test_datetime_pendulum_positive(): 3, 4, 0, - tzinfo=pendulum.timezone("Asia/Shanghai"), + tzinfo=timezone("Asia/Shanghai"), ) ] ) == msgpack.packb(["2018-01-01T02:03:04+08:00"]) -def test_datetime_pytz_negative_dst(): - """ - datetime.datetime negative UTC DST - """ - assert ormsgpack.packb( - [ - datetime.datetime( - 2018, 6, 1, 2, 3, 4, 0, tzinfo=pytz.timezone("America/New_York") - ) - ] - ) == msgpack.packb(["2018-06-01T02:03:04-04:00"]) - - -@pytest.mark.skipif(pendulum is None, reason="pendulum install broken on win") -def test_datetime_pendulum_negative_dst(): +@pytest.mark.parametrize("timezone", TIMEZONE_PARAMS) +def test_datetime_negative_dst(timezone): """ datetime.datetime negative UTC DST """ @@ -229,34 +161,14 @@ def test_datetime_pendulum_negative_dst(): 3, 4, 0, - tzinfo=pendulum.timezone("America/New_York"), + tzinfo=timezone("America/New_York"), ) ] ) == msgpack.packb(["2018-06-01T02:03:04-04:00"]) -def test_datetime_pytz_negative_non_dst(): - """ - datetime.datetime negative UTC non-DST - """ - assert ormsgpack.packb( - [ - datetime.datetime( - 2018, - 12, - 1, - 2, - 3, - 4, - 0, - tzinfo=pytz.timezone("America/New_York"), - ) - ] - ) == msgpack.packb(["2018-12-01T02:03:04-05:00"]) - - -@pytest.mark.skipif(pendulum is None, reason="pendulum install broken on win") -def test_datetime_pendulum_negative_non_dst(): +@pytest.mark.parametrize("timezone", TIMEZONE_PARAMS) +def test_datetime_negative_non_dst(timezone): """ datetime.datetime negative UTC non-DST """ @@ -270,13 +182,14 @@ def test_datetime_pendulum_negative_non_dst(): 3, 4, 0, - tzinfo=pendulum.timezone("America/New_York"), + tzinfo=timezone("America/New_York"), ) ] ) == msgpack.packb(["2018-12-01T02:03:04-05:00"]) -def test_datetime_partial_hour(): +@pytest.mark.parametrize("timezone", TIMEZONE_PARAMS) +def test_datetime_partial_hour(timezone): """ datetime.datetime UTC offset partial hour """ @@ -290,77 +203,14 @@ def test_datetime_partial_hour(): 3, 4, 0, - tzinfo=pytz.timezone("Australia/Adelaide"), + tzinfo=timezone("Australia/Adelaide"), ) ] ) == msgpack.packb(["2018-12-01T02:03:04+10:30"]) -def test_datetime_pytz_partial_hour(): - """ - datetime.datetime UTC offset partial hour - """ - assert ormsgpack.packb( - [ - datetime.datetime( - 2018, - 12, - 1, - 2, - 3, - 4, - 0, - tzinfo=pytz.timezone("Australia/Adelaide"), - ) - ] - ) == msgpack.packb(["2018-12-01T02:03:04+10:30"]) - - -@pytest.mark.skipif(pendulum is None, reason="pendulum install broken on win") -def test_datetime_pendulum_partial_hour(): - """ - datetime.datetime UTC offset partial hour - """ - assert ormsgpack.packb( - [ - datetime.datetime( - 2018, - 12, - 1, - 2, - 3, - 4, - 0, - tzinfo=pendulum.timezone("Australia/Adelaide"), - ) - ] - ) == msgpack.packb(["2018-12-01T02:03:04+10:30"]) - - -@pytest.mark.skipif(pendulum is None, reason="pendulum install broken on win") -def test_datetime_partial_second_pendulum_supported(): - """ - datetime.datetime UTC offset round seconds - - https://tools.ietf.org/html/rfc3339#section-5.8 - """ - assert ormsgpack.packb( - [ - datetime.datetime( - 1937, - 1, - 1, - 12, - 0, - 27, - 87, - tzinfo=pendulum.timezone("Europe/Amsterdam"), - ) - ] - ) == msgpack.packb(["1937-01-01T12:00:27.000087+00:20"]) - - -def test_datetime_partial_second_pytz(): +@pytest.mark.parametrize("timezone", TIMEZONE_PARAMS) +def test_datetime_partial_second(timezone): """ datetime.datetime UTC offset round seconds @@ -376,25 +226,13 @@ def test_datetime_partial_second_pytz(): 0, 27, 87, - tzinfo=pytz.timezone("Asia/Vladivostok"), - ) - ] - ) == msgpack.packb(["1937-01-01T12:00:27.000087+10:00"]) - - -def test_datetime_partial_second_dateutil(): - """ - datetime.datetime UTC offset round seconds - - https://tools.ietf.org/html/rfc3339#section-5.8 - """ - assert ormsgpack.packb( - [ - datetime.datetime( - 1937, 1, 1, 12, 0, 27, 87, tzinfo=tz.gettz("Asia/Vladivostok") + tzinfo=timezone("Europe/Amsterdam"), ) ] - ) == msgpack.packb(["1937-01-01T12:00:27.000087+10:00"]) + ) in { + msgpack.packb(["1937-01-01T12:00:27.000087+00:00"]), + msgpack.packb(["1937-01-01T12:00:27.000087+00:20"]), + } def test_datetime_microsecond_max(): @@ -487,14 +325,16 @@ def test_datetime_utc_z_with_tz(): assert ormsgpack.packb( [ datetime.datetime( - 1937, 1, 1, 12, 0, 27, 87, tzinfo=tz.gettz("Asia/Vladivostok") + 1937, 1, 1, 12, 0, 27, 87, tzinfo=tz.gettz("Europe/Amsterdam") ) ], option=ormsgpack.OPT_UTC_Z, - ) == msgpack.packb(["1937-01-01T12:00:27.000087+10:00"]) + ) in { + msgpack.packb(["1937-01-01T12:00:27.000087Z"]), + msgpack.packb(["1937-01-01T12:00:27.000087+00:20"]), + } -@pytest.mark.skipif(pendulum is None, reason="pendulum install broken on win") def test_datetime_roundtrip(): """ datetime.datetime parsed by pendulum