Code covered by the BSD License  

Highlights from
DateConvert

image thumbnail

DateConvert

by

 

16 Oct 2009 (Updated )

Simple but fast date conversion: 1.3% of DATESTR time, 20% of DATEVEC/ DATENUM time

DateConvert(DIn, OutFormat)
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;

Contact us