function DOut = DateConvert(DIn, OutFormat)
% Convert date to number or vector
% Matlab's DATENUM, DATEVEC and DATESTR functions accept a variety of inputs,
% but the parsing needs a lot of time. If the input format is known exactly,
% the conversion can be much faster (1.5GHz Pentium-M, Matlab 7.7):
% Convert 1000 strings from DATESTR(0) format to serial date number:
% DATENUM: 2.97 sec, DateConvert: 0.039 sec => 98.7% faster.
%
% DateOut = DateConvert(DateIn, Format)
% INPUT:
% DateIn: Date in DATESTR(0), DATENUM or DATEVEC format. Just one date can be
% processed at a time: no cell strings, no matrix. The month name is
% not sensitive for case.
% The inputs are checked roughly only, because this is designed for
% the fast conversion of very specific inputs.
% Format: String to specify the output format: 'vector', 'number', 'string'.
%
% OUTPUT:
% DateOut: Either scalar number for 'number', [1 x 6] double vector for
% 'vector' mode or string in DATESTR(0) format.
%
% TABLE OF INPUT/OUTPUT TYPES:
% DateIn: Format: DateOut:
% '08-Jun-2004 00:31:37' 'vector' [2004 6 8 0 31 37]
%
% '08-Jun-2004 00:31:37' 'number' 732106.021956019
%
% [2004 6 8 0 31 37] 'string' '08-Jun-2004 00:31:37'
% 732106.021956019
%
% NOTES:
% - The MEX functions DATENUMMX and DATEVECMX are called. Although they are not
% documented, they exist at least from Matlab 5.3 to 2009a.
% - Speed: string -> vector/number: ~2% of DATENUM/DATEVEC
% vector/number -> string: ~16% / 20% of DATESTR.
% - The more powerful DATESTR, DATEVEC, DATENUM of Matlab accept free format
% inputs also, e.g.: DATESTR('225-Jan') replies the date 200 days after the
% 25.th January of the current year.
% - Old style TRY CATCH for Matlab 6.5 support.
% - Run TestDateConvert to check results and compare speed. This test function
% is not needed for processing!
%
% Tested: Matlab 6.5, 7.7, 7.8, WinXP
% Author: Jan Simon, Heidelberg, (C) 2009-2010 matlab.THISYEAR(a)nMINUSsimon.de
%
% See also: DATESTR, DATEVEC, DATENUM.
% FEX: DateStr2Num (28093, Jan Simon)
% $JRev: R0l V:011 Sum:MMqeQQH86VGD Date:31-May-2010 00:25:38 $
% $License: BSD (see Docs\BSD_License.txt) $
% $UnitTest: TestDateConvert $
% $File: Tools\GLString\DateConvert.m $
% History:
% 001: 15-Jun-2009 00:17, DATENUM was a bottleneck due to its high flexibility.
% But actually the dates have strict DATESTR(0) format and no intelligent
% parsing is needed.
% 004: 22-Sep-2009 00:53, Call DATENUMMX.
% 006: 10-Oct-2009 18:28, Help section polished. Published.
% Do the work: =================================================================
switch lower(OutFormat)
case 'number' % Input is a string, output a serial date number:
try
Dx = double(DIn - '0'); % For faster conversion of numbers
month = (strfind('janfebmaraprmayjunjulaugsepoctnovdec', ...
lower(DIn(4:6))) + 2) / 3;
year = Dx(8) * 1000 + Dx(9) * 100 + Dx(10) * 10 + Dx(11);
DOut = datenummx(year, month, Dx(1) * 10 + Dx(2), ...
Dx(13) * 10 + Dx(14), Dx(16) * 10 + Dx(17), ...
Dx(19) * 10 + Dx(20));
% Pure Matlab method:
% % Number of days elapsed until 01-Jan:
% % nofd = cumsum([0,31,28,31,30,31,30,31,31,30,31,30,31]);
% nofd = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
%
% % result = (365 days/year)*(number of years) + number of leap years ...
% % + days in previous months + days in this month + fraction of a day.
% DOut = 365 * year + ceil(year / 4) - ceil(year / 100) + ...
% ceil(year / 400) + nofd(month) + ((month > 2) & ...
% ((rem(year, 4) == 0 & rem(year, 100) ~= 0) | ...
% rem(year, 400) == 0)) + ...
% Dx(1) * 10 + Dx(2) + ...
% (Dx(13) * 36000 + Dx(14) * 3600 + ...
% Dx(16) * 600 + Dx(17) * 60 + ...
% Dx(19) * 10 + Dx(20) ) / 86400;
catch
error(['JSim:', mfilename, ':BadInput'], ...
['Input must be a DATESTR(0) string.', char(10), lasterr]);
end
case 'vector' % Input is a string, output a [1 x 6] date vector: --------------
try
Dx = double(DIn - '0'); % For faster conversion of numbers
DOut = [Dx(8) * 1000 + Dx(9) * 100 + Dx(10) * 10 + Dx(11), ... % Year
(strfind('JanFebMarAprMayJunJulAugSepOctNovDec', ...
DIn(4:6)) + 2) / 3, ... % Month
Dx(1) * 10 + Dx(2), ... % Day
Dx(13) * 10 + Dx(14), ... % Hour
Dx(16) * 10 + Dx(17), ... % Minute
Dx(19) * 10 + Dx(20)]; % Second
catch
error(['JSim:', mfilename, ':BadInput'], ...
['Input must be a DATESTR(0) string.', char(10), lasterr]);
end
case 'string' % Input is serial date number or vector, output a string: -------
try
if length(DIn) == 1 % Serial number to [1 x 6] vector at first:
DIn = datevecmx(DIn, 1); % With rounding
end
% [1 x 6] vector to string:
months = ['Jan'; 'Feb'; 'Mar'; 'Apr'; 'May'; 'Jun'; ...
'Jul'; 'Aug'; 'Sep'; 'Oct'; 'Nov'; 'Dec'];
DOut = sprintf('%.2d-%s-%.4d %.2d:%.2d:%.2d', ...
DIn(3), months(DIn(2), :), fix(DIn([1, 4, 5, 6])));
catch
error(['JSim:', mfilename, ':BadInput'], ...
['Input must be a date number or vector.', char(10), lasterr]);
end
otherwise
error(['JSim:', mfilename, ':BadOutput'], 'Bad Output format.');
end
% return;