diff --git a/common/time_utils.py b/common/time_utils.py index f501674e8c..50ea2bcaf1 100644 --- a/common/time_utils.py +++ b/common/time_utils.py @@ -46,8 +46,9 @@ def timestamp_to_date(timestamp, format_string="%Y-%m-%d %H:%M:%S"): >>> timestamp_to_date(1704067200000) '2024-01-01 08:00:00' """ - if not timestamp: - timestamp = time.time() + if timestamp is None or timestamp == "": + timestamp = current_timestamp() + logging.debug("timestamp_to_date received empty timestamp; using current_timestamp() fallback") timestamp = int(timestamp) / 1000 time_array = time.localtime(timestamp) str_date = time.strftime(format_string, time_array) @@ -144,11 +145,8 @@ def format_iso_8601_to_ymd_hms(time_str: str) -> str: from dateutil import parser try: - if parser.isoparse(time_str): - dt = datetime.datetime.fromisoformat(time_str.replace("Z", "+00:00")) - return dt.strftime("%Y-%m-%d %H:%M:%S") - else: - return time_str + dt = parser.isoparse(time_str) + return dt.strftime("%Y-%m-%d %H:%M:%S") except Exception as e: logging.error(str(e)) return time_str diff --git a/test/unit_test/common/test_time_utils.py b/test/unit_test/common/test_time_utils.py index 6a622e798a..c7142df5bc 100644 --- a/test/unit_test/common/test_time_utils.py +++ b/test/unit_test/common/test_time_utils.py @@ -17,7 +17,7 @@ import time import datetime import pytest -from common.time_utils import current_timestamp, timestamp_to_date, date_string_to_timestamp, datetime_format, delta_seconds +from common.time_utils import current_timestamp, timestamp_to_date, date_string_to_timestamp, datetime_format, delta_seconds, format_iso_8601_to_ymd_hms class TestCurrentTimestamp: @@ -650,4 +650,65 @@ class TestDeltaSeconds: # If we're testing on the first day of month date_string = "2024-01-31 12:00:00" # Use a known past date result = delta_seconds(date_string) - assert result > 0 \ No newline at end of file + assert result > 0 + + +@pytest.mark.p2 +class TestTimestampToDateCurrentTimeFallback: + """Regression tests for the None/empty fallback of timestamp_to_date. + + The docstring promises "If None or empty, uses current time", but the + fallback assigned ``time.time()`` (seconds) and then divided by 1000 again, + producing a date around 1970-01-21 instead of now. The existing + ``test_return_type_always_string`` only checks the return type, so it never + caught this. These tests pin the behaviour by value. + """ + + def test_none_uses_current_time(self, monkeypatch): + """None input must resolve to current_timestamp() fallback.""" + fixed_ms = 1704067200123 + monkeypatch.setattr("common.time_utils.current_timestamp", lambda: fixed_ms) + assert timestamp_to_date(None) == time.strftime( + "%Y-%m-%d %H:%M:%S", time.localtime(fixed_ms / 1000) + ) + + def test_empty_string_uses_current_time(self, monkeypatch): + """Empty-string input must resolve to current_timestamp() fallback.""" + fixed_ms = 1704067200123 + monkeypatch.setattr("common.time_utils.current_timestamp", lambda: fixed_ms) + assert timestamp_to_date("") == time.strftime( + "%Y-%m-%d %H:%M:%S", time.localtime(fixed_ms / 1000) + ) + + def test_zero_timestamp_is_not_treated_as_empty(self): + """Zero timestamp should map to Unix epoch, not fallback to current time.""" + assert timestamp_to_date(0) == time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(0)) + + +@pytest.mark.p2 +class TestFormatIso8601ToYmdHms: + """Test cases for format_iso_8601_to_ymd_hms function.""" + + def test_standard_utc_z(self): + """Standard UTC timestamp with trailing Z.""" + assert format_iso_8601_to_ymd_hms("2024-01-01T12:00:00Z") == "2024-01-01 12:00:00" + + def test_explicit_utc_offset(self): + """Timestamp with an explicit +00:00 offset.""" + assert format_iso_8601_to_ymd_hms("2024-01-01T12:00:00+00:00") == "2024-01-01 12:00:00" + + def test_ordinal_date_extended(self): + """ISO 8601 ordinal date (day-of-year), extended form. + + dateutil.isoparse accepts it but datetime.fromisoformat rejects it, + which previously made the function silently return the input unchanged. + """ + assert format_iso_8601_to_ymd_hms("2024-001T12:00:00Z") == "2024-01-01 12:00:00" + + def test_ordinal_date_basic(self): + """ISO 8601 ordinal date (day-of-year), basic form.""" + assert format_iso_8601_to_ymd_hms("2024001T120000Z") == "2024-01-01 12:00:00" + + def test_invalid_string_returns_original(self): + """Unparseable input is returned unchanged.""" + assert format_iso_8601_to_ymd_hms("not-a-date") == "not-a-date" \ No newline at end of file