Fix time code to work in timezones other than UTC, and add tests in multiple timezones (#810)
* Add tests in multiple timezones. * Fix get_epoch_seconds() for timestamps without timezones. * Add changelog fragment. * Pin version for Python 2.6.pull/811/head
parent
21e344e283
commit
feee571bc8
|
@ -0,0 +1,2 @@
|
||||||
|
bugfixes:
|
||||||
|
- "time module utils - fix conversion of naive ``datetime`` objects to UNIX timestamps for Python 3 (https://github.com/ansible-collections/community.crypto/issues/808, https://github.com/ansible-collections/community.crypto/pull/810)."
|
|
@ -83,6 +83,9 @@ if sys.version_info < (3, 3):
|
||||||
return (delta.microseconds + (delta.seconds + delta.days * 24 * 3600) * 10**6) / 10**6
|
return (delta.microseconds + (delta.seconds + delta.days * 24 * 3600) * 10**6) / 10**6
|
||||||
else:
|
else:
|
||||||
def get_epoch_seconds(timestamp):
|
def get_epoch_seconds(timestamp):
|
||||||
|
if timestamp.tzinfo is None:
|
||||||
|
# timestamp.timestamp() is offset by the local timezone if timestamp has no timezone
|
||||||
|
timestamp = ensure_utc_timezone(timestamp)
|
||||||
return timestamp.timestamp()
|
return timestamp.timestamp()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ from ansible_collections.community.crypto.plugins.module_utils.acme.errors impor
|
||||||
BackendException,
|
BackendException,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from ..test_time import cartesian_product, TIMEZONES
|
||||||
|
|
||||||
|
|
||||||
def load_fixture(name):
|
def load_fixture(name):
|
||||||
with open(os.path.join(os.path.dirname(__file__), 'fixtures', name)) as f:
|
with open(os.path.join(os.path.dirname(__file__), 'fixtures', name)) as f:
|
||||||
|
@ -89,11 +91,11 @@ TEST_CERT_OPENSSL_OUTPUT_2 = load_fixture("cert_2.txt") # OpenSSL 3.3.0 output
|
||||||
TEST_CERT_OPENSSL_OUTPUT_2B = load_fixture("cert_2-b.txt") # OpenSSL 1.1.1f output
|
TEST_CERT_OPENSSL_OUTPUT_2B = load_fixture("cert_2-b.txt") # OpenSSL 1.1.1f output
|
||||||
|
|
||||||
|
|
||||||
TEST_CERT_DAYS = [
|
TEST_CERT_DAYS = cartesian_product(TIMEZONES, [
|
||||||
(datetime.datetime(2018, 11, 15, 1, 2, 3), 11),
|
(datetime.datetime(2018, 11, 15, 1, 2, 3), 11),
|
||||||
(datetime.datetime(2018, 11, 25, 15, 20, 0), 1),
|
(datetime.datetime(2018, 11, 25, 15, 20, 0), 1),
|
||||||
(datetime.datetime(2018, 11, 25, 15, 30, 0), 0),
|
(datetime.datetime(2018, 11, 25, 15, 30, 0), 0),
|
||||||
]
|
])
|
||||||
|
|
||||||
|
|
||||||
TEST_CERT_INFO = CertificateInformation(
|
TEST_CERT_INFO = CertificateInformation(
|
||||||
|
@ -121,7 +123,7 @@ TEST_CERT_INFO = [
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
TEST_PARSE_ACME_TIMESTAMP = [
|
TEST_PARSE_ACME_TIMESTAMP = cartesian_product(TIMEZONES, [
|
||||||
(
|
(
|
||||||
'2024-01-01T00:11:22Z',
|
'2024-01-01T00:11:22Z',
|
||||||
dict(year=2024, month=1, day=1, hour=0, minute=11, second=22),
|
dict(year=2024, month=1, day=1, hour=0, minute=11, second=22),
|
||||||
|
@ -134,10 +136,10 @@ TEST_PARSE_ACME_TIMESTAMP = [
|
||||||
'2024-04-17T06:54:13.333333334Z',
|
'2024-04-17T06:54:13.333333334Z',
|
||||||
dict(year=2024, month=4, day=17, hour=6, minute=54, second=13, microsecond=333333),
|
dict(year=2024, month=4, day=17, hour=6, minute=54, second=13, microsecond=333333),
|
||||||
),
|
),
|
||||||
]
|
])
|
||||||
|
|
||||||
if sys.version_info >= (3, 5):
|
if sys.version_info >= (3, 5):
|
||||||
TEST_PARSE_ACME_TIMESTAMP.extend([
|
TEST_PARSE_ACME_TIMESTAMP.extend(cartesian_product(TIMEZONES, [
|
||||||
(
|
(
|
||||||
'2024-01-01T00:11:22+0100',
|
'2024-01-01T00:11:22+0100',
|
||||||
dict(year=2023, month=12, day=31, hour=23, minute=11, second=22),
|
dict(year=2023, month=12, day=31, hour=23, minute=11, second=22),
|
||||||
|
@ -146,10 +148,10 @@ if sys.version_info >= (3, 5):
|
||||||
'2024-01-01T00:11:22.123+0100',
|
'2024-01-01T00:11:22.123+0100',
|
||||||
dict(year=2023, month=12, day=31, hour=23, minute=11, second=22, microsecond=123000),
|
dict(year=2023, month=12, day=31, hour=23, minute=11, second=22, microsecond=123000),
|
||||||
),
|
),
|
||||||
])
|
]))
|
||||||
|
|
||||||
|
|
||||||
TEST_INTERPOLATE_TIMESTAMP = [
|
TEST_INTERPOLATE_TIMESTAMP = cartesian_product(TIMEZONES, [
|
||||||
(
|
(
|
||||||
dict(year=2024, month=1, day=1, hour=0, minute=0, second=0),
|
dict(year=2024, month=1, day=1, hour=0, minute=0, second=0),
|
||||||
dict(year=2024, month=1, day=1, hour=1, minute=0, second=0),
|
dict(year=2024, month=1, day=1, hour=1, minute=0, second=0),
|
||||||
|
@ -168,7 +170,7 @@ TEST_INTERPOLATE_TIMESTAMP = [
|
||||||
1.0,
|
1.0,
|
||||||
dict(year=2024, month=1, day=1, hour=1, minute=0, second=0),
|
dict(year=2024, month=1, day=1, hour=1, minute=0, second=0),
|
||||||
),
|
),
|
||||||
]
|
])
|
||||||
|
|
||||||
|
|
||||||
class FakeBackend(CryptoBackend):
|
class FakeBackend(CryptoBackend):
|
||||||
|
|
|
@ -5,11 +5,14 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from freezegun import freeze_time
|
||||||
|
|
||||||
from ansible_collections.community.crypto.tests.unit.compat.mock import MagicMock
|
from ansible_collections.community.crypto.tests.unit.compat.mock import MagicMock
|
||||||
|
|
||||||
|
from ansible_collections.community.crypto.plugins.module_utils.time import UTC
|
||||||
|
|
||||||
from ansible_collections.community.crypto.plugins.module_utils.acme.backend_cryptography import (
|
from ansible_collections.community.crypto.plugins.module_utils.acme.backend_cryptography import (
|
||||||
HAS_CURRENT_CRYPTOGRAPHY,
|
HAS_CURRENT_CRYPTOGRAPHY,
|
||||||
|
@ -34,6 +37,8 @@ from .backend_data import (
|
||||||
TEST_INTERPOLATE_TIMESTAMP,
|
TEST_INTERPOLATE_TIMESTAMP,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from ..test_time import TIMEZONES
|
||||||
|
|
||||||
|
|
||||||
if not HAS_CURRENT_CRYPTOGRAPHY:
|
if not HAS_CURRENT_CRYPTOGRAPHY:
|
||||||
pytest.skip('cryptography not found')
|
pytest.skip('cryptography not found')
|
||||||
|
@ -65,8 +70,9 @@ def test_csridentifiers_cryptography(csr, result, openssl_output, tmpdir):
|
||||||
assert identifiers == result
|
assert identifiers == result
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("now, expected_days", TEST_CERT_DAYS)
|
@pytest.mark.parametrize("timezone, now, expected_days", TEST_CERT_DAYS)
|
||||||
def test_certdays_cryptography(now, expected_days, tmpdir):
|
def test_certdays_cryptography(timezone, now, expected_days, tmpdir):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
fn = tmpdir / 'test-cert.pem'
|
fn = tmpdir / 'test-cert.pem'
|
||||||
fn.write(TEST_CERT)
|
fn.write(TEST_CERT)
|
||||||
module = MagicMock()
|
module = MagicMock()
|
||||||
|
@ -96,15 +102,26 @@ def test_get_cert_information(cert_content, expected_cert_info, openssl_output,
|
||||||
assert cert_info == expected_cert_info
|
assert cert_info == expected_cert_info
|
||||||
|
|
||||||
|
|
||||||
def test_now():
|
# @pytest.mark.parametrize("timezone", TIMEZONES)
|
||||||
|
# Due to a bug in freezegun (https://github.com/spulec/freezegun/issues/348, https://github.com/spulec/freezegun/issues/553)
|
||||||
|
# this only works with timezone = UTC if CRYPTOGRAPHY_TIMEZONE is truish
|
||||||
|
@pytest.mark.parametrize("timezone", [datetime.timedelta(hours=0)] if CRYPTOGRAPHY_TIMEZONE else TIMEZONES)
|
||||||
|
def test_now(timezone):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
module = MagicMock()
|
module = MagicMock()
|
||||||
backend = CryptographyBackend(module)
|
backend = CryptographyBackend(module)
|
||||||
now = backend.get_now()
|
now = backend.get_now()
|
||||||
assert CRYPTOGRAPHY_TIMEZONE == (now.tzinfo is not None)
|
if CRYPTOGRAPHY_TIMEZONE:
|
||||||
|
assert now.tzinfo is not None
|
||||||
|
assert now == datetime.datetime(2024, 2, 3, 4, 5, 6, tzinfo=UTC)
|
||||||
|
else:
|
||||||
|
assert now.tzinfo is None
|
||||||
|
assert now == datetime.datetime(2024, 2, 3, 4, 5, 6)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("input, expected", TEST_PARSE_ACME_TIMESTAMP)
|
@pytest.mark.parametrize("timezone, input, expected", TEST_PARSE_ACME_TIMESTAMP)
|
||||||
def test_parse_acme_timestamp(input, expected):
|
def test_parse_acme_timestamp(timezone, input, expected):
|
||||||
|
with freeze_time("2024-02-03 04:05:06 +00:00", tz_offset=timezone):
|
||||||
module = MagicMock()
|
module = MagicMock()
|
||||||
backend = CryptographyBackend(module)
|
backend = CryptographyBackend(module)
|
||||||
ts_expected = backend.get_utc_datetime(**expected)
|
ts_expected = backend.get_utc_datetime(**expected)
|
||||||
|
@ -112,8 +129,9 @@ def test_parse_acme_timestamp(input, expected):
|
||||||
assert ts_expected == timestamp
|
assert ts_expected == timestamp
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("start, end, percentage, expected", TEST_INTERPOLATE_TIMESTAMP)
|
@pytest.mark.parametrize("timezone, start, end, percentage, expected", TEST_INTERPOLATE_TIMESTAMP)
|
||||||
def test_interpolate_timestamp(start, end, percentage, expected):
|
def test_interpolate_timestamp(timezone, start, end, percentage, expected):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
module = MagicMock()
|
module = MagicMock()
|
||||||
backend = CryptographyBackend(module)
|
backend = CryptographyBackend(module)
|
||||||
ts_start = backend.get_utc_datetime(**start)
|
ts_start = backend.get_utc_datetime(**start)
|
||||||
|
|
|
@ -5,8 +5,10 @@
|
||||||
from __future__ import absolute_import, division, print_function
|
from __future__ import absolute_import, division, print_function
|
||||||
__metaclass__ = type
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from freezegun import freeze_time
|
||||||
|
|
||||||
from ansible_collections.community.crypto.tests.unit.compat.mock import MagicMock
|
from ansible_collections.community.crypto.tests.unit.compat.mock import MagicMock
|
||||||
|
|
||||||
|
@ -26,6 +28,8 @@ from .backend_data import (
|
||||||
TEST_INTERPOLATE_TIMESTAMP,
|
TEST_INTERPOLATE_TIMESTAMP,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from ..test_time import TIMEZONES
|
||||||
|
|
||||||
|
|
||||||
TEST_IPS = [
|
TEST_IPS = [
|
||||||
("0:0:0:0:0:0:0:1", "::1"),
|
("0:0:0:0:0:0:0:1", "::1"),
|
||||||
|
@ -69,8 +73,9 @@ def test_normalize_ip(ip, result):
|
||||||
assert backend._normalize_ip(ip) == result
|
assert backend._normalize_ip(ip) == result
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("now, expected_days", TEST_CERT_DAYS)
|
@pytest.mark.parametrize("timezone, now, expected_days", TEST_CERT_DAYS)
|
||||||
def test_certdays_cryptography(now, expected_days, tmpdir):
|
def test_certdays_cryptography(timezone, now, expected_days, tmpdir):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
fn = tmpdir / 'test-cert.pem'
|
fn = tmpdir / 'test-cert.pem'
|
||||||
fn.write(TEST_CERT)
|
fn.write(TEST_CERT)
|
||||||
module = MagicMock()
|
module = MagicMock()
|
||||||
|
@ -95,15 +100,19 @@ def test_get_cert_information(cert_content, expected_cert_info, openssl_output,
|
||||||
assert cert_info == expected_cert_info
|
assert cert_info == expected_cert_info
|
||||||
|
|
||||||
|
|
||||||
def test_now():
|
@pytest.mark.parametrize("timezone", TIMEZONES)
|
||||||
|
def test_now(timezone):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
module = MagicMock()
|
module = MagicMock()
|
||||||
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
||||||
now = backend.get_now()
|
now = backend.get_now()
|
||||||
assert now.tzinfo is None
|
assert now.tzinfo is None
|
||||||
|
assert now == datetime.datetime(2024, 2, 3, 4, 5, 6)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("input, expected", TEST_PARSE_ACME_TIMESTAMP)
|
@pytest.mark.parametrize("timezone, input, expected", TEST_PARSE_ACME_TIMESTAMP)
|
||||||
def test_parse_acme_timestamp(input, expected):
|
def test_parse_acme_timestamp(timezone, input, expected):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
module = MagicMock()
|
module = MagicMock()
|
||||||
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
||||||
ts_expected = backend.get_utc_datetime(**expected)
|
ts_expected = backend.get_utc_datetime(**expected)
|
||||||
|
@ -111,8 +120,9 @@ def test_parse_acme_timestamp(input, expected):
|
||||||
assert ts_expected == timestamp
|
assert ts_expected == timestamp
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("start, end, percentage, expected", TEST_INTERPOLATE_TIMESTAMP)
|
@pytest.mark.parametrize("timezone, start, end, percentage, expected", TEST_INTERPOLATE_TIMESTAMP)
|
||||||
def test_interpolate_timestamp(start, end, percentage, expected):
|
def test_interpolate_timestamp(timezone, start, end, percentage, expected):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
module = MagicMock()
|
module = MagicMock()
|
||||||
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
backend = OpenSSLCLIBackend(module, openssl_binary='openssl')
|
||||||
ts_start = backend.get_utc_datetime(**start)
|
ts_start = backend.get_utc_datetime(**start)
|
||||||
|
|
|
@ -10,7 +10,9 @@ import datetime
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
from freezegun import freeze_time
|
||||||
|
|
||||||
|
from ansible.module_utils.common.collections import is_sequence
|
||||||
|
|
||||||
from ansible_collections.community.crypto.plugins.module_utils.time import (
|
from ansible_collections.community.crypto.plugins.module_utils.time import (
|
||||||
add_or_remove_timezone,
|
add_or_remove_timezone,
|
||||||
|
@ -25,18 +27,42 @@ from ansible_collections.community.crypto.plugins.module_utils.time import (
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
TEST_REMOVE_TIMEZONE = [
|
TIMEZONES = [
|
||||||
(
|
datetime.timedelta(hours=0),
|
||||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
datetime.timedelta(hours=1),
|
||||||
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
datetime.timedelta(hours=2),
|
||||||
),
|
datetime.timedelta(hours=-6),
|
||||||
(
|
|
||||||
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
|
||||||
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
TEST_UTC_TIMEZONE = [
|
|
||||||
|
def cartesian_product(list1, list2):
|
||||||
|
result = []
|
||||||
|
for item1 in list1:
|
||||||
|
if not is_sequence(item1):
|
||||||
|
item1 = (item1, )
|
||||||
|
elif not isinstance(item1, tuple):
|
||||||
|
item1 = tuple(item1)
|
||||||
|
for item2 in list2:
|
||||||
|
if not is_sequence(item2):
|
||||||
|
item2 = (item2, )
|
||||||
|
elif not isinstance(item2, tuple):
|
||||||
|
item2 = tuple(item2)
|
||||||
|
result.append(item1 + item2)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
TEST_REMOVE_TIMEZONE = cartesian_product(TIMEZONES, [
|
||||||
|
(
|
||||||
|
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
||||||
|
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
||||||
|
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
|
||||||
|
TEST_UTC_TIMEZONE = cartesian_product(TIMEZONES, [
|
||||||
(
|
(
|
||||||
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
datetime.datetime(2024, 1, 1, 0, 1, 2),
|
||||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
||||||
|
@ -45,21 +71,21 @@ TEST_UTC_TIMEZONE = [
|
||||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
||||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=UTC),
|
||||||
),
|
),
|
||||||
]
|
])
|
||||||
|
|
||||||
TEST_EPOCH_SECONDS = [
|
TEST_EPOCH_SECONDS = cartesian_product(TIMEZONES, [
|
||||||
(0, dict(year=1970, day=1, month=1, hour=0, minute=0, second=0, microsecond=0)),
|
(0, dict(year=1970, day=1, month=1, hour=0, minute=0, second=0, microsecond=0)),
|
||||||
(1E-6, dict(year=1970, day=1, month=1, hour=0, minute=0, second=0, microsecond=1)),
|
(1E-6, dict(year=1970, day=1, month=1, hour=0, minute=0, second=0, microsecond=1)),
|
||||||
(1E-3, dict(year=1970, day=1, month=1, hour=0, minute=0, second=0, microsecond=1000)),
|
(1E-3, dict(year=1970, day=1, month=1, hour=0, minute=0, second=0, microsecond=1000)),
|
||||||
(3691.2, dict(year=1970, day=1, month=1, hour=1, minute=1, second=31, microsecond=200000)),
|
(3691.2, dict(year=1970, day=1, month=1, hour=1, minute=1, second=31, microsecond=200000)),
|
||||||
]
|
])
|
||||||
|
|
||||||
TEST_EPOCH_TO_SECONDS = [
|
TEST_EPOCH_TO_SECONDS = cartesian_product(TIMEZONES, [
|
||||||
(datetime.datetime(1970, 1, 1, 0, 1, 2, 0), 62),
|
(datetime.datetime(1970, 1, 1, 0, 1, 2, 0), 62),
|
||||||
(datetime.datetime(1970, 1, 1, 0, 1, 2, 0, tzinfo=UTC), 62),
|
(datetime.datetime(1970, 1, 1, 0, 1, 2, 0, tzinfo=UTC), 62),
|
||||||
]
|
])
|
||||||
|
|
||||||
TEST_CONVERT_RELATIVE_TO_DATETIME = [
|
TEST_CONVERT_RELATIVE_TO_DATETIME = cartesian_product(TIMEZONES, [
|
||||||
(
|
(
|
||||||
'+0',
|
'+0',
|
||||||
False,
|
False,
|
||||||
|
@ -96,9 +122,9 @@ TEST_CONVERT_RELATIVE_TO_DATETIME = [
|
||||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||||
datetime.datetime(2023, 10, 1, 17, 19, 10, tzinfo=UTC),
|
datetime.datetime(2023, 10, 1, 17, 19, 10, tzinfo=UTC),
|
||||||
),
|
),
|
||||||
]
|
])
|
||||||
|
|
||||||
TEST_GET_RELATIVE_TIME_OPTION = [
|
TEST_GET_RELATIVE_TIME_OPTION = cartesian_product(TIMEZONES, [
|
||||||
(
|
(
|
||||||
'+1d2h3m4s',
|
'+1d2h3m4s',
|
||||||
'foo',
|
'foo',
|
||||||
|
@ -195,28 +221,28 @@ TEST_GET_RELATIVE_TIME_OPTION = [
|
||||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||||
'202401020405Z',
|
'202401020405Z',
|
||||||
),
|
),
|
||||||
]
|
])
|
||||||
|
|
||||||
|
|
||||||
if sys.version_info >= (3, 5):
|
if sys.version_info >= (3, 5):
|
||||||
ONE_HOUR_PLUS = datetime.timezone(datetime.timedelta(hours=1))
|
ONE_HOUR_PLUS = datetime.timezone(datetime.timedelta(hours=1))
|
||||||
|
|
||||||
TEST_REMOVE_TIMEZONE.extend([
|
TEST_REMOVE_TIMEZONE.extend(cartesian_product(TIMEZONES, [
|
||||||
(
|
(
|
||||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=ONE_HOUR_PLUS),
|
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=ONE_HOUR_PLUS),
|
||||||
datetime.datetime(2023, 12, 31, 23, 1, 2),
|
datetime.datetime(2023, 12, 31, 23, 1, 2),
|
||||||
),
|
),
|
||||||
])
|
]))
|
||||||
TEST_UTC_TIMEZONE.extend([
|
TEST_UTC_TIMEZONE.extend(cartesian_product(TIMEZONES, [
|
||||||
(
|
(
|
||||||
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=ONE_HOUR_PLUS),
|
datetime.datetime(2024, 1, 1, 0, 1, 2, tzinfo=ONE_HOUR_PLUS),
|
||||||
datetime.datetime(2023, 12, 31, 23, 1, 2, tzinfo=UTC),
|
datetime.datetime(2023, 12, 31, 23, 1, 2, tzinfo=UTC),
|
||||||
),
|
),
|
||||||
])
|
]))
|
||||||
TEST_EPOCH_TO_SECONDS.extend([
|
TEST_EPOCH_TO_SECONDS.extend(cartesian_product(TIMEZONES, [
|
||||||
(datetime.datetime(1970, 1, 1, 0, 1, 2, 0, tzinfo=ONE_HOUR_PLUS), 62 - 3600),
|
(datetime.datetime(1970, 1, 1, 0, 1, 2, 0, tzinfo=ONE_HOUR_PLUS), 62 - 3600),
|
||||||
])
|
]))
|
||||||
TEST_GET_RELATIVE_TIME_OPTION.extend([
|
TEST_GET_RELATIVE_TIME_OPTION.extend(cartesian_product(TIMEZONES, [
|
||||||
(
|
(
|
||||||
'20240102040506+0100',
|
'20240102040506+0100',
|
||||||
'foo',
|
'foo',
|
||||||
|
@ -265,35 +291,50 @@ if sys.version_info >= (3, 5):
|
||||||
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
datetime.datetime(2024, 1, 1, 0, 0, 0),
|
||||||
'202401020405+0100',
|
'202401020405+0100',
|
||||||
),
|
),
|
||||||
])
|
]))
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("input, expected", TEST_REMOVE_TIMEZONE)
|
@pytest.mark.parametrize("timezone, input, expected", TEST_REMOVE_TIMEZONE)
|
||||||
def test_remove_timezone(input, expected):
|
def test_remove_timezone(timezone, input, expected):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
output_1 = remove_timezone(input)
|
output_1 = remove_timezone(input)
|
||||||
assert expected == output_1
|
assert expected == output_1
|
||||||
output_2 = add_or_remove_timezone(input, with_timezone=False)
|
output_2 = add_or_remove_timezone(input, with_timezone=False)
|
||||||
assert expected == output_2
|
assert expected == output_2
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("input, expected", TEST_UTC_TIMEZONE)
|
@pytest.mark.parametrize("timezone, input, expected", TEST_UTC_TIMEZONE)
|
||||||
def test_utc_timezone(input, expected):
|
def test_utc_timezone(timezone, input, expected):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
output_1 = ensure_utc_timezone(input)
|
output_1 = ensure_utc_timezone(input)
|
||||||
assert expected == output_1
|
assert expected == output_1
|
||||||
output_2 = add_or_remove_timezone(input, with_timezone=True)
|
output_2 = add_or_remove_timezone(input, with_timezone=True)
|
||||||
assert expected == output_2
|
assert expected == output_2
|
||||||
|
|
||||||
|
|
||||||
def test_get_now_datetime():
|
# @pytest.mark.parametrize("timezone", TIMEZONES)
|
||||||
output_1 = get_now_datetime(with_timezone=False)
|
# Due to a bug in freezegun (https://github.com/spulec/freezegun/issues/348, https://github.com/spulec/freezegun/issues/553)
|
||||||
assert output_1.tzinfo is None
|
# this only works with timezone = UTC
|
||||||
|
@pytest.mark.parametrize("timezone", [datetime.timedelta(hours=0)])
|
||||||
|
def test_get_now_datetime_w_timezone(timezone):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
output_2 = get_now_datetime(with_timezone=True)
|
output_2 = get_now_datetime(with_timezone=True)
|
||||||
assert output_2.tzinfo is not None
|
assert output_2.tzinfo is not None
|
||||||
assert output_2.tzinfo == UTC
|
assert output_2.tzinfo == UTC
|
||||||
|
assert output_2 == datetime.datetime(2024, 2, 3, 4, 5, 6, tzinfo=UTC)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("seconds, timestamp", TEST_EPOCH_SECONDS)
|
@pytest.mark.parametrize("timezone", TIMEZONES)
|
||||||
def test_epoch_seconds(seconds, timestamp):
|
def test_get_now_datetime_wo_timezone(timezone):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
|
output_1 = get_now_datetime(with_timezone=False)
|
||||||
|
assert output_1.tzinfo is None
|
||||||
|
assert output_1 == datetime.datetime(2024, 2, 3, 4, 5, 6)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("timezone, seconds, timestamp", TEST_EPOCH_SECONDS)
|
||||||
|
def test_epoch_seconds(timezone, seconds, timestamp):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
ts_wo_tz = datetime.datetime(**timestamp)
|
ts_wo_tz = datetime.datetime(**timestamp)
|
||||||
assert seconds == get_epoch_seconds(ts_wo_tz)
|
assert seconds == get_epoch_seconds(ts_wo_tz)
|
||||||
timestamp_w_tz = dict(timestamp)
|
timestamp_w_tz = dict(timestamp)
|
||||||
|
@ -306,18 +347,21 @@ def test_epoch_seconds(seconds, timestamp):
|
||||||
assert ts_w_tz == output_2
|
assert ts_w_tz == output_2
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("timestamp, expected_seconds", TEST_EPOCH_TO_SECONDS)
|
@pytest.mark.parametrize("timezone, timestamp, expected_seconds", TEST_EPOCH_TO_SECONDS)
|
||||||
def test_epoch_to_seconds(timestamp, expected_seconds):
|
def test_epoch_to_seconds(timezone, timestamp, expected_seconds):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
assert expected_seconds == get_epoch_seconds(timestamp)
|
assert expected_seconds == get_epoch_seconds(timestamp)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("relative_time_string, with_timezone, now, expected", TEST_CONVERT_RELATIVE_TO_DATETIME)
|
@pytest.mark.parametrize("timezone, relative_time_string, with_timezone, now, expected", TEST_CONVERT_RELATIVE_TO_DATETIME)
|
||||||
def test_convert_relative_to_datetime(relative_time_string, with_timezone, now, expected):
|
def test_convert_relative_to_datetime(timezone, relative_time_string, with_timezone, now, expected):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
output = convert_relative_to_datetime(relative_time_string, with_timezone=with_timezone, now=now)
|
output = convert_relative_to_datetime(relative_time_string, with_timezone=with_timezone, now=now)
|
||||||
assert expected == output
|
assert expected == output
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("input_string, input_name, backend, with_timezone, now, expected", TEST_GET_RELATIVE_TIME_OPTION)
|
@pytest.mark.parametrize("timezone, input_string, input_name, backend, with_timezone, now, expected", TEST_GET_RELATIVE_TIME_OPTION)
|
||||||
def test_get_relative_time_option(input_string, input_name, backend, with_timezone, now, expected):
|
def test_get_relative_time_option(timezone, input_string, input_name, backend, with_timezone, now, expected):
|
||||||
|
with freeze_time("2024-02-03 04:05:06", tz_offset=timezone):
|
||||||
output = get_relative_time_option(input_string, input_name, backend=backend, with_timezone=with_timezone, now=now)
|
output = get_relative_time_option(input_string, input_name, backend=backend, with_timezone=with_timezone, now=now)
|
||||||
assert expected == output
|
assert expected == output
|
||||||
|
|
|
@ -7,5 +7,7 @@ cryptography
|
||||||
idna
|
idna
|
||||||
ipaddress ; python_version < '3.0'
|
ipaddress ; python_version < '3.0'
|
||||||
|
|
||||||
|
freezegun == 0.3.10 ; python_version < '2.7'
|
||||||
|
freezegun ; python_version >= '2.7'
|
||||||
unittest2 ; python_version < '2.7'
|
unittest2 ; python_version < '2.7'
|
||||||
importlib ; python_version < '2.7'
|
importlib ; python_version < '2.7'
|
||||||
|
|
Loading…
Reference in New Issue