Skip to content

Commit

Permalink
feat: add temporal operations (#832)
Browse files Browse the repository at this point in the history
Closes #XYZ

### Summary of Changes

<!-- Please provide a summary of changes in this pull request, ensuring
all changes are explained. -->

Added temporal operations to the temporal interface.

---------

Co-authored-by: megalinter-bot <[email protected]>
Co-authored-by: Lars Reimann <[email protected]>
Co-authored-by: Simon Breuer <[email protected]>
  • Loading branch information
4 people committed Jun 11, 2024
1 parent 3c6232e commit 06eab77
Show file tree
Hide file tree
Showing 8 changed files with 284 additions and 5 deletions.
18 changes: 18 additions & 0 deletions src/safeds/data/tabular/containers/_lazy_temporal_cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,24 @@ def __sizeof__(self) -> int:
# Temporal operations
# ------------------------------------------------------------------------------------------------------------------

def century(self) -> Cell[int]:
return _LazyCell(self._expression.dt.century())

def weekday(self) -> Cell[int]:
return _LazyCell(self._expression.dt.weekday())

def week(self) -> Cell[int]:
return _LazyCell(self._expression.dt.week())

def year(self) -> Cell[int]:
return _LazyCell(self._expression.dt.year())

def month(self) -> Cell[int]:
return _LazyCell(self._expression.dt.month())

def day(self) -> Cell[int]:
return _LazyCell(self._expression.dt.day())

def datetime_to_string(self, format_string: str = "%Y/%m/%d %H:%M:%S") -> Cell[str]:
if not _check_format_string(format_string):
raise ValueError("Invalid format string")
Expand Down
151 changes: 146 additions & 5 deletions src/safeds/data/tabular/containers/_temporal_cell.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,9 @@

class TemporalCell(ABC):
"""
A class that contains temporal methods for a column.
Namespace for operations on temporal data.
Parameters
----------
column:
The column to be operated on.
This class cannot be instantiated directly. It can only be accessed using the `dt` attribute of a cell.
Examples
--------
Expand All @@ -31,6 +28,150 @@ class TemporalCell(ABC):
+------------+
"""

@abstractmethod
def century(self) -> Cell[int]:
"""
Get the century of the underlying date(time) data.
Returns
-------
A cell containing the century as integer.
Examples
--------
>>> from safeds.data.tabular.containers import Column
>>> import datetime
>>> column = Column("example", [datetime.date(2022, 1, 1)])
>>> column.transform(lambda cell: cell.dt.century())
+---------+
| example |
| --- |
| i32 |
+=========+
| 21 |
+---------+
"""

@abstractmethod
def weekday(self) -> Cell[int]:
"""
Get the weekday of the underlying date(time) data.
Returns
-------
A cell containing the weekday as integer.
Examples
--------
>>> from safeds.data.tabular.containers import Column
>>> import datetime
>>> column = Column("example", [datetime.date(2022, 1, 1)])
>>> column.transform(lambda cell: cell.dt.weekday())
+---------+
| example |
| --- |
| i8 |
+=========+
| 6 |
+---------+
"""

@abstractmethod
def week(self) -> Cell[int]:
"""
Get the week of the underlying date(time) data.
Returns
-------
A cell containing the week as integer.
Examples
--------
>>> from safeds.data.tabular.containers import Column
>>> import datetime
>>> column = Column("example", [datetime.date(2022, 1, 1)])
>>> column.transform(lambda cell: cell.dt.week())
+---------+
| example |
| --- |
| i8 |
+=========+
| 52 |
+---------+
"""

@abstractmethod
def year(self) -> Cell[int]:
"""
Get the year of the underlying date(time) data.
Returns
-------
A cell containing the year as integer.
Examples
--------
>>> from safeds.data.tabular.containers import Column
>>> import datetime
>>> column = Column("example", [datetime.date(2022, 1, 9)])
>>> column.transform(lambda cell: cell.dt.year())
+---------+
| example |
| --- |
| i32 |
+=========+
| 2022 |
+---------+
"""

@abstractmethod
def month(self) -> Cell[int]:
"""
Get the month of the underlying date(time) data.
Returns
-------
A cell containing the month as integer.
Examples
--------
>>> from safeds.data.tabular.containers import Column
>>> import datetime
>>> column = Column("example", [datetime.date(2022, 1, 9)])
>>> column.transform(lambda cell: cell.dt.month())
+---------+
| example |
| --- |
| i8 |
+=========+
| 1 |
+---------+
"""

@abstractmethod
def day(self) -> Cell[int]:
"""
Get the day of the underlying date(time) data.
Returns
-------
A cell containing the day as integer.
Examples
--------
>>> from safeds.data.tabular.containers import Column
>>> import datetime
>>> column = Column("example", [datetime.date(2022, 1, 9)])
>>> column.transform(lambda cell: cell.dt.day())
+---------+
| example |
| --- |
| i8 |
+=========+
| 9 |
+---------+
"""

@abstractmethod
def datetime_to_string(self, format_string: str = "%Y/%m/%d %H:%M:%S") -> Cell[str]:
"""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import datetime

import pytest

from tests.helpers import assert_cell_operation_works


@pytest.mark.parametrize(
("expected", "input_date"),
[
(18, datetime.datetime(1800, 1, 9, 23, 29, 1, tzinfo=datetime.UTC)),
(21, datetime.date(2022, 1, 1)),
],
ids=[
"ISO datetime",
"ISO date",
],
)
def test_get_day(input_date: datetime.date, expected: bool) -> None:
assert_cell_operation_works(input_date, lambda cell: cell.dt.century(), expected)
20 changes: 20 additions & 0 deletions tests/safeds/data/tabular/containers/_temporal_cell/test_day.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import datetime

import pytest

from tests.helpers import assert_cell_operation_works


@pytest.mark.parametrize(
("expected", "input_date"),
[
(9, datetime.datetime(2022, 1, 9, 23, 29, 1, tzinfo=datetime.UTC)),
(1, datetime.date(2022, 1, 1)),
],
ids=[
"ISO datetime",
"ISO date",
],
)
def test_get_day(input_date: datetime.date, expected: bool) -> None:
assert_cell_operation_works(input_date, lambda cell: cell.dt.day(), expected)
20 changes: 20 additions & 0 deletions tests/safeds/data/tabular/containers/_temporal_cell/test_month.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import datetime

import pytest

from tests.helpers import assert_cell_operation_works


@pytest.mark.parametrize(
("expected", "input_date"),
[
(3, datetime.datetime(2022, 3, 9, 23, 29, 1, tzinfo=datetime.UTC)),
(1, datetime.date(2022, 1, 1)),
],
ids=[
"ISO datetime",
"ISO date",
],
)
def test_get_month(input_date: datetime.date, expected: bool) -> None:
assert_cell_operation_works(input_date, lambda cell: cell.dt.month(), expected)
20 changes: 20 additions & 0 deletions tests/safeds/data/tabular/containers/_temporal_cell/test_week.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import datetime

import pytest

from tests.helpers import assert_cell_operation_works


@pytest.mark.parametrize(
("expected", "input_date"),
[
(10, datetime.datetime(2023, 3, 9, 23, 29, 1, tzinfo=datetime.UTC)),
(52, datetime.date(2022, 1, 1)),
],
ids=[
"ISO datetime",
"ISO date",
],
)
def test_get_week(input_date: datetime.date, expected: bool) -> None:
assert_cell_operation_works(input_date, lambda cell: cell.dt.week(), expected)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import datetime

import pytest

from tests.helpers import assert_cell_operation_works


@pytest.mark.parametrize(
("expected", "input_date"),
[
(4, datetime.datetime(2023, 3, 9, 23, 29, 1, tzinfo=datetime.UTC)),
(6, datetime.date(2022, 1, 1)),
],
ids=[
"ISO datetime",
"ISO date",
],
)
def test_get_weekday(input_date: datetime.date, expected: bool) -> None:
assert_cell_operation_works(input_date, lambda cell: cell.dt.weekday(), expected)
20 changes: 20 additions & 0 deletions tests/safeds/data/tabular/containers/_temporal_cell/test_year.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import datetime

import pytest

from tests.helpers import assert_cell_operation_works


@pytest.mark.parametrize(
("expected", "input_date"),
[
(2023, datetime.datetime(2023, 3, 9, 23, 29, 1, tzinfo=datetime.UTC)),
(2022, datetime.date(2022, 1, 1)),
],
ids=[
"ISO datetime",
"ISO date",
],
)
def test_get_year(input_date: datetime.date, expected: bool) -> None:
assert_cell_operation_works(input_date, lambda cell: cell.dt.year(), expected)

0 comments on commit 06eab77

Please sign in to comment.