Odd behavior using datetime

조회 수: 4 (최근 30일)
Gonzalo
Gonzalo 2024년 9월 3일
편집: dpb 2024년 9월 5일
I am using the datetime function to convert numbers into dates. For example:
datetime(num2str(2072016),'InputFormat','ddMMyyyy')
ans = datetime
02-Jul-2016
This works as expected, but -for some unknown reason to me- this fails on certain dates, e.g.:
datetime(num2str(4072016),'InputFormat','ddMMyyyy')
Error using datetime (line 667)
Unable to convert '4072016' to datetime using the format 'ddMMyyyy'.
Why does this happen? Am I doing something wrong? Is this a bug?
However, if I only specify one 'd' on my InputFormat instead of 2, this works as expected:
datetime(num2str(4072016),'InputFormat','dMMyyyy')
I am aware of other ways to input numbers to use the datetime function, but in my case this is the way that takes the less number of lines in my code. Also, a workaround for this should not be necessary since this way of converting a string into a date should work regardless of the date in question.
My MATLAB version is 2024a. Although I do not know whether this is a thing in other versions as well.
Thanks!

답변 (4개)

dpb
dpb 2024년 9월 3일
편집: dpb 2024년 9월 5일
I'm surprised the first works; it shouldn't either.
See the doc for datetime <time formats>. As it notes,
d Day of the month, using one or two digits
dd Day of the month using two digits
The date strings should be
datetime('04072016','InputFormat','ddMMyyyy')
ans = datetime
04-Jul-2016
to use 'dd'.
If you do not want to incorporate the leading zero on days, then you want/need the single-letter date format string. Note, by the way, the same rule holds for months, 'M' and 'MM' and the various time fields as well. Read all of the documentation!!! :)
Also note that neither
num2str(04072016)
ans = '4072016'
string(04072016)
ans = "4072016"
keep the nonsignificant leading zero if you are reading date strings in as numeric; you would need a format string to convert them to include such.
ADDENDUM/ERRATUM:
While the datetime documentation format description describes that the single-letter form will accept either one- or two-digit days/months, datetime seems unable to convert the two-digit form given the single digit format. I think this is either a bug or the documentation should be corrected to reflect actual behavior. The description section of the documentation using 'infmt' states that all strings must be the same format, but the input array are all compliant with the one- or two- character and the input format string provided that is two-digits for month and four for year.

Star Strider
Star Strider 2024년 9월 4일
If there are more than one value that you want to convert, perhaps something like this —
date = [4072016 12072016];
sdate = cellfun(@num2str, num2cell(date), 'Unif',0)
sdate = 1x2 cell array
{'4072016'} {'12072016'}
for k = 1:size(sdate,2) % Zero-Pad 'date' Values With Odd Numbers Of Characters
if rem(numel(sdate{k}),2) ~= 0
sdate{k} = ['0' sdate{k}];
end
end
Out = datetime(sdate.', InputFormat="ddMMyyyy")
Out = 2x1 datetime array
04-Jul-2016 12-Jul-2016
Any leading zeros would be left off of a date specified only as a number.
.
  댓글 수: 3
Stephen23
Stephen23 2024년 9월 4일
편집: Stephen23 2024년 9월 4일
vec = [4072016 12072016];
str = compose('%08i',vec(:))
str = 2x1 cell array
{'04072016'} {'12072016'}
dpb
dpb 2024년 9월 4일
편집: dpb 2024년 9월 4일
Another good alternative, @Stephen23!
vec = [4072016 12072016];
str = num2str(vec(:),'%08i')
str = 2x8 char array
'04072016' '12072016'
also works, but returns a char() array unless cast to cellstr for datetime()
The arithmetic to convert to y,m,d arrays is not bad, either
y=rem(vec,10000);
m=fix(rem(vec/10000,100));
d=fix(rem(vec/1000000,100));
datetime(y,m,d).'
ans = 2x1 datetime array
04-Jul-2016 12-Jul-2016

댓글을 달려면 로그인하십시오.


dpb
dpb 2024년 9월 4일
Have a better mousetrap, I think...
dates = string([4072016 2072016 12072016]).';
dt=datetime(pad(dates,8,'left','0'),'InputFormat','ddMMyyyy')
dt = 3x1 datetime array
04-Jul-2016 02-Jul-2016 12-Jul-2016
using the new(ish) strings class functionality to pad the shorter rows -- same end result as @Star Strider's with the explicit code, of course.
BTW, I'd caution against using date as a variable, it is a MATLAB-supplied function that gets aliased and might be confusing later in code dealing with time and dates...

dpb
dpb 2024년 9월 4일
Another alternative without converting the numeric values to strings...
dates = [4072016 2072016 12072016].';
y=rem(dates,10000);
m=fix(rem(dates/10000,100));
d=fix(rem(dates/1000000,100));
datetime(y,m,d)
ans = 3x1 datetime array
04-Jul-2016 02-Jul-2016 12-Jul-2016
Or, the date vector can be passed if more convenient
ymd=[y m d];
datetime(ymd)
ans = 3x1 datetime array
04-Jul-2016 02-Jul-2016 12-Jul-2016

카테고리

Help CenterFile Exchange에서 Calendar에 대해 자세히 알아보기

태그

제품


릴리스

R2024a

Community Treasure Hunt

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

Start Hunting!

Translated by