What happened?
When a case archive contains a date-only RUN_STARTDATE in env_run.xml, the ingested simulation_start_date can appear one day earlier after persistence or rendering.
Example:
env_run.xml contains <entry id="RUN_STARTDATE" value="2019-08-01" />
- the stored or rendered value shows
2019-07-31 17:00:00
The XML parser appears to read the correct date string. The shift likely happens later, when the backend converts the date-only value into a timezone-aware datetime and stores it in a timezone-aware database column. Database or browser-local timezone rendering can then show the previous calendar day.
Steps to reproduce
- Ingest an archive containing
env_run.xml with RUN_TYPE=startup and RUN_STARTDATE=2019-08-01.
- Inspect the created simulation record in PostgreSQL or in the UI.
- Observe that
simulation_start_date is shown as 2019-07-31 17:00:00, or otherwise resolves to the previous day in a timezone west of UTC.
What did you expect to happen?
simulation_start_date should preserve the calendar date from env_run.xml and remain 2019-08-01 regardless of database session timezone or browser locale.
Environment
- Repository:
E3SM-Project/simboard
- Area: backend ingestion, simulation persistence, and date rendering
- Observed from macOS on 2026-05-05
- Most likely reproducible in timezones west of UTC, such as
America/Los_Angeles during DST
Relevant code or screenshots
backend/app/features/ingestion/parsers/case_docs.py reads RUN_STARTDATE directly and returns the raw date string.
backend/app/features/ingestion/ingest.py::_parse_datetime_field parses date-only strings and assigns UTC to naive datetimes.
backend/app/features/simulation/models.py stores simulation_start_date as DateTime(timezone=True).
- Frontend date helpers construct
new Date(...) and format in local time, which can also surface the previous calendar day.
Anything else?
Likely root cause: a date-only field is being modeled as an absolute timestamp.
Potential fixes:
- Store
simulation_start_date and simulation_end_date as date-only values.
- Keep these fields timezone-neutral through API and UI formatting instead of converting them through local time.
A regression test should cover ingesting RUN_STARTDATE=2019-08-01 and asserting that the persisted and displayed calendar date remains 2019-08-01.
What happened?
When a case archive contains a date-only
RUN_STARTDATEinenv_run.xml, the ingestedsimulation_start_datecan appear one day earlier after persistence or rendering.Example:
env_run.xmlcontains<entry id="RUN_STARTDATE" value="2019-08-01" />2019-07-31 17:00:00The XML parser appears to read the correct date string. The shift likely happens later, when the backend converts the date-only value into a timezone-aware
datetimeand stores it in a timezone-aware database column. Database or browser-local timezone rendering can then show the previous calendar day.Steps to reproduce
env_run.xmlwithRUN_TYPE=startupandRUN_STARTDATE=2019-08-01.simulation_start_dateis shown as2019-07-31 17:00:00, or otherwise resolves to the previous day in a timezone west of UTC.What did you expect to happen?
simulation_start_dateshould preserve the calendar date fromenv_run.xmland remain2019-08-01regardless of database session timezone or browser locale.Environment
E3SM-Project/simboardAmerica/Los_Angelesduring DSTRelevant code or screenshots
backend/app/features/ingestion/parsers/case_docs.pyreadsRUN_STARTDATEdirectly and returns the raw date string.backend/app/features/ingestion/ingest.py::_parse_datetime_fieldparses date-only strings and assigns UTC to naive datetimes.backend/app/features/simulation/models.pystoressimulation_start_dateasDateTime(timezone=True).new Date(...)and format in local time, which can also surface the previous calendar day.Anything else?
Likely root cause: a date-only field is being modeled as an absolute timestamp.
Potential fixes:
simulation_start_dateandsimulation_end_dateas date-only values.A regression test should cover ingesting
RUN_STARTDATE=2019-08-01and asserting that the persisted and displayed calendar date remains2019-08-01.