datetime 'InputFormat' syntax

I am looking to convert a cell array of dates to a datetime array. From the text file BUContactOutput.txt I need the Start Time and Stop time in separate datetime arrays. This section of code shows how I am going about creating the StartTime datetime array.
ContactData = readtable('BUContactOutput.txt',...
'Delimiter', ' ', 'HeaderLines',4);
NumOfContacts = height(ContactData);
StartTime = cell(NumOfContacts,1);
for i = 1:NumOfContacts
day = num2str(ContactData.Var1(i));
month = char(ContactData.Var2(i));
year = num2str(ContactData.Var3(i));
time = char(ContactData.Var4(i));
StartTime{i,1} = strcat(year,'-',month,'-',day,'-',time);
end
datetime(StartContact, 'InputFormat', 'yyyy-MMM-dd-HH:mm:SSS')
This method is successful when the time component of StartTime is not included (no ,'-',time in the strcat function and no -HH:mm:SSS in datetime function), yet is not successful when the time component is included. I believe I have a syntax error in my 'InputFormat' content. I am unsure how to resolve the issue and the documentation has yet to provide me with a solution.
https://www.mathworks.com/help/matlab/ref/datetime.html#
Thanks ahead to anyone who offers help.
-Emil

1 Comment

A few questions
  • is StartContact the same as StartTime?
  • why are you converting days, months, etc. to strings to parse them back into number in the datetime?
  • Why the loop?
  • What is the actual content of time and month?

Sign in to comment.

 Accepted Answer

Without seeing the actual format of time, it's difficult to know what the correct format should be. However, it's unusual to have SSS without a ss preceding it. So, possibly:
datetime(StartContact, 'InputFormat', 'yyyy-MMM-dd-HH:mm:ss.SSS')
See my comments to your question if that doesn't solve it.
Note: loop unneeded:
startTime = compose('%d-%s-%d-%s', ContactData.Var1, ContactData.Var2, ContactData.Var3, ContactData.Var4);

5 Comments

Thank you Guillaume! This is the syntax that I seem to not be able to find on the MatLab datetime documentation. I looked again and did not see any examples there.
Thanks for your help,
-Emil
Using InputFormat says, in effect, "My data are in this screwy format that I need to import from, but I don't want to preserve that as the display format of the resulting datetime array." That may or may not be what you want. Here's the difference between InputFormat and Format:
>> datetime('2019-Mar-18-03:37:24.409','InputFormat','yyyy-MMM-dd-HH:mm:ss.SSS')
ans =
datetime
18-Mar-2019 03:37:24
>> datetime('2019-Mar-18-03:37:24.409','Format','yyyy-MMM-dd-HH:mm:ss.SSS')
ans =
datetime
2019-Mar-18-03:37:24.409
Unfortunately, the InputFormat does not appear to be flexible enough to handle timestamps when fractional seconds are not always present. If I have a large array of timestamp strings and one of them results in:
datetime('2019-Mar-18-03:37:24','InputFormat','yyyy-MMM-dd-HH:mm:ss.SSS')
this throws an error that the format is not matched. An optional fractional part would be useful and is supported by many time parsing libraries.
You are correct that only one format is currently supported. But you are not correct that if only one timestamp among a large number is missing fractional seconds that the function errors. In fact, that error only occurs if NONE of the timestamps match the specified format (which includes the case of only one timestamp, and that one doesn't match). If only some of the timestamps don't match, the corresponding elements of the output are filled with NaT (Not a Time). If you have a large number of timestamps and are calling datetime on them one at a time, that's something to look at.
The work-around for a mix of formats is to call datetime with one format, then go back and, using isnat, read the ones that match the other format. Something equivalent to
dt = datetime(timestamps,InputFormat=fmt1);
dt(isnan(dt) )= datetime(dt(isnan(dt)),InputFormat=fmt2);
I think you have a typo on that second line. The first input to datetime should be the elements of timestamps corresponding to NaT values in dt, not the elements of dt. All those elements of dt are going to be NaT.

Sign in to comment.

More Answers (1)

Steven Lord
Steven Lord on 11 Oct 2017
I suggest using the Import Tool. Using this you can experiment with datetime formats and column widths then import the data to a variable, generate a script file, and/or generate a function file. The latter two options allow you to use the results of your experimentation to automatically import other data files with the same format in the future or to tweak the import process.
For your file, I removed the delimiters separating each of the components of your start and stop times from the default (which were set by using spaces as the delimeter.) I changed the first two columns to import as datetime arrays using the custom format dd MMM yyyy HH:mm:ss.SSS. Hovering over one of the elements in columns A and B showed me that each would import correctly. I then selected to read column C as a number and imported it and the results were what I expected.

2 Comments

Steven,
I looked into using the Import Tool but decided to go with readtable because the incoming data will (or at least should) always be in the same format coming from the software we are running to generate the .txt file. The larger function this will be going into needs to run continuous so needing the Import Tool would delay this (or so I believe). Thank you for your comment and I will be sure to use the Import Tool in the future when I need to control the incoming data.
Thanks again,
-Emil
Use the Import Tool once to generate a function file that imports the first data file.
Run the generated function file to import the second, third, fourth, etc. data files.

Sign in to comment.

Categories

Tags

Asked:

on 11 Oct 2017

Commented:

on 9 Aug 2022

Community Treasure Hunt

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

Start Hunting!