From 7994dd2cbef4faf083fe64cb17a325f2e8df6c2d Mon Sep 17 00:00:00 2001 From: Dmitry Kropachev Date: Sat, 4 Jan 2025 19:26:33 -0400 Subject: [PATCH] Replace datetime.utcfromtimestamp It is depricated and to be removed soon. datetime.fromtimestamp either include timezone into datetime, which we do not want, or offset datetime from utc. So, in order to have same behavior we have to ship separate function that provides same results as datetime.utcfromtimestamp --- cassandra/cqlengine/columns.py | 4 ++-- cassandra/query.py | 2 +- cassandra/util.py | 11 ++++++++++- .../integration/cqlengine/columns/test_validation.py | 7 ++++--- tests/integration/cqlengine/model/test_model_io.py | 8 ++++---- tests/integration/cqlengine/model/test_udts.py | 6 +++--- tests/unit/test_types.py | 6 +++--- 7 files changed, 27 insertions(+), 17 deletions(-) diff --git a/cassandra/cqlengine/columns.py b/cassandra/cqlengine/columns.py index 4adb88476..496e1d3fd 100644 --- a/cassandra/cqlengine/columns.py +++ b/cassandra/cqlengine/columns.py @@ -21,7 +21,7 @@ from cassandra.cqltypes import SimpleDateType, _cqltypes, UserType from cassandra.cqlengine import ValidationError from cassandra.cqlengine.functions import get_total_seconds -from cassandra.util import Duration as _Duration +from cassandra.util import Duration as _Duration, utcfromtimestamp log = logging.getLogger(__name__) @@ -551,7 +551,7 @@ def to_python(self, value): elif isinstance(value, date): return datetime(*(value.timetuple()[:6])) - return datetime.utcfromtimestamp(value) + return utcfromtimestamp(value) def to_database(self, value): value = super(DateTime, self).to_database(value) diff --git a/cassandra/query.py b/cassandra/query.py index f3922849a..d06f01529 100644 --- a/cassandra/query.py +++ b/cassandra/query.py @@ -26,7 +26,7 @@ import warnings from cassandra import ConsistencyLevel, OperationTimedOut -from cassandra.util import unix_time_from_uuid1, maybe_add_timeout_to_query +from cassandra.util import unix_time_from_uuid1, maybe_add_timeout_to_query, utcfromtimestamp from cassandra.encoder import Encoder import cassandra.encoder from cassandra.policies import ColDesc diff --git a/cassandra/util.py b/cassandra/util.py index c6e2f0eda..4a0ecd5bc 100644 --- a/cassandra/util.py +++ b/cassandra/util.py @@ -40,8 +40,17 @@ from cassandra import DriverException + +def utcfromtimestamp(timestamp): + """ + It replicates behavior of datetime.utcfromtimestamp + """ + dt = datetime.datetime.fromtimestamp(timestamp, datetime.timezone.utc) + return datetime.datetime(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, dt.microsecond, fold=dt.fold) + + DATETIME_EPOC = datetime.datetime(1970, 1, 1) -UTC_DATETIME_EPOC = datetime.datetime.utcfromtimestamp(0) +UTC_DATETIME_EPOC = utcfromtimestamp(0) _nan = float('nan') diff --git a/tests/integration/cqlengine/columns/test_validation.py b/tests/integration/cqlengine/columns/test_validation.py index 21fe1581f..33acb0df1 100644 --- a/tests/integration/cqlengine/columns/test_validation.py +++ b/tests/integration/cqlengine/columns/test_validation.py @@ -15,7 +15,7 @@ import unittest import sys -from datetime import datetime, timedelta, date, tzinfo, time +from datetime import datetime, timedelta, date, tzinfo, time, timezone from decimal import Decimal as D from uuid import uuid4, uuid1 from packaging.version import Version @@ -30,6 +30,7 @@ from cassandra.cqlengine.models import Model, ValidationError from cassandra.cqlengine.usertype import UserType from cassandra import util +from cassandra.util import utcfromtimestamp from tests.integration import PROTOCOL_VERSION, CASSANDRA_VERSION, greaterthanorequalcass30, greaterthanorequalcass3_11 from tests.integration.cqlengine.base import BaseCassEngTestCase @@ -97,7 +98,7 @@ def test_datetime_timestamp(self): dt_value = 1454520554 self.DatetimeTest.objects.create(test_id=5, created_at=dt_value) dt2 = self.DatetimeTest.objects(test_id=5).first() - self.assertEqual(dt2.created_at, datetime.utcfromtimestamp(dt_value)) + self.assertEqual(dt2.created_at, utcfromtimestamp(dt_value)) def test_datetime_large(self): dt_value = datetime(2038, 12, 31, 10, 10, 10, 123000) @@ -809,7 +810,7 @@ def test_conversion_specific_date(self): assert isinstance(uuid, UUID) ts = (uuid.time - 0x01b21dd213814000) / 1e7 # back to a timestamp - new_dt = datetime.utcfromtimestamp(ts) + new_dt = utcfromtimestamp(ts) # checks that we created a UUID1 with the proper timestamp assert new_dt == dt diff --git a/tests/integration/cqlengine/model/test_model_io.py b/tests/integration/cqlengine/model/test_model_io.py index 7195d685f..ad0a86df5 100644 --- a/tests/integration/cqlengine/model/test_model_io.py +++ b/tests/integration/cqlengine/model/test_model_io.py @@ -15,7 +15,7 @@ from uuid import uuid4, UUID import random -from datetime import datetime, date, time +from datetime import datetime, date, time, timezone from decimal import Decimal from operator import itemgetter @@ -26,7 +26,7 @@ from cassandra.cqlengine.management import drop_table from cassandra.cqlengine.models import Model from cassandra.query import SimpleStatement -from cassandra.util import Date, Time, Duration +from cassandra.util import Date, Time, Duration, utcfromtimestamp from cassandra.cqlengine.statements import SelectStatement, DeleteStatement, WhereClause from cassandra.cqlengine.operators import EqualsOperator @@ -200,13 +200,13 @@ class AllDatatypesModel(Model): sync_table(AllDatatypesModel) - input = ['ascii', 2 ** 63 - 1, bytearray(b'hello world'), True, datetime.utcfromtimestamp(872835240), + input = ['ascii', 2 ** 63 - 1, bytearray(b'hello world'), True, utcfromtimestamp(872835240), Decimal('12.3E+7'), 2.39, 3.4028234663852886e+38, '123.123.123.123', 2147483647, 'text', UUID('FE2B4360-28C6-11E2-81C1-0800200C9A66'), UUID('067e6162-3b6f-4ae2-a171-2470b63dff00'), int(str(2147483647) + '000')] AllDatatypesModel.create(id=0, a='ascii', b=2 ** 63 - 1, c=bytearray(b'hello world'), d=True, - e=datetime.utcfromtimestamp(872835240), f=Decimal('12.3E+7'), g=2.39, + e=utcfromtimestamp(872835240), f=Decimal('12.3E+7'), g=2.39, h=3.4028234663852886e+38, i='123.123.123.123', j=2147483647, k='text', l=UUID('FE2B4360-28C6-11E2-81C1-0800200C9A66'), m=UUID('067e6162-3b6f-4ae2-a171-2470b63dff00'), n=int(str(2147483647) + '000'), diff --git a/tests/integration/cqlengine/model/test_udts.py b/tests/integration/cqlengine/model/test_udts.py index 1e3adf9a7..721cf5ea7 100644 --- a/tests/integration/cqlengine/model/test_udts.py +++ b/tests/integration/cqlengine/model/test_udts.py @@ -13,7 +13,7 @@ # limitations under the License. import unittest -from datetime import datetime, date, time +from datetime import datetime, date, time, timezone from decimal import Decimal from mock import Mock from uuid import UUID, uuid4 @@ -23,7 +23,7 @@ from cassandra.cqlengine import columns, connection from cassandra.cqlengine.management import sync_table, drop_table, sync_type, create_keyspace_simple, drop_keyspace from cassandra.cqlengine import ValidationError -from cassandra.util import Date, Time +from cassandra.util import Date, Time, utcfromtimestamp from tests.integration import PROTOCOL_VERSION from tests.integration.cqlengine.base import BaseCassEngTestCase @@ -272,7 +272,7 @@ def test_can_insert_udts_with_all_datatypes(self): self.addCleanup(drop_table, AllDatatypesModel) input = AllDatatypes(a='ascii', b=2 ** 63 - 1, c=bytearray(b'hello world'), d=True, - e=datetime.utcfromtimestamp(872835240), f=Decimal('12.3E+7'), g=2.39, + e=utcfromtimestamp(872835240), f=Decimal('12.3E+7'), g=2.39, h=3.4028234663852886e+38, i='123.123.123.123', j=2147483647, k='text', l=UUID('FE2B4360-28C6-11E2-81C1-0800200C9A66'), m=UUID('067e6162-3b6f-4ae2-a171-2470b63dff00'), n=int(str(2147483647) + '000')) diff --git a/tests/unit/test_types.py b/tests/unit/test_types.py index a06bbd452..13b9f0677 100644 --- a/tests/unit/test_types.py +++ b/tests/unit/test_types.py @@ -41,7 +41,7 @@ from cassandra.util import ( OPEN_BOUND, Date, DateRange, DateRangeBound, DateRangePrecision, Time, ms_timestamp_from_datetime, - datetime_from_timestamp + datetime_from_timestamp, utcfromtimestamp ) from tests.unit.util import check_sequence_consistency @@ -200,7 +200,7 @@ def test_empty_value(self): def test_datetype(self): now_time_seconds = time.time() - now_datetime = datetime.datetime.utcfromtimestamp(now_time_seconds) + now_datetime = utcfromtimestamp(now_time_seconds) # Cassandra timestamps in millis now_timestamp = now_time_seconds * 1e3 @@ -211,7 +211,7 @@ def test_datetype(self): # deserialize # epoc expected = 0 - self.assertEqual(DateType.deserialize(int64_pack(1000 * expected), 0), datetime.datetime.utcfromtimestamp(expected)) + self.assertEqual(DateType.deserialize(int64_pack(1000 * expected), 0), utcfromtimestamp(expected)) # beyond 32b expected = 2 ** 33