how to print datetime in fprintf

Hi there,
I have elevation profiles on different days which are stored in datenum, and as want to print out the last measurement and the day that the sample was taken.
I currently have this in a loop , but i keep getting this error :
Error using fprintf Conversion to int64 from datetime is not possible.
fprintf('last row for profile %s on the %s is : %d',ProfName,ProfDateNum,indNaN) % Print out the index of the profile
It will only print out the first date and not the others, any others.
Do you have any suggestions to resplve this please?
Many thanks !

 Accepted Answer

dpb
dpb on 4 Apr 2023
Edited: dpb on 6 Apr 2023
We don't have sufficient data to reproduce the problem -- we don't have definitions of ProfName, ProfDateNum, nor indNaN
Guessing
ProfName="Profile XYZ";
ProfDateNum=datetime(now,'convertfrom','datenum');
indNaN=1234;
fprintf('last row for profile %s on the %s is : %d',ProfName,ProfDateNum,indNaN)
last row for profile Profile XYZ on the 04-Apr-2023 16:07:51 is : 1234
We don't get any errors; fprintf is capable of handling a datetime.
So, what's going on? With the statement the above is in a loop and it only does one, one can then add to the guess that the above may be arrays and you forgot to index into them, in which case MATLAB will try to send each array to the format string for output...
ProfName=["Profile ABC";"Profile XYZ"];
ProfDateNum=[datetime(now,'convertfrom','datenum');datetime(now+1,'convertfrom','datenum')];
indNaN=[0123;1234];
try % Put in try..catch block so can proceed past the error
fprintf('last row for profile %s on the %s is : %d',ProfName,ProfDateNum,indNaN)
catch % Show the error that occurred is what got above...
lasterr
end
last row for profile Profile ABC on the Profile XYZ is :
ans =
'Error using fprintf Conversion to int64 from datetime is not possible.'
And, Boom! the error message does show up...ergo, the answer is, when looping over a set of values, don't forget to index into the array...
ProfName=["Profile ABC";"Profile XYZ"];
ProfDateNum=[datetime(now,'convertfrom','datenum');datetime(now+1,'convertfrom','datenum')];
indNaN=[0123;1234];
for i=1:numel(ProfName)
fprintf('last row for profile %s on the %s is : %d',ProfName(i),ProfDateNum(i),indNaN(i))
end
last row for profile Profile ABC on the 04-Apr-2023 16:07:51 is : 123last row for profile Profile XYZ on the 05-Apr-2023 16:07:51 is : 1234
Now what shows up is that you forgot to include a newline so everything is all run together...
fmt='last row for profile %s on the %s is : %d\n'; % put the format string in variable for ease edit
for i=1:numel(ProfName)
fprintf(fmt,ProfName(i),ProfDateNum(i),indNaN(i))
end
last row for profile Profile ABC on the 04-Apr-2023 16:07:51 is : 123 last row for profile Profile XYZ on the 05-Apr-2023 16:07:51 is : 1234
You can control the format of the date by setting the .Format property of ProfDateNum. As a stylistic comment only, since it really is a datetime variable, using "DateNum" in the variable name is somewhat misleading and may lead to misuse later on when don't remember so clearly and interpret the variable name as being what it says it is.

4 Comments

Hello,
Oh yes , sorry my bad it is in datetime, I have amended the var name !
I will try out these and see how I get on - Thank you !
for i=1:nprof
indNaN = find(isnan(Ch(:,i))==1, 1 )-1; % Find the index of the last row in the current (ith) profile that has a value (the minumum row value). This is using
% Find function streamlined so it orginally was: indNaN=min(find(isnan(Ch(:,i))==1))-1.
% We use -1 because we want to find the row number just before it turns
% to NaN to give last chainage value.
fprintf('last row for profile %s on the %s is : %d',ProfName,ProfDateTime,indNaN) % Print out the index of the profile
if isempty(indNaN) % For the profile which has no NaNs in the column the line above will
% get no result and so indNaN must be the length of the column.
indNaN=length(Ch(i,:));
end
zGrid(:,i)=interp1(Ch(1:indNaN,i),Elev(1:indNaN,i),xGrid); % Find values for zGrid at every xGrid point by interpolating the Chainage and Elevation data.
end
this is the part that I want to loop with the dates dispalyed
+1 Another approach is to use COMPOSE (which could then be FPRINTed if required):
P = ["Profile ABC";"Profile XYZ"];
D = datetime(2023,4,[1;5]);
N = [123;456];
C = compose('last row for profile %s on the %s is : %d',P,D,N)
C = 2×1 cell array
{'last row for profile Profile ABC on the 01-Apr-2023 is : 123'} {'last row for profile Profile XYZ on the 05-Apr-2023 is : 456'}
fprintf('%s\n',C{:})
last row for profile Profile ABC on the 01-Apr-2023 is : 123 last row for profile Profile XYZ on the 05-Apr-2023 is : 456
dpb
dpb on 6 Apr 2023
Edited: dpb on 6 Apr 2023
Yeah, I always wondered why fprintf wasn't vectorized in that form instead...would have made much easier from the beginning -- and makes more sense than as is.
While on the foibles of fprintf and friends, when (back in the dark ages before commercial relase) moved the code base to C to and chose to use the builtin i/o libraries instead of implementing/following Fortran FORMAT syntax was the easier route for implementation/developers, but an unfortunate choice for a scientific/engineering code development environment. It took 30+ years before finally fixed (sorta') the issues with fixed-width files.
Just having to write(*) the b-ugly
fmt=[repmat('%f',1,numel(x)) '\n'];
instead of
fmt=numel(x)+"F";
has grated on raw nerves like fingernails on the blackboard forever...of course, the trick with the string class is a new(ish) feature, but just having repeat factor alone without all the other niceties of the FORMAT syntax (a language all its own) (**) would save countless hours cumulatively of having to do the same silly thing over and over and over ...
(*) Or, even worse as one often sees in newcomers' code who have yet to see (or rediscover) the above MATLAB idiom...
fmt='%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%d%f%f%f%f%f%f%f%f%s%f%f%f%f%f%f%f%f\n';
Try to maintain that!!!! :(
(**) At one point I wrote a mex extension that allowed one to pass a variable list and FORMAT string and passed it off to the Fortran i/o library to do the output. I offered that code to TMW over 30 years ago now, but they never showed any interest. Unfortunately, that code was on the corporate machine at the firm through which I was consulting at the time and when I left, I forgot to take it with me. When I thought I might try to resurrect it a few years ago, the MATLAB support for Fortran had detiorated to such an extent I was never able to get a Fortran compiler installed and to run without the unaffordable commercial Intel compiler. Why on earth they've made that process so convoluted no mere mortal can figure out how to just compile/link is unfathomable...and a tragic loss to the MATLAB user community.
Hi all ,
I got it working ! thank you !

Sign in to comment.

More Answers (1)

You can convert datenum data to datetime data and set its format to the one you desire:
d = datenum(2023, 4, 13);
dt = datetime(d, 'ConvertFrom', 'datenum');
dt.Format = 'MMMM d, yyyy - HH:mm:ss';
fprintf('%s', dt)
April 13, 2023 - 00:00:00

1 Comment

But, read the error OP got carefully, @Bora Eryilmaz --
Error using fprintf Conversion to int64 from datetime is not possible.
The date variable actually is a datetime despite the ill-chosen name that indicates it is a datenum
The problem is passing arrays to a format string instead of each element of the array in turn in the loop...

Sign in to comment.

Categories

Asked:

on 4 Apr 2023

Edited:

dpb
on 6 Apr 2023

Community Treasure Hunt

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

Start Hunting!