Datetime with variable format

169 views (last 30 days)
Winston Black
Winston Black on 11 Feb 2016
Edited: dpb on 26 Sep 2017
I have an output file that has timestamps in the form of 'yyyy-MM-dd HH:mm:ss.S' or 'yyyy-MM-dd HH:mm:ss'. I would like a clean way to convert them from date strings into an array of date time format.
Example code:
a={'2016-02-09 10:28:00';'2016-02-09 10:28:01.5'}
out=datetime(a,'InputFormat','yyyy-MM-dd HH:mm:ss.S','InputFormat','yyyy-MM-dd HH:mm:ss','Format','yyyy-MM-dd HH:mm:ss.S');
Actual output:
out =
2016-02-09 10:28:00.0
NaT
Desired output:
out =
2016-02-09 10:28:00.0
2016-02-09 10:28:00.5

Accepted Answer

Brendan Hamm
Brendan Hamm on 11 Feb 2016
Edited: Brendan Hamm on 11 Feb 2016
Unfortunatelly you cannot specify multiple InputFormats simultaneously. Common to Name-Value pairs is that the last instance of a name value pair is used; in your example this is: 'yyyy-MM-dd HH:mm:ss'. One thing you can do to work around this issue is to convert the cell string to a vector of MATALB Serial Date Numbers and then to a datetime:
d = datenum(a);
d = datetime(d,'Format','yyyy-MM-dd HH:mm:ss.S','convertFrom','datenum');
I would caution you here as if you attempt to change the format in the line d = datenum(a) you will error due to a non-conforming entry.
  12 Comments
Peter Perkins
Peter Perkins on 26 Sep 2017
Running R2017b, which was released like yesterday ...
>> version
ans =
'9.3.0.713579 (R2017b)'
>> a = {'2016-02-09 10:28:00.5';'2016-02-09 10:28:01'}
a =
2×1 cell array
{'2016-02-09 10:28:00.5'}
{'2016-02-09 10:28:01' }
>> fmt = {'yyyy-MM-dd HH:mm:ss.S';'yyyy-MM-dd HH:mm:ss'}
fmt =
2×1 cell array
{'yyyy-MM-dd HH:mm:ss.S'}
{'yyyy-MM-dd HH:mm:ss' }
>> cellfun(@(t,f) datetime(t,'format',f),a,fmt)
ans =
2×1 datetime array
2016-02-09 10:28:00.5
2016-02-09 10:28:01.0
Just to be clear, this does not allow you to provide multiple formats to the datetime constructor, but it does allow dpb's solution using cellfun to work.
dpb
dpb on 26 Sep 2017
Edited: dpb on 26 Sep 2017
Nice enhancement...I've noted in the past that datetime class is clearly "a work in progress" and while basic functionality and interaction is pretty good start there were/are still missing pieces. This just took care of one; not sure I'd actually run across it before, but it's a continuing step to fully integrate the facility.
Kudos! :)
PS: I note you carefully arranged to put the format with the .S format string first so the output format included it and didn't have to reset the display format... :)

Sign in to comment.

More Answers (3)

dpb
dpb on 11 Feb 2016
Edited: dpb on 11 Feb 2016
I'm frankly surprised the above doesn't give a syntax error on the duplicated named input, but guess it likely just takes the first occurrence and doesn't count the number...will have to do some testing on that behavior; never thought of even trying it before.
Anyway, the doc says " All strings in DateStrings must have the same format." so you have only one shot at getting it right! :)
If you can't fixup the input format to become consistent, you'll have to fixup the data before converting--
>> a={'2016-02-09 10:28:00';'2016-02-09 10:28:01.5'};
>> ix=cellfun(@isempty,strfind(a,'.')) % find the locations missing the fractional seconds
ix =
1
0
>> a(ix)={[char(a(ix)) '.0']} % add the superfluous '.0' to make format match
a =
'2016-02-09 10:28:00.0'
'2016-02-09 10:28:01.5'
>>
Now you can convert with the fractional second format.
I thought you might get lucky if you skipped defining an input format string entirely but the requirement for all to be the same means that will also fail, undoubtedly.

Peter Perkins
Peter Perkins on 18 Feb 2016
Winston, I recommend that you NOT mix datenum and datetime. If you're in R2014b or later, don't use datenums. Among other things, because they count in units of days, using datenums runs the risk of round-off problems for sub-second timestamps.
You're right, datetime requires a single format. But it's pretty easy to get what you want.Convert using the first format. You'll get a vector of datetimes, with NaTs where the format was different. Then use isnat to convert those strings with the other format and assign into the appropriate elements.
Hope this helps.

Winston Black
Winston Black on 12 Feb 2016
Thanks for these solutions! I think they are both nice though Brendan's is a bit cleaner.
Another alternative solution (which I think is less attractive) would be to run datetime twice - once with each format - then combine the results into one variable.

Categories

Find more on Data Type Conversion in Help Center and File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!