This is an automated email from the ASF dual-hosted git repository.

blue pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iceberg.git


The following commit(s) were added to refs/heads/master by this push:
     new 167a8ccd7c Python: Support creating a DateLiteral from a date (#6123)
167a8ccd7c is described below

commit 167a8ccd7c578296c40f8fc61c90135e71cf1183
Author: Douglas Drinka <[email protected]>
AuthorDate: Sun Nov 6 17:28:51 2022 -0700

    Python: Support creating a DateLiteral from a date (#6123)
    
    Closes #6120.
---
 python/pyiceberg/expressions/literals.py  |  9 ++++++++-
 python/pyiceberg/utils/datetime.py        |  7 ++++++-
 python/tests/expressions/test_literals.py | 12 ++++++++++++
 python/tests/test_transforms.py           | 11 +++++++----
 4 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/python/pyiceberg/expressions/literals.py 
b/python/pyiceberg/expressions/literals.py
index 458cbda41d..ac4c0711a9 100644
--- a/python/pyiceberg/expressions/literals.py
+++ b/python/pyiceberg/expressions/literals.py
@@ -23,6 +23,7 @@ from __future__ import annotations
 
 import struct
 from abc import ABC, abstractmethod
+from datetime import date
 from decimal import ROUND_HALF_UP, Decimal
 from functools import singledispatch, singledispatchmethod
 from typing import (
@@ -50,6 +51,7 @@ from pyiceberg.types import (
     UUIDType,
 )
 from pyiceberg.utils.datetime import (
+    date_str_to_days,
     date_to_days,
     micros_to_days,
     time_to_micros,
@@ -164,6 +166,11 @@ def _(value: Decimal) -> Literal[Decimal]:
     return DecimalLiteral(value)
 
 
[email protected](date)
+def _(value: date) -> Literal[int]:
+    return DateLiteral(date_to_days(value))
+
+
 class AboveMax(Singleton):
     @property
     def value(self):
@@ -395,7 +402,7 @@ class StringLiteral(Literal[str]):
     @to.register(DateType)
     def _(self, type_var: DateType) -> Optional[Literal[int]]:
         try:
-            return DateLiteral(date_to_days(self.value))
+            return DateLiteral(date_str_to_days(self.value))
         except (TypeError, ValueError):
             return None
 
diff --git a/python/pyiceberg/utils/datetime.py 
b/python/pyiceberg/utils/datetime.py
index 76a5e9d484..31a8e6193d 100644
--- a/python/pyiceberg/utils/datetime.py
+++ b/python/pyiceberg/utils/datetime.py
@@ -47,11 +47,16 @@ def micros_to_time(micros: int) -> time:
     return time(hour=hours, minute=minutes, second=seconds, 
microsecond=microseconds)
 
 
-def date_to_days(date_str: str) -> int:
+def date_str_to_days(date_str: str) -> int:
     """Converts an ISO-8601 formatted date to days from 1970-01-01"""
     return (date.fromisoformat(date_str) - EPOCH_DATE).days
 
 
+def date_to_days(date_val: date) -> int:
+    """Converts a Python date object to days from 1970-01-01"""
+    return (date_val - EPOCH_DATE).days
+
+
 def days_to_date(days: int) -> date:
     """Creates a date from the number of days from 1970-01-01"""
     return EPOCH_DATE + timedelta(days)
diff --git a/python/tests/expressions/test_literals.py 
b/python/tests/expressions/test_literals.py
index 019c925bfc..f34c8ae683 100644
--- a/python/tests/expressions/test_literals.py
+++ b/python/tests/expressions/test_literals.py
@@ -339,6 +339,17 @@ def test_string_to_decimal_literal():
 # MISC
 
 
+def test_python_date_conversion():
+    one_day_str = "2022-03-28"
+    one_day_date = datetime.date(2022, 3, 28)
+
+    from_str_lit = literal(one_day_str).to(DateType())
+    from_date_lit = literal(one_day_date)
+
+    assert isinstance(from_date_lit, DateLiteral)
+    assert from_str_lit == from_date_lit
+
+
 @pytest.mark.parametrize(
     "lit, primitive_type",
     [
@@ -348,6 +359,7 @@ def test_string_to_decimal_literal():
         (literal(34.11), FloatType()),
         (literal(3.5028235e38), DoubleType()),
         (literal(Decimal(34.55).quantize(Decimal("0.01"))), DecimalType(9, 2)),
+        (literal(datetime.date(2017, 8, 18)), DateType()),
         (literal("2017-08-18"), DateType()),
         (literal("14:21:01.919"), TimeType()),
         (literal("2017-08-18T14:21:01.919"), TimestampType()),
diff --git a/python/tests/test_transforms.py b/python/tests/test_transforms.py
index eec3e4aebe..3e4e63494a 100644
--- a/python/tests/test_transforms.py
+++ b/python/tests/test_transforms.py
@@ -15,6 +15,7 @@
 # specific language governing permissions and limitations
 # under the License.
 # pylint: disable=eval-used,protected-access
+from datetime import date
 from decimal import Decimal
 from uuid import UUID
 
@@ -51,6 +52,7 @@ from pyiceberg.types import (
     UUIDType,
 )
 from pyiceberg.utils.datetime import (
+    date_str_to_days,
     date_to_days,
     time_to_micros,
     timestamp_to_micros,
@@ -65,7 +67,8 @@ from pyiceberg.utils.iceberg_base_model import 
IcebergBaseModel
         (1, IntegerType(), 1392991556),
         (34, IntegerType(), 2017239379),
         (34, LongType(), 2017239379),
-        (date_to_days("2017-11-16"), DateType(), -653330422),
+        (date_to_days(date(2017, 11, 16)), DateType(), -653330422),
+        (date_str_to_days("2017-11-16"), DateType(), -653330422),
         (time_to_micros("22:31:08"), TimeType(), -662762989),
         (
             timestamp_to_micros("2017-11-16T22:31:08"),
@@ -144,15 +147,15 @@ def test_string_with_surrogate_pair():
 
 
 @pytest.mark.parametrize(
-    "date,date_transform,expected",
+    "date_val,date_transform,expected",
     [
         (47, YearTransform(), "2017"),
         (575, MonthTransform(), "2017-12"),
         (17501, DayTransform(), "2017-12-01"),
     ],
 )
-def test_date_to_human_string(date, date_transform, expected):
-    assert date_transform.to_human_string(DateType(), date) == expected
+def test_date_to_human_string(date_val, date_transform, expected):
+    assert date_transform.to_human_string(DateType(), date_val) == expected
 
 
 @pytest.mark.parametrize(

Reply via email to