datevec with no leap year timeseries
Show older comments
Hello,
I am having issues using the function datevec on a time series with a no-leap calendar. I have a 4000 year time series with a time series resembling:
[31, 59, 90, 120, 151, 181, 212.... 1460000]
I would like to create a matrix in the form [year, month, day] for the time series.
When I run the code,
datevalue = time + datenum(1,1,1)-2;
DateVec = datevec(datevalue);
everything runs fine, but the values are wrong for the year and month. I was wondering if there was a way to use the datevec function with a no-leap calendar.
Thank you for any comments or suggestions.
1 Comment
Jan
on 8 Jul 2013
What an interesting and bewildering question. +1
Accepted Answer
More Answers (1)
No, there isn't. datevec considers leap years and it would need are very complicated and indirect method to remove this afterwards. It will be much easier to rewrite datevec and omit the leap year stuff.
I guess, that the show vector is the number of days (please mention such details explicitly in the future). Then:
function v = noLeapDateVec(day)
% Cumsum of the number of days, no leap years:
cum = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
% Get year:
day = reshape(day, 1, []); % Row-shape
y = floor(day / 365);
t = day - y * 365;
% Adjust year for the last day of the year:
idx = (t <= 0);
y(idx) = y(idx) - 1;
t(idx) = day(idx) - y(idx) * 365;
% Get month roughly and refine using accumulated number of days:
m = ceil(t / 29) - 1; % 30 or 31 would work also!
idx = t > cum(m + 1);
m(idx) = m(idx) + 1;
% Get day:
d = t - cum(m);
% Join the date:
v = [y(:), m(:), d(:)];
And a test, because the t/29 formula was developed for leap years also:
cum = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
in = 1:1460000;
v = noLeapDateVec(in);
d = v(:, 1)' * 365 + cum(v(:, 2)) + v(:,3)';
isequal(d, in)
Yep, it works. But now let me ask, why on earth should anybody calculate the datevector for a non-leap-year calendar?!
Note 1: You find an equivalent algorithm in datevecmx.c (of course with leap years), which has been shipped with older Matlab releases. Unfortunately modern releases lost a lot of these important examples, e.g. cellfun.c also.
Note 2: The shown M-code is only 6% slower than the compiled Mex function datevecmx for the shown test vector. This is caused by the expensive consideration of the leap year, which requires several operations with floating point numbers. I'm convinced a pure integer arithmetic method will faster.
Categories
Find more on Calendar in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!