How to calculate the date 0.25 years after the date of January 15, 2020
3 views (last 30 days)
Show older comments
How to calculate the date 0.75 years after the date of January 15, 2020 take into account leap day!
The years function supports decimals, but does not calculate leap days
1、any starday
2、any Time span 1.37years or 3.68years
3、leap year must be the actural days
4、count the endday
t = datetime(2020,1,1)
leapy=t+years(0.25)
0 Comments
Answers (6)
dpb
on 24 Jun 2023
t = datetime(2020,1,1);
leapy=t+calmonths(3)
3 Comments
dpb
on 25 Jun 2023
Edited: dpb
on 25 Jun 2023
I had missed this comment previously.
Now you're back to the problem of what the definition of 0.27 years is -- it has to represent some integer number of months, days, hours, minutes, seconds and then if desired, fractional seconds. But, for calendar date calculations, the intervals ALWAYS must be in integral time units until get to seconds.
I think you need to go back to the conceptual manner in which you're generating the need for such a calculation/date to produce an unambiguous time interval to be added. Describing the problem you're trying to solve would probably lead to more fruitful discussion on how to approach it than the comparison between the years and calyears functions this has become; they're simply two different functions for two different purposes. It appears you need calendar-sensitive solutions, but the community needs a more complete description of the problem that is causing the question to have better answer.
dpb
on 25 Jun 2023
Edited: dpb
on 25 Jun 2023
Consider these examples...
dt=0.27*years(1);
dt.Format='dd:hh:mm:ss.SSS'
dt=0.27*days(365);
dt.Format='dd:hh:mm:ss.SSS'
dt=0.27*days(366);
dt.Format='dd:hh:mm:ss.SSS'
98/365
98/366
All of those are somewhat different and the last shows that using only two decimal places for a fraction isn't adequate to represent a discrete time interval for either number of days in a year...of course since
factor(365)
factor(366)
generate a pretty short list, there are only a few choices that can be represented exactly, anyways. That's why systems such as datenum treat the days as the integer portion; even there a double doesn't have sufficient precision to avoid rounding issues with precise timings. That's the reason for TMW introducing datetime as a much more complex class.
One presumes you must be looking at differences in calendar dates and trying to express those as fractons of a year, but that is (as you're discovering) a nonproductive approach. But, again, we'd need to know the application to have better ideas about how to solve whatever is the underlying problem.
John D'Errico
on 24 Jun 2023
Edited: John D'Errico
on 24 Jun 2023
You did this:
t = datetime(2020,1,1)
But that is not January 15. It is January 1. Instead, had you done this:
t = datetime(2020,1,15)
We see the date you apparently intended as the initial date. Now, if you offset that by 3/4 of a year... Hmm. Is it intended to be 3/4 of a leap year? I might argue there is some ambiguity in this question, since 2020 should be a leap year. Years seems happy with this though:
years(0.75)
t + years(0.75)
And that seems to make sense. 1/4 of a year will not be an integer number of days. Comparing that to a different year, we see this:
datetime(2021,1,15) + years(0.75)
The difference being, of course, that 2020 had an extra day in there intervening between those dates.
2 Comments
John D'Errico
on 25 Jun 2023
Edited: John D'Errico
on 25 Jun 2023
OF COURSE THEY ARE DIFFERENT.
There is no error in integer arithmetic. 1 year is 365.2425 days, by explicit definition of the function years.
help years
Years does not know that for SOME years, it will be exactly one day longer. And it cannot possibly know that. All you are doing is calling years like this:
years(0.75)
How should it possibly know that some of the time, you want that to be a different number?????
You CAN use the function calyears. It should understand the length of a year.
help calyears
calyears([2020 2021])
But that does not allow you to scale those years by some fractional amount.
Anyway, as I said in my answer, the question is far too ambiguous. One fractional year from now should not depend on whether today happens to fall in a leap year. And worse, consider this case:
Starting with the date 2020:6:1, so june first, 2020. What day is exactly 3/4 of a year after that? 2020 being a leap year, that year is 366.2425 day. But only part of that fractional 3/4 year has that length. After 2020 is over, it is no longer a leap year. So year(2021) has a shorter length than year(2020).
Or, go the other way around. Now, start at the date June 1, 2019. Project forwards 3/4 of a year from that point. Part of that projection lies in the year 2019, which is NOT a leap year. But then as soon as you look at 2020, it becomes a leap year. Is that part of the year forwards going to use the longer year?
the cyclist
on 24 Jun 2023
"If X is a numeric array, then Y is a duration array in units of fixed-length years. A fixed-length year is equal to 365.2425 days".
So, it is adding
365.2425/4
days to your date.
And, it does take into account leap years:
t = datetime((2020:2027)',1,1) % 8 year range with 2 leap years
leapy=t+years(0.25)
Steven Lord
on 25 Jun 2023
Normally I would have suggested using the calyears function instead of the years function, but that does not allow you to specify a fractional number of calendar years. Instead I would translate 0.25 calendar years or 0.75 calendar years into 3 calendar months or 9 calendar months respectively. Compare the results of the following example that adds 0.25 fixed-length years to today's date and that adds three calendar months to today's date.
T = datetime('today')
fixedLength = T + years(0.25) % 0.25 times 365.24 days
calendarMonths = T + calmonths(3) % 3 calendar months
0 Comments
dpb
on 25 Jun 2023
Edited: dpb
on 25 Jun 2023
"In matlab document ,declare 'years' fuction do not count leap days ,If count leap days use ‘calyears’,But calyears do not accept decimal as Input Arguments"
Yes, but when you try, the error message tells you the correct syntax to use as well -- although I'll agree it takes more poking at the doc to find it directly --
try
datetime(2020,1,1)+calyears(0.25)
catch ME
msg=string(strtrim(split(extractAfter(ME.message,'. '),',')));
disp('Error message: ')
disp(msg)
end
As the error message says, don't try to mix fractional time units in the calandar duration functions, use the specific functions created for the purpose...so calyears(0.25) is written as calymonths(12/4) --> calmonths(3)
datetime(2020,1,1)+calmonths(3)
While for some reason the composite function <calendarDuration> doesn't have the standing in the documentation hierarchy of being its own function page but as links in the "See Also" section of the various calXXX functions, it handles all time units from years down to fractional seconds.
From the Tips section there you can find the useful (and lacking elsewhere) syntax of
"When you add a calendarDuration array that contains more than one unit to a datetime, MATLAB® always adds the larger units first. If t is a datetime, then this command:
t + calendarDuration(1,2,3)
is the same as:
t + calyears(1) + calmonths(2) + caldays(3)"
Peter Perkins
on 17 Jul 2023
Edited: Peter Perkins
on 18 Jul 2023
This is a long thread. I hope the following will clarify a couple things.
The years function is not really intended for precise arithmetic, or more accurately, its intended for arithmetic in a rough sense on very long durations. Which of these two would you rather look at?
t = seconds(1234567890)
t.Format = 'y'
I have no feeling for what e+9 seconds is, but I can get my head around 39.22y. Of course if you need to do precise calendar arithmetic, how many years 1234567890s is depends on where you start and on whether or not you are accounbting for DST shifts. Calendar arithmetic is messy, and the years and days functions are just meant as "help me get my head around this" conveniences for long durations.
t = seconds(1234567)
t.Format = 'd'
I happen to know that 86400s is one day, but beyond that it's easier to get my head around 14.289 days. days is somewhat safer to use in arithmetic, but only if you NEVER care about time zones. Otherwise, use calendar arithmetic (caldays, calyears, between, caldiff, ...).
Asking for .25 of a year is not well-defined, as others have said. It might be .25*(365*86400)s, or .25*(366*86400) or either of those +/- 1h and/or + 1s. It might also be 3 months, which has a different length depending on where you start from.
0 Comments
See Also
Categories
Find more on Dates and Time 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!