fix(common/time_utils): correct None/empty timestamp fallback and ISO 8601 parsing (#16483)

Recovery PR for #16173 after the fork branch was accidentally reset
during rewrite-cleanup.

Cherry-picked onto current `main`:
- fix(common/time_utils): correct fallback timestamp and ISO-8601
normalization
- fix(common/time_utils): preserve zero timestamps and mark regression
tests
- test(common/time_utils): make fallback assertions deterministic

Supersedes closed #16173 — same branch
`Harsh23Kashyap/fix/time-utils-edgecases`, rebuilt per @yuzhichang
recovery steps in
https://github.com/infiniflow/ragflow/pull/16173#issuecomment-4829663835

---------

Co-authored-by: Harsh Kashyap <harshkashyap@Harshs-MacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Harsh Kashyap
2026-06-30 20:00:44 +05:30
committed by GitHub
parent b53b693f22
commit 45fc7feab4
2 changed files with 68 additions and 9 deletions

View File

@@ -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

View File

@@ -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
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"