Skip to content

[BUG] Resampled/CMORised time axis off by ~1 day for pre-1582 dates (GREGORIAN vs proleptic_gregorian) #461

Description

@rhaegar325

Summary

The WCRP CMIP6 compliance check [TIME001] Check Time Squareness fails on CMORised
ocean output for ACCESS-ESM1-5, with the time coordinate off by exactly one day:

[TIME001] Check Time Squareness
* Mismatch at index 0: expected 36706.500000, got 36707.500000.
  (table_id=Oyr, frequency=yr, var=no3, midpoint=True)

The numeric time values (and their bounds) are computed in the mixed Julian/Gregorian
"standard" calendar
, but the file ultimately declares proleptic_gregorian, so for
dates before the 1582 Julian→Gregorian reform the two disagree by ~1 day.

The same root cause produces a related CF §7.1 finding:

'time_bnds' has attr 'calendar' with value 'GREGORIAN' that does not agree with
its associated variable ('time')'s attr value 'proleptic_gregorian'

Root cause

ACCESS-ESM1-5 model files label their time axis with the non-CF calendar name
"GREGORIAN"
. Two pieces of code interpret this label inconsistently:

  1. base.CMORiser._check_calendar() rewrites "GREGORIAN""proleptic_gregorian"
    (a documented TODO workaround for the model's mislabelling). It changes only the
    label, not the numeric values
    — which is correct, because the model's values are
    genuinely proleptic-Gregorian (the model has no Julian transition).

  2. utilities.calculate_time_bounds() and the resampling midpoint helper
    (_shift_resampled_time_to_period_midpoint) read the raw "GREGORIAN" label and pass
    it to cftime, which treats "GREGORIAN" as the CF standard calendar
    (Julian before 1582-10-15). They therefore build the year/period boundaries — and the
    yearly midpoint — in the Julian frame.

For year 0101 this gives:

Quantity standard / Julian (what we compute) proleptic_gregorian (what the file declares & the checker expects)
0101-01-01 (days since 0001-01-01) 36525 36524
Yearly midpoint 36707.5 36706.5

The 1-day gap is exactly the Julian-vs-proleptic leap-day difference accumulated over
years 1–101 (Julian counts year 100 as a leap year; proleptic_gregorian does not).

The checker validates against the file's declared calendar (proleptic_gregorian), so it
expects 36706.5 and flags our 36707.5.

Impact

  • [TIME001] fails for all CMORised ACCESS-ESM1-5 output whose time axis falls before
    1582 (e.g. piControl/historical spin-up years like 0101).
  • CF §7.1 reports a time_bnds vs time calendar mismatch (GREGORIAN vs
    proleptic_gregorian) for the same reason.
  • Post-1582 data is unaffected (the two calendars coincide), which is why the
    discrepancy is easy to miss.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions