Skip to content

Commit 3c02cf1

Browse files
committed
feat: add new granularities
JIRA: CQ-2758 risk: low
1 parent acfcc1a commit 3c02cf1

8 files changed

Lines changed: 62 additions & 2 deletions

File tree

packages/gooddata-flexconnect/json_schemas/execution-context/date-granularity.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,18 @@
55
"description": "All the supported granularities of the date attributes.",
66
"enum": [
77
"TIMESTAMP",
8+
"SECOND",
89
"MINUTE",
910
"HOUR",
1011
"DAY",
1112
"WEEK",
1213
"MONTH",
1314
"QUARTER",
1415
"YEAR",
16+
"SECOND_OF_MINUTE",
17+
"SECOND_OF_DAY",
1518
"MINUTE_OF_HOUR",
19+
"MINUTE_OF_DAY",
1620
"HOUR_OF_DAY",
1721
"DAY_OF_WEEK",
1822
"DAY_OF_MONTH",

packages/gooddata-pandas/src/gooddata_pandas/arrow_convertor.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def _get_date_converter_for_label(label_id: str, model_labels: dict):
6868
6969
- ``DAY`` / ``MONTH`` / ``YEAR`` → ``DateConverter`` (→ ``pandas.Timestamp`` via external fn)
7070
- ``WEEK`` / ``QUARTER`` → ``StringConverter`` (no-op)
71-
- ``MINUTE`` / ``HOUR`` → ``DatetimeConverter``
71+
- ``SECOND`` / ``MINUTE`` / ``HOUR`` → ``DatetimeConverter``
7272
- No granularity (text attrs) → ``None`` (caller skips conversion)
7373
"""
7474
info = model_labels.get(label_id, {})
@@ -84,6 +84,7 @@ def convert_label_values(label_id: str, values: list, model_labels: dict) -> lis
8484
Mirrors the non-Arrow execution path (``AttributeConverterStore`` in ``_typed_attribute_value``):
8585
8686
- ``DAY`` / ``MONTH`` / ``YEAR`` granularity → ``pandas.Timestamp``
87+
- ``SECOND`` / ``MINUTE`` / ``HOUR`` → ``pandas.Timestamp``
8788
- ``WEEK`` / ``QUARTER`` → ``str`` (unchanged)
8889
- No granularity (text attributes) → values returned as the **same object**
8990

packages/gooddata-pandas/tests/utils/test_utils.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,12 @@ def test_typed_attribute_values_batches_dates_to_timestamps():
5959
pandas.Timestamp("2023-01-01"),
6060
pandas.Timestamp("2023-03-01"),
6161
]
62+
assert _typed_attribute_values(
63+
_date_catalog_attribute("SECOND"), ["2026-07-31 12:34:56", "2026-12-31 23:59:59"]
64+
) == [
65+
pandas.Timestamp("2026-07-31 12:34:56"),
66+
pandas.Timestamp("2026-12-31 23:59:59"),
67+
]
6268

6369

6470
def test_typed_attribute_values_week_and_quarter_stay_strings():

packages/gooddata-sdk/src/gooddata_sdk/compute/model/filter.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ def __eq__(self, other: object) -> bool:
264264
"DAY",
265265
"HOUR",
266266
"MINUTE",
267+
"SECOND",
267268
"QUARTER_OF_YEAR",
268269
"MONTH_OF_YEAR",
269270
"WEEK_OF_YEAR",
@@ -272,6 +273,9 @@ def __eq__(self, other: object) -> bool:
272273
"DAY_OF_WEEK",
273274
"HOUR_OF_DAY",
274275
"MINUTE_OF_HOUR",
276+
"MINUTE_OF_DAY",
277+
"SECOND_OF_DAY",
278+
"SECOND_OF_MINUTE",
275279
"FISCAL_MONTH",
276280
"FISCAL_QUARTER",
277281
"FISCAL_YEAR",

packages/gooddata-sdk/src/gooddata_sdk/type_converter.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ def build_stores() -> None:
295295
AttributeConverterStore.register("DATE", IntegerConverter)
296296
AttributeConverterStore.register("DATE", StringConverter, ["WEEK", "QUARTER"])
297297
AttributeConverterStore.register("DATE", DateConverter, ["DAY", "MONTH", "YEAR"])
298-
AttributeConverterStore.register("DATE", DatetimeConverter, ["MINUTE", "HOUR"])
298+
AttributeConverterStore.register("DATE", DatetimeConverter, ["SECOND", "MINUTE", "HOUR"])
299299

300300
DBTypeConverterStore.register("date", DateConverter)
301301
DBTypeConverterStore.register("timestamp", DatetimeConverter)

packages/gooddata-sdk/src/gooddata_sdk/visualization.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"GDC.time.date": "DAY",
5050
"GDC.time.hour": "HOUR",
5151
"GDC.time.minute": "MINUTE",
52+
"GDC.time.second": "SECOND",
5253
"GDC.time.quarter_in_year": "QUARTER_OF_YEAR",
5354
"GDC.time.month_in_year": "MONTH_OF_YEAR",
5455
"GDC.time.week_in_year": "WEEK_OF_YEAR",
@@ -57,6 +58,9 @@
5758
"GDC.time.day_in_week": "DAY_OF_WEEK",
5859
"GDC.time.hour_in_day": "HOUR_OF_DAY",
5960
"GDC.time.minute_in_hour": "MINUTE_OF_HOUR",
61+
"GDC.time.minute_in_day": "MINUTE_OF_DAY",
62+
"GDC.time.second_in_day": "SECOND_OF_DAY",
63+
"GDC.time.second_in_minute": "SECOND_OF_MINUTE",
6064
"GDC.time.fiscal_month": "FISCAL_MONTH",
6165
"GDC.time.fiscal_quarter": "FISCAL_QUARTER",
6266
"GDC.time.fiscal_year": "FISCAL_YEAR",

packages/gooddata-sdk/tests/compute_model/test_date_filters.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,40 @@ def test_date_filters_description(scenario, filter, descriptions):
109109
def test_all_time_date_filter_is_noop_by_default():
110110
f = AllTimeDateFilter(dataset=ObjId(type="dataset", id="dataset.id"))
111111
assert f.is_noop()
112+
113+
114+
@pytest.mark.parametrize(
115+
"granularity",
116+
[
117+
"YEAR",
118+
"QUARTER",
119+
"MONTH",
120+
"WEEK",
121+
"DAY",
122+
"HOUR",
123+
"MINUTE",
124+
"SECOND",
125+
"QUARTER_OF_YEAR",
126+
"MONTH_OF_YEAR",
127+
"WEEK_OF_YEAR",
128+
"DAY_OF_YEAR",
129+
"DAY_OF_MONTH",
130+
"DAY_OF_WEEK",
131+
"HOUR_OF_DAY",
132+
"MINUTE_OF_HOUR",
133+
"MINUTE_OF_DAY",
134+
"SECOND_OF_DAY",
135+
"SECOND_OF_MINUTE",
136+
"FISCAL_MONTH",
137+
"FISCAL_QUARTER",
138+
"FISCAL_YEAR",
139+
],
140+
)
141+
def test_relative_date_filter_accepts_all_supported_granularities(granularity):
142+
f = RelativeDateFilter(
143+
dataset=ObjId(type="dataset", id="dataset.id"),
144+
granularity=granularity,
145+
from_shift=-30,
146+
to_shift=-1,
147+
)
148+
assert f.granularity == granularity

packages/gooddata-sdk/tests/test_type_converter.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ def test_to_type_ok(self):
6666
c = conv.DatetimeConverter()
6767
assert c.to_type(test_value) == datetime.datetime(2021, 10, 20, 11, 0)
6868

69+
def test_second_granularity_values_convert_to_datetime(self):
70+
c = conv.AttributeConverterStore.find_converter("DATE", "SECOND")
71+
assert c.to_type("2026-07-31 12:34:56") == datetime.datetime(2026, 7, 31, 12, 34, 56)
72+
6973
def test_to_type_wrong_val(self):
7074
test_value = "2021-10-20"
7175
c = conv.DatetimeConverter()

0 commit comments

Comments
 (0)