From 54ee9118842aff350286950d1f067297629558e5 Mon Sep 17 00:00:00 2001 From: Nathan Stender Date: Tue, 7 Apr 2026 22:42:10 -0400 Subject: [PATCH] fix: Default to day-first format for invalid/unknown locales MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem Previously, when an invalid or unknown locale was provided, the code would catch the exception and default to month-first (American) format by returning False. This is incorrect because: 1. Most of the world uses day-first format (DD/MM/YYYY) 2. Only en_US and a few other locales use month-first (MM/DD/YYYY) 3. Defaulting to the less common format causes more parsing errors Example bug: - User provides locale "xyz_ABC" (typo or unknown locale) - Date "01/02/2023" gets parsed as January 2nd (month-first) - Should be parsed as February 1st (day-first, more common globally) ## Solution Changed the exception handler in `_should_use_day_first()` to return True (day-first) instead of False (month-first) for invalid locales. The logic now: - locale_str is None → False (backward compat, American default) - Valid locale → check Babel CLDR data - Invalid locale → True (day-first is global default) ## Testing - Updated test: `test_invalid_locale_returns_true()` - Added test: `test_invalid_locale_defaults_to_day_first()` - Confirms "01/02/2023" with invalid locale → February 1st (day-first) - All 19 timestamp parser tests pass Co-Authored-By: Claude Opus 4.1 --- .../parsers/utils/timestamp_parser.py | 6 +++-- tests/parsers/utils/timestamp_parser_test.py | 23 ++++++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/allotropy/parsers/utils/timestamp_parser.py b/src/allotropy/parsers/utils/timestamp_parser.py index 4d3e9f6b4..991fbac12 100644 --- a/src/allotropy/parsers/utils/timestamp_parser.py +++ b/src/allotropy/parsers/utils/timestamp_parser.py @@ -42,7 +42,7 @@ def _should_use_day_first(time_str: str, locale_str: str | None) -> bool: if re.match(r"^\d{4}[-/.]", time_str): return False - # Use locale data for non-ISO formats + # No locale specified: default to American format for backward compatibility if not locale_str: return False @@ -60,7 +60,9 @@ def _should_use_day_first(time_str: str, locale_str: str | None) -> bool: return False except Exception: - return False + # Invalid/unknown locale: default to day-first since most of the world uses it + # Only en_US and a few other locales use month-first (MM/DD/YYYY) + return True class TimestampParser: diff --git a/tests/parsers/utils/timestamp_parser_test.py b/tests/parsers/utils/timestamp_parser_test.py index a11037103..35ced26c8 100644 --- a/tests/parsers/utils/timestamp_parser_test.py +++ b/tests/parsers/utils/timestamp_parser_test.py @@ -42,9 +42,11 @@ def test_none_locale_returns_false(self) -> None: assert _should_use_day_first("01/15/2023", None) is False assert _should_use_day_first("15/01/2023", None) is False - def test_invalid_locale_returns_false(self) -> None: - # Invalid locales default to False - assert _should_use_day_first("01/15/2023", "invalid_LOCALE") is False + def test_invalid_locale_returns_true(self) -> None: + # Invalid/unknown locales default to day-first since most of world uses it + assert _should_use_day_first("01/15/2023", "invalid_LOCALE") is True + assert _should_use_day_first("15/01/2023", "xyz_ABC") is True + assert _should_use_day_first("01/02/2023", "not_a_real_locale") is True class TestTimestampParser: @@ -142,6 +144,21 @@ def test_parse_invalid_date_raises_error(self) -> None: ): parser.parse("not a date") + def test_invalid_locale_defaults_to_day_first(self) -> None: + """Invalid/unknown locales should default to day-first (most common globally).""" + parser = TimestampParser() + + # With an invalid locale, ambiguous dates should parse as day-first + # 01/02/2023 should be February 1st (day-first), not January 2nd + with set_locale_context("invalid_LOCALE"): + result = parser.parse("01/02/2023") + assert "2023-02-01" in result, "Invalid locale should default to day-first" + + # Another invalid locale - should still use day-first + with set_locale_context("xyz_ABC"): + result = parser.parse("15/01/2023") + assert "2023-01-15" in result, "Unknown locale should default to day-first" + def test_real_world_examples(self) -> None: """Test real-world date formats from various instruments.""" parser = TimestampParser()