Skip to content

Commit 12330a5

Browse files
authored
Fix: Use midnight UTC for date-only CLI timestamps instead of current time (#220)
2 parents e29b0b3 + 6bb7e1c commit 12330a5

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

RELEASE_NOTES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
- `filter_queries` parameter supports text-based filtering on dispatch `id` and `type` fields
1616
- Query format: IDs are prefixed with `#` (e.g., `#4`), types are matched as substrings (e.g., `bar` matches `foobar`)
1717
- Multiple queries are combined with logical OR
18+
* Date-only inputs in CLI timestamps now default to midnight UTC instead of using the current time.
1819

1920
## Bug Fixes
2021

src/frequenz/client/dispatch/_cli_types.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ def convert(
5757
if parse_status == 0:
5858
self.fail(f"Invalid time expression: {value}", param, ctx)
5959

60+
# Check if only a date was provided (no time component)
61+
# parsedatetime returns status 1 for date-only parsing
62+
if parse_status == 1:
63+
# Set time to midnight in UTC for date-only inputs
64+
# First convert to UTC, then set time to midnight
65+
parsed_dt = parsed_dt.astimezone(timezone.utc).replace(
66+
hour=0, minute=0, second=0, microsecond=0
67+
)
68+
6069
return cast(datetime, parsed_dt.astimezone(timezone.utc))
6170
except Exception as e: # pylint: disable=broad-except
6271
self.fail(

tests/test_cli.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
ElectricalComponentCategory,
1818
)
1919
from frequenz.client.dispatch.__main__ import cli
20+
from frequenz.client.dispatch._cli_types import FuzzyDateTime
2021
from frequenz.client.dispatch.recurrence import (
2122
EndCriteria,
2223
Frequency,
@@ -739,3 +740,30 @@ async def test_delete_command(
739740
assert expected_output in result.output
740741
if dispatches:
741742
assert len(fake_client.dispatches(MicrogridId(1))) == 0
743+
744+
745+
def test_fuzzy_datetime_date_only() -> None:
746+
"""Test that date-only inputs are parsed as midnight."""
747+
fuzzy_dt = FuzzyDateTime()
748+
749+
# Test date-only input
750+
result = fuzzy_dt.convert("2025-08-06", None, None)
751+
assert isinstance(result, datetime)
752+
# Check that time is set to midnight in UTC (accounting for timezone conversion)
753+
# For Europe/Berlin (UTC+2), midnight local time becomes 22:00 UTC previous day
754+
assert result.hour in [
755+
0,
756+
22,
757+
] # Could be 0 (UTC) or 22 (UTC for Europe/Berlin midnight)
758+
assert result.minute == 0
759+
assert result.second == 0
760+
assert result.microsecond == 0
761+
762+
# Test date-time input (should preserve time)
763+
result_with_time = fuzzy_dt.convert("2025-08-06 14:30:15", None, None)
764+
assert isinstance(result_with_time, datetime)
765+
# Time should be preserved (accounting for timezone conversion)
766+
# For Europe/Berlin (UTC+2), 14:30 local becomes 12:30 UTC
767+
assert result_with_time.hour in [12, 14] # Could be 12 (UTC) or 14 (local)
768+
assert result_with_time.minute == 30
769+
assert result_with_time.second == 15

0 commit comments

Comments
 (0)