-
Notifications
You must be signed in to change notification settings - Fork 44
Description
To report a non-security related issue, please provide:
-
the version of the software with which you are encountering an issue
cftime v1.6.4 -
environmental information (i.e. Operating System, compiler info, java version, python version, etc.)
python: 3.12.4 | packaged by conda-forge | (main, Jun 17 2024, 10:23:07) [GCC 12.3.0]
python-bits: 64
OS: Linux
OS-release: 5.14.21-150500.55.83-default
machine: x86_64
- a description of the issue with the steps needed to reproduce it
I'm trying to wrap my head around how cftime converts datetimes of different provencience to the numerical representation (via cftime.date2num). First a working example with python datetime and cftime datetime with standard and proleptic gregorian calendars. The output is as expected, two proleptic_gregorian and one standard calendar. Also the roundtrip works, when using the appropriate calendar.
import numpy as np
import cftime
# create dates
# 1 - python datetimes (proleptic_gregorian)
# 2 - cftime datetime standard-calendar
# 3 - cftime datetime proleptic_gregorian-calendar
dates1 = np.array(["0002"], dtype="datetime64[s]").astype("M8[us]").astype(datetime.datetime)
calendar1 ="standard"
calendar2 ="proleptic_gregorian"
dates2 = np.array([cftime.datetime(t0.year, t0.month, t0.day, calendar=calendar1) for t0 in dates1])
dates3 = np.array([cftime.datetime(t0.year, t0.month, t0.day, calendar=calendar2) for t0 in dates1])
print(dates1)
print(dates2)
print(dates3)
num1 = cftime.date2num(dates1, "seconds since 2000-01-01")
num2 = cftime.date2num(dates2, "seconds since 2000-01-01")
num3 = cftime.date2num(dates3, "seconds since 2000-01-01")
print(num1)
print(num2)
print(num3)
date1 = cftime.num2date(num1, "seconds since 2000-01-01", calendar2)
date2 = cftime.num2date(num2, "seconds since 2000-01-01", calendar1)
date3 = cftime.num2date(num3, "seconds since 2000-01-01", calendar2)
print(date1)
print(date2)
print(date3)Output
[datetime.datetime(2, 1, 1, 0, 0)]
[cftime.datetime(2, 1, 1, 0, 0, 0, 0, calendar='standard', has_year_zero=False)]
[cftime.datetime(2, 1, 1, 0, 0, 0, 0, calendar='proleptic_gregorian', has_year_zero=True)]
[-63050745600]
[-63050918400]
[-63050745600]
[cftime.DatetimeProlepticGregorian(2, 1, 1, 0, 0, 0, 0, has_year_zero=True)]
[cftime.DatetimeGregorian(2, 1, 1, 0, 0, 0, 0, has_year_zero=False)]
[cftime.DatetimeProlepticGregorian(2, 1, 1, 0, 0, 0, 0, has_year_zero=True)]Now, when selecting the output calendar this doesn't work anymore and a shift of two days occur for the python datetimes in the roundtrip:
import numpy as np
import cftime
# create dates
# 1 - python datetimes (proleptic_gregorian)
# 2 - cftime datetime standard-calendar
# 3 - cftime datetime proleptic_gregorian-calendar
dates1 = np.array(["0002"], dtype="datetime64[s]").astype("M8[us]").astype(datetime.datetime)
calendar1 ="standard"
calendar2 ="proleptic_gregorian"
dates2 = np.array([cftime.datetime(t0.year, t0.month, t0.day, calendar=calendar1) for t0 in dates1])
dates3 = np.array([cftime.datetime(t0.year, t0.month, t0.day, calendar=calendar2) for t0 in dates1])
print(dates1)
print(dates2)
print(dates3)
num1 = cftime.date2num(dates1, "seconds since 2000-01-01", calendar1)
num2 = cftime.date2num(dates2, "seconds since 2000-01-01", calendar1)
num3 = cftime.date2num(dates3, "seconds since 2000-01-01", calendar1)
print(num1)
print(num2)
print(num3)
date1 = cftime.num2date(num1, "seconds since 2000-01-01", calendar1)
date2 = cftime.num2date(num2, "seconds since 2000-01-01", calendar1)
date3 = cftime.num2date(num3, "seconds since 2000-01-01", calendar1)
print(date1)
print(date2)
print(date3)Output
[datetime.datetime(2, 1, 1, 0, 0)]
[cftime.datetime(2, 1, 1, 0, 0, 0, 0, calendar='standard', has_year_zero=False)]
[cftime.datetime(2, 1, 1, 0, 0, 0, 0, calendar='proleptic_gregorian', has_year_zero=True)]
[-63050745600]
[-63050918400]
[-63050918400]
[cftime.DatetimeGregorian(2, 1, 3, 0, 0, 0, 0, has_year_zero=False)]
[cftime.DatetimeGregorian(2, 1, 1, 0, 0, 0, 0, has_year_zero=False)]
[cftime.DatetimeGregorian(2, 1, 1, 0, 0, 0, 0, has_year_zero=False)]I'd expect that cftime correctly converts the python datetimes to the wanted output calendar. I did not find anything related in the documentation so any pointers are welcome.