Reputation: 6323
With 100,000 date strings to convert to datenums, Matlab is really slow... 20 seconds!! Is there a faster way of doing this?
%strDay
%strTime
dblDate = zeros(1, nLines);
for i = 1 : nLines
dblDate(j) = datenum([strDay{i}, ' ', strTime{i}], 'yy.mm.dd HH:MM:SS.FFF');
j = j + 1;
end
Upvotes: 2
Views: 2274
Reputation: 24127
Internally, datenum
does a large amount of fiddling around to process many different date formats. Then it calls the internal function datenummx
with different input arguments depending on the date format and the syntax with which you called datenum
.
If you know ahead of time which syntax you will be calling datenum
with, and which date format you will be using, you can call datenummx
directly. Since datenummx
is a built-in MEX file, and avoids all the overhead processing, it is typically vastly faster.
Take a look into datenum
(type edit datenum
) to find out the appropriate way to call datenummx
for your application.
(Plus, do all the vectorization that other answers have suggested).
Upvotes: 4
Reputation: 9317
You could try to avoid the loop:
tmp = repmat({' '}, length(strDay), 1);
datenum(cell2mat([strDay (:), tmp(:), strTime(:)]))
~edit~
A little bit of benchmarking of all the solutions so far:
% creating some bogus data
a = ones(10000,1).*(now.*rand(10000,1));
str = datestr(a,'yy.mm.dd HH:MM:SS.FFF');
strDay = cellstr(str(:,1:8));
strTime = cellstr(str(:,10:end));
%% jdl's original code
disp('jdl''s original code')
tic
nLines = length(strDay);
dblDate = zeros(1, nLines);
j = 1;
for i = 1 : nLines
dblDate(j) = datenum([strDay{i}, ' ', strTime{i}]);
j = j + 1;
end
toc
%% hmuster's solution
disp('hmuster''s solution')
tic
tmp = repmat({' '}, length(strDay), 1);% cell(size(str1));
b = datenum(cell2mat([strDay(:), tmp(:), strTime(:)]));
toc
%% ThijsW's solution
disp('ThijsW''s solution')
tic
strDay = cell2mat(strDay);
strTime = cell2mat(strTime);
dblDate = datenum([strDay, (' ')*ones(size(strTime)), strTime], 'yy.mm.dd HH:MM:SS.FFF');
toc
% jdl's solution
disp('jdl''s solution')
tic
dblDate = datenum(strDay, 'yy.mm.dd') + ...
datenum(strTime, 'HH:MM:SS.FFF') - ...
datenum('00:00:00.000', 'HH:MM:SS.FFF');
toc
This results in:
jdl's original code
Elapsed time is 19.624597 seconds.
hmuster's solution
Elapsed time is 4.029291 seconds.
ThijsW's solution
Elapsed time is 0.183376 seconds.
jdl's solution
Elapsed time is 0.222996 seconds.
Upvotes: 2
Reputation: 6323
This is what I found to reduce time from 20 sec to 2 sec:
dblDate = datenum(strDay, 'yy.mm.dd') + ...
datenum(strTime, 'HH:MM:SS.FFF') - ...
datenum('00:00:00.000', 'HH:MM:SS.FFF');
Upvotes: 2
Reputation: 2599
Try it without the for loop. datenum
should be able to handle a vectors.
strDay = cell2mat(strDay);
strTime = cell2mat(strTime);
dblDate = datenum([strDay, (' ')*ones(size(strTime)), strTime], 'yy.mm.dd HH:MM:SS.FFF');
Upvotes: 2