Skip to content

Commit 4d72b0c

Browse files
feat(CDF-19308): Add timezone as an optional param to WorkflowScheduledTriggerRule (#2200)
Co-authored-by: erlendvollset <erlendvollset@gmail.com>
1 parent 2f555aa commit 4d72b0c

7 files changed

Lines changed: 32 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ Changes are grouped as follows
1717
- `Fixed` for any bug fixes.
1818
- `Security` in case of vulnerabilities.
1919

20+
## [7.83.0] - 2025-08-28
21+
### Added
22+
- Add `timezone` as an optional param to the WorkflowScheduledTriggerRule.
23+
2024
## [7.82.1] - 2025-08-28
2125
### Fixed
2226
- Fix documentation of files.upload_content. It does not support directories. Use more meaningful errors when the path is not a file.

cognite/client/_api/workflows.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,12 @@ def upsert(
8181
8282
>>> from cognite.client import CogniteClient
8383
>>> from cognite.client.data_classes.workflows import WorkflowTriggerUpsert, WorkflowScheduledTriggerRule
84+
>>> from zoneinfo import ZoneInfo
8485
>>> client = CogniteClient()
8586
>>> client.workflows.triggers.upsert(
8687
... WorkflowTriggerUpsert(
8788
... external_id="my_trigger",
88-
... trigger_rule=WorkflowScheduledTriggerRule(cron_expression="0 0 * * *"),
89+
... trigger_rule=WorkflowScheduledTriggerRule(cron_expression="0 0 * * *", timezone=ZoneInfo("UTC")),
8990
... workflow_external_id="my_workflow",
9091
... workflow_version="1",
9192
... input={"a": 1, "b": 2},

cognite/client/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from __future__ import annotations
22

3-
__version__ = "7.82.1"
3+
__version__ = "7.83.0"
44

55
__api_subversion__ = "20230101"

cognite/client/data_classes/workflows.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
if TYPE_CHECKING:
3030
from cognite.client import CogniteClient
31+
from zoneinfo import ZoneInfo
3132

3233
TaskStatus: TypeAlias = Literal[
3334
"in_progress",
@@ -1415,16 +1416,30 @@ class WorkflowScheduledTriggerRule(WorkflowTriggerRule):
14151416
14161417
Args:
14171418
cron_expression (str): The cron specification for the scheduled trigger.
1419+
timezone (ZoneInfo | None): The timezone in which the scheduled trigger should be evaluated.
1420+
If not provided, UTC will be used as the default timezone on the server side.
14181421
"""
14191422

14201423
_trigger_type = "schedule"
14211424

1422-
def __init__(self, cron_expression: str) -> None:
1425+
def __init__(self, cron_expression: str, timezone: ZoneInfo | None = None) -> None:
14231426
self.cron_expression = cron_expression
1427+
self.timezone = timezone
1428+
1429+
def dump(self, camel_case: bool = True) -> dict[str, Any]:
1430+
# Override dump to handle timezone field specially:
1431+
# 1. Only include timezone key when it has a value (avoid "timezone": null)
1432+
# 2. Convert ZoneInfo object to its string key representation
1433+
item = super().dump(camel_case)
1434+
if self.timezone:
1435+
item["timezone"] = self.timezone.key
1436+
return item
14241437

14251438
@classmethod
14261439
def _load_trigger(cls, data: dict) -> WorkflowScheduledTriggerRule:
1427-
return cls(cron_expression=data["cronExpression"])
1440+
# Convert timezone to ZoneInfo
1441+
timezone = ZoneInfo(data["timezone"]) if "timezone" in data else None
1442+
return cls(cron_expression=data["cronExpression"], timezone=timezone)
14281443

14291444

14301445
class WorkflowDataModelingTriggerRule(WorkflowTriggerRule):
@@ -1525,6 +1540,7 @@ def dump(self, camel_case: bool = True) -> dict[str, Any]:
15251540
"workflow_external_id": self.workflow_external_id,
15261541
"workflow_version": self.workflow_version,
15271542
}
1543+
15281544
if self.input:
15291545
item["input"] = self.input
15301546
if self.metadata:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "cognite-sdk"
3-
version = "7.82.1"
3+
version = "7.83.0"
44

55
description = "Cognite Python SDK"
66
readme = "README.md"

tests/tests_integration/test_api/test_workflows.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import time
44
import unittest
5+
from zoneinfo import ZoneInfo
56

67
import pytest
78

@@ -593,7 +594,7 @@ def test_create_update_scheduled_trigger(
593594
created = cognite_client.workflows.triggers.upsert(existing)
594595

595596
update = WorkflowTriggerUpsert._load(existing.dump())
596-
new_rule = WorkflowScheduledTriggerRule(cron_expression="0 * * * *")
597+
new_rule = WorkflowScheduledTriggerRule(cron_expression="0 * * * *", timezone=ZoneInfo("Europe/Oslo"))
597598
update.trigger_rule = new_rule
598599

599600
updated = cognite_client.workflows.triggers.upsert(update)

tests/utils.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from pathlib import Path
1919
from types import UnionType
2020
from typing import TYPE_CHECKING, Any, Literal, TypeVar, cast, get_args, get_origin, get_type_hints
21+
from zoneinfo import ZoneInfo
2122

2223
from cognite.client import CogniteClient
2324
from cognite.client._api_client import APIClient
@@ -538,6 +539,9 @@ def create_value(self, type_: Any, var_name: str | None = None) -> Any:
538539
return {self._random_string(10): self._random_string(10) for _ in range(self._random.randint(1, 3))}
539540
elif type_ is CogniteClient:
540541
return self._cognite_client
542+
elif type_ is ZoneInfo:
543+
# Special case for ZoneInfo - provide a default timezone
544+
return ZoneInfo("UTC")
541545
elif inspect.isclass(type_) and any(base is abc.ABC for base in type_.__bases__):
542546
implementations = all_concrete_subclasses(type_)
543547
if type_ is Filter:

0 commit comments

Comments
 (0)