convert "number of days since" to datetime, given 365-day and 360-day calendars (not Gregorian)
33 visualizzazioni (ultimi 30 giorni)
Hi, I have some regional climate model data that is dated by "days since 1949-12-1". None of the models use a Gregorian calendar (365/366 days/year depending on leap year). They either use a "365-day" calendar (no Feb 29 in any year) or "360-day" calendar (every month is exactly 30 days).
I found two functions in the Financial Toolbox that can generate the number of days between two dates, based on either a 365- or 360-day calendar (days365 and days360, respectively).
But I need to do the reverse. I have the number of days since a point in time, and I need the dates. I'm currently using "caldays", but it doesn't appear to have the calendar type as an option. This is the code I'm currently using, before I discovered the usage of different calendars:
var_time = importdata('var_time.txt');
base_date = datetime(1949,12,1);
% round 'time' attribute to nearest integer, add the number of days it
% represents to the baseline date, then extract the month and year from
% the new date generated
data_mx = day(base_date+caldays(floor(var_time))); % day of month
data_mx(:,2) = month(base_date+caldays(floor(var_time))); % month number
data_mx(:,3) = year(base_date+caldays(floor(var_time))); % year
% results in 365 days ending with 12/30/1952, a leap year
% should exclude 2/29/1952 and end with 12/31/1952
Anyone know of any Matlab functions I'm missing, or coding ideas to accomplish this?
UPDATE: I've added a new file: var_time_mx.txt which includes data from the beginning of the dataset (1/1/1950) through 1956, so it includes two leap years (1952 and 1956). Details about it are in the comment thread with @Walter Robertson, below.
Eric Sofen il 29 Lug 2019
Adding support for a broader range of calendars is something I've been thinking about. For a fixed-length calendar (360-day or 365-day), there are a couple issues to deal with:
1) Where do you put the extra days in the Gregorian calendar? Is day 59 from the model on a leap year 29 Feb or 1 Mar? If 29 Feb, then the extra day falls at the end of the year.
2) How do you want to fill in data for the days that aren't represented in the model data? Fill with previous? average of the previous and next? Leave it as missing? This matters when you want to do more aggregation/statistics on your data (e.g. monthly mean and standard deviation).
3) If you're using fraction-of-year values (second column of var_time_mx), you run into floating point and roundoff issues and needing to correct things to the nearest day.
One approach that I've come up with:
t = readtable('var_time_mx.txt');
d = t.Var1;
dt = datetime(1949,12,1)+calyears(fix(d/365))+caldays(floor(mod(d,365)))+hours((mod(d,365)-floor(mod(d,365)))*24)
This approach includes 29 Feb 1952, but skips 30 Nov 1952 (because 1 Dec is the start of the 365-day year in your definition). This is a bit weird, but a pain to work around and may not be necessary for your use. If it is, you can us the leapyear() function to check whether the dates need to be shifted by one day.