diff --git a/amber/src/main/python/core/models/tuple.py b/amber/src/main/python/core/models/tuple.py index 1f319b6a4f4..c585bf0a4a8 100644 --- a/amber/src/main/python/core/models/tuple.py +++ b/amber/src/main/python/core/models/tuple.py @@ -24,6 +24,7 @@ import typing from collections import OrderedDict from copy import deepcopy as _deepcopy +from dateutil.tz import tzlocal from loguru import logger from pandas._libs.missing import checknull from pympler import asizeof @@ -472,7 +473,9 @@ def __hash__(self) -> int: AttributeType.LONG: lambda f: java_hash_long(f), AttributeType.DOUBLE: lambda f: java_hash_long(double_to_long(f)), AttributeType.STRING: lambda f: java_hash_bytes(map(ord, f), 0, salt), - AttributeType.TIMESTAMP: lambda f: java_hash_long(int(f.timestamp())), + AttributeType.TIMESTAMP: lambda f: java_hash_long( + int((f if f.tzinfo else f.replace(tzinfo=tzlocal())).timestamp()) + ), AttributeType.BINARY: lambda f: java_hash_bytes(f, 1, salt), } diff --git a/amber/src/test/python/core/models/test_tuple.py b/amber/src/test/python/core/models/test_tuple.py index aff43faa881..7b7be27e191 100644 --- a/amber/src/test/python/core/models/test_tuple.py +++ b/amber/src/test/python/core/models/test_tuple.py @@ -540,7 +540,10 @@ def test_hash(self): "col-bool": True, "col-long": -8965536434247, "col-double": 1 / 3, - "col-timestamp": datetime.datetime.fromtimestamp(-1990), + "col-timestamp": datetime.datetime( + 1970, 1, 1, tzinfo=datetime.timezone.utc + ) + - datetime.timedelta(seconds=1990), "col-binary": None, }, schema, @@ -561,6 +564,14 @@ def test_hash(self): ) assert hash(tuple5) == -2099556631 # calculated with Java + def test_hash_supports_local_epoch_timestamp(self): + tuple_ = Tuple( + {"value": datetime.datetime.fromtimestamp(0)}, + Schema(raw_schema={"value": "TIMESTAMP"}), + ) + + assert hash(tuple_) == 31 + def test_tuple_with_large_binary(self): """Test tuple with largebinary field.""" from core.models.type.large_binary import largebinary