Borrar filtros
Borrar filtros

How to calculate the date 0.25 years after the date of January 15, 2020

4 visualizaciones (últimos 30 días)
fa wu
fa wu el 24 de Jun. de 2023
Editada: Peter Perkins el 18 de Jul. de 2023
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)
t = datetime
01-Jan-2020
leapy=t+years(0.25)
leapy = datetime
01-Apr-2020 07:27:18

Respuestas (6)

dpb
dpb el 24 de Jun. de 2023
t = datetime(2020,1,1);
t = datetime
01-Jan-2020
leapy=t+calmonths(3)
leapy = datetime
01-Apr-2020
  3 comentarios
dpb
dpb el 25 de Jun. de 2023
Editada: dpb el 25 de Jun. de 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.
You may find <the Answer I posted a little while ago> of some benefit, however, in this regards...
dpb
dpb el 25 de Jun. de 2023
Editada: dpb el 25 de Jun. de 2023
Consider these examples...
dt=0.27*years(1);
dt.Format='dd:hh:mm:ss.SSS'
dt = duration
98:14:46:17.040
dt=0.27*days(365);
dt.Format='dd:hh:mm:ss.SSS'
dt = duration
98:13:12:00.000
dt=0.27*days(366);
dt.Format='dd:hh:mm:ss.SSS'
dt = duration
98:19:40:48.000
98/365
ans = 0.2685
98/366
ans = 0.2678
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)
ans = 1×2
5 73
factor(366)
ans = 1×3
2 3 61
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.

Iniciar sesión para comentar.


John D'Errico
John D'Errico el 24 de Jun. de 2023
Editada: John D'Errico el 24 de Jun. de 2023
You did this:
t = datetime(2020,1,1)
t = datetime
01-Jan-2020
But that is not January 15. It is January 1. Instead, had you done this:
t = datetime(2020,1,15)
t = datetime
15-Jan-2020
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)
ans = duration
0.75 yrs
t + years(0.75)
ans = datetime
14-Oct-2020 22:21:54
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)
ans = datetime
15-Oct-2021 22:21:54
The difference being, of course, that 2020 had an extra day in there intervening between those dates.
  2 comentarios
fa wu
fa wu el 25 de Jun. de 2023
Thanks for your help
The code get a correct result in your example,but I think it is an error in integer arithmetic。2020,1,1+years(1) and 2021,1,1 + years(1) The calculation results are different!
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
John D'Errico
John D'Errico el 25 de Jun. de 2023
Editada: John D'Errico el 25 de Jun. de 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 Create durations from numeric values in units of standard-length years. Y = YEARS(X) returns an array of durations with each element equal to the number of exact fixed-length (i.e. 365.2425 day) years in the corresponding element of X. Y is the same size as X. X may contain non-integer values. To create an array of calendar years that account for leap days when used in calendar calculations, use the CALYEARS function. See also SECONDS, MINUTES, HOURS, DAYS, CALDAYS, CALWEEKS, CALMONTHS, CALQUARTERS, CALYEARS, DURATION, CALENDARDURATION. Documentation for years doc years Other uses of years codistributed/years duration/years tall/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)
ans = duration
0.75 yrs
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 Create calendar durations from numeric values in units of calendar years. Y = CALYEARS(N) returns an array of calendar durations with each element equal to the number of calendar years in the corresponding element of N. N must contain integer values. Y is the same size as N. CALYEARS creates an array of years that account for leap days when used in calendar calculations. To create exact fixed-length (i.e. 365.2425 day) years, use the YEARS function. See also CALDAYS, CALWEEKS, CALMONTHS, CALQUARTERS, SECONDS, MINUTES, HOURS, DAYS, YEARS, DURATION, CALENDARDURATION. Documentation for calyears doc calyears Other uses of calyears codistributed/calyears tall/calyears
calyears([2020 2021])
ans = 1×2 calendarDuration array
2020y 2021y
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?

Iniciar sesión para comentar.


the cyclist
the cyclist el 24 de Jun. de 2023
The behavior might not be what you expect, but it is what is documented for the years function:
"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
ans = 91.3106
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
t = 8×1 datetime array
01-Jan-2020 01-Jan-2021 01-Jan-2022 01-Jan-2023 01-Jan-2024 01-Jan-2025 01-Jan-2026 01-Jan-2027
leapy=t+years(0.25)
leapy = 8×1 datetime array
01-Apr-2020 07:27:18 02-Apr-2021 07:27:18 02-Apr-2022 07:27:18 02-Apr-2023 07:27:18 01-Apr-2024 07:27:18 02-Apr-2025 07:27:18 02-Apr-2026 07:27:18 02-Apr-2027 07:27:18
  1 comentario
fa wu
fa wu el 25 de Jun. de 2023
Thanks for your help
The code get a correct result in your example,but I think it is an error in integer arithmetic。2020,1,1+years(1) and 2021,1,1 + years(1) The calculation results are different! if count leap days ,It should get a same result,right? In my case,maybe count 2020,2,3 +7.5years ,include two leap years
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

Iniciar sesión para comentar.


Steven Lord
Steven Lord el 25 de Jun. de 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')
T = datetime
25-Jun-2023
fixedLength = T + years(0.25) % 0.25 times 365.24 days
fixedLength = datetime
24-Sep-2023 07:27:18
calendarMonths = T + calmonths(3) % 3 calendar months
calendarMonths = datetime
25-Sep-2023

dpb
dpb el 25 de Jun. de 2023
Editada: dpb el 25 de Jun. de 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
Error message:
"Use the CALMONTHS or CALDAYS functions to create calendar durations shorter than one year" "or use the YEARS function to create fractional fixed-length years as durations."
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)
ans = datetime
01-Apr-2020
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)"
  1 comentario
dpb
dpb el 25 de Jun. de 2023
Editada: dpb el 25 de Jun. de 2023
for Y=2020:2021;
t0=datetime(Y,1,1);
t1=t0+calmonths(3);
disp([t0 t1])
disp(days(t1-t0))
end
01-Jan-2020 01-Apr-2020
91
01-Jan-2021 01-Apr-2021
90
Shows that calmonths does account for leap year...

Iniciar sesión para comentar.


Peter Perkins
Peter Perkins el 17 de Jul. de 2023
Editada: Peter Perkins el 18 de Jul. de 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 = duration
1.2346e+09 sec
t.Format = 'y'
t = duration
39.122 yrs
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 = duration
1.2346e+06 sec
t.Format = 'd'
t = duration
14.289 days
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.

Categorías

Más información sobre Dates and Time en Help Center y File Exchange.

Etiquetas

Productos


Versión

R2020a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by