Search code examples
pythonnumpynetcdfpython-xarray

How to convert array of float into 365-calendar daytime? (excluding leap year)


I have a nc file in which the day unit is off.

<xarray.DataArray 'days' (time: 6570)>
array([730817., 730818., 730819., ..., 737384., 737385., 737386.])
Dimensions without coordinates: time
Attributes:
    units:      days_since_Jan11900
    long_name:  calendar_days

I want to convert these into a date without taking leap year into consideration, as my data is on a 365-day-a-year calendar, meaning there is no such thing as a leap year in the dataset. I have tried this

ds['days'] = ds.days - 730817
ds.days.attrs['units'] = 'days since 2001-05-30'

But, the leap year in 2004 then gives me one day earlier than the previous three years. Hence, it begins on May 29th but that is not correct, as it is actually May 30th due to the 365-day-a-year-calendar. What I want is my time unit to constantly show a period ranging from May 30th to Aug 18th, 2001, May 30th to Aug 18th, 2002, and so on even in leap years. So basically substitute my ranges with:

<xarray.DataArray 'days' (time: 6570)>
array([30-05-2001, 31-05-2001, ..., 18-08-2001, ..., 18-08-2015, 30-05-2016, ...,])

How can I do that?

EDIT I now tried to include @spencerkclark's method.

ds['days'] = ds.days - 730817
ds.days.attrs['units'] = 'days since 2001-05-30'
ds['days'].attrs['calender'] = 'noleap'
ds = xr.decode_cf(ds)

But, I still get Feb 29th in the leap years. Therefore, my very last date is shifted backwards to 2099-11-02 while it should stay at 2099-12-31. So not entirely fixed, unfortunately.


Solution

  • Add a calendar attribute to the 'days' coordinate and xarray will decode the times assuming a 'noleap' calendar into cftime.DatetimeNoLeap objects:

    ds['days'].attrs['calendar'] = 'noleap'
    ds = xr.decode_cf(ds)