source: trunk/src/datenum_uvmat.m @ 19

Last change on this file since 19 was 19, checked in by gostiaux, 15 years ago

the private files have been moved down to the root folder

File size: 21.2 KB
Line 
1%'datenum_uvmat': like the Matlab function datenum.m but gives empty output instead of stopping for input error
2%--------------------------------------------------------------------------
3function n = datenum_uvmat(arg1,arg2,arg3,h,min,s)
4%DATENUM Serial date number.
5%       N = DATENUM(V) converts one or more date vectors V into serial date
6%       numbers N. Input V can be an M-by-6 or M-by-3 matrix containing M full
7%       or partial date vectors respectively.  DATENUM returns a column vector
8%       of M date numbers.
9%
10%       A date vector contains six elements, specifying year, month, day, hour,
11%       minute, and second. A partial date vector has three elements, specifying
12%       year, month, and day.  Each element of V must be a positive double
13%       precision number.  A serial date number of 1 corresponds to Jan-1-0000. 
14%       The year 0000 is merely a reference point and is not intended to be
15%       interpreted as a real year.
16%
17%       N = DATENUM(S,F) converts one or more date strings S to serial date
18%       numbers N using format string F. S can be a character array where each
19%       row corresponds to one date string, or one dimensional cell array of
20%       strings.  DATENUM returns a column vector of M date numbers, where M is
21%       the number of strings in S.
22%
23%       All of the date strings in S must have the same format F, which must be
24%       composed of date format symbols according to Table 2 in DATESTR help.
25%       Formats with 'Q' are not accepted by DATENUM. 
26%
27%       Certain formats may not contain enough information to compute a date
28%       number.  In those cases, hours, minutes, and seconds default to 0, days
29%       default to 1, months default to January, and years default to the
30%       current year. Date strings with two character years are interpreted to
31%       be within the 100 years centered around the current year.
32%
33%       N = DATENUM(S,F,P) or N = DATENUM(S,P,F) uses the specified format F
34%       and the pivot year P to determine the date number N, given the date
35%       string S.  The pivot year is the starting year of the 100-year range in
36%       which a two-character year resides.  The default pivot year is the
37%       current year minus 50 years.
38%
39%       N = DATENUM(Y,MO,D) and N = DATENUM([Y,MO,D]) return the serial date
40%       numbers for corresponding elements of the Y,MO,D (year,month,day)
41%       arrays. Y, MO, and D must be arrays of the same size (or any can be a
42%       scalar).
43%
44%       N = DATENUM(Y,MO,D,H,MI,S) and N = DATENUM([Y,MO,D,H,MI,S]) return the
45%       serial date numbers for corresponding elements of the Y,MO,D,H,MI,S
46%       (year,month,day,hour,minute,second) arrays.  The six arguments must be
47%       arrays of the same size (or any can be a scalar).
48%
49%       N = DATENUM(S) converts the string or date vector (as defined by
50%       DATEVEC) S into a serial date number.  If S is a string, it must be in
51%       one of the date formats 0,1,2,6,13,14,15,16,23 as defined by DATESTR.
52%       This calling syntax is provided for backward compatibility, and is
53%       significantly slower than the syntax which specifies the format string.
54%       If the format is known, the N = DATENUM(S,F) syntax should be used.
55%
56%       N = DATENUM(S,P) converts the date string S, using pivot year P. If the
57%       format is known, the N = DATENUM(S,F,P) or N = DATENUM(S,P,F) syntax
58%       should be used.
59%
60%       Note:  The vectorized calling syntax can offer significant performance
61%       improvement for large arrays.
62%
63%       Examples:
64%               n = datenum('19-May-2000') returns n = 730625.
65%               n = datenum(2001,12,19) returns n = 731204.
66%               n = datenum(2001,12,19,18,0,0) returns n = 731204.75.
67%               n = datenum('19.05.2000','dd.mm.yyyy') returns n = 730625.
68%
69%       See also NOW, DATESTR, DATEVEC, DATETICK.
70
71%   Copyright 1984-2004 The MathWorks, Inc.
72%   $Revision: 1.24.4.7 $  $Date: 2004/10/27 23:53:57 $
73
74if (nargin<1) || (nargin>6)
75    error('MATLAB:datenumr:Nargin',nargchk(1,6,nargin));
76end
77
78% parse input arguments
79isdatestr = ~isnumeric(arg1);
80isdateformat = false;
81if nargin == 2
82    isdateformat = ischar(arg2);
83elseif nargin == 3
84    isdateformat = [ischar(arg2),ischar(arg3)];
85end
86% try to convert date string or date vector to a date number
87try
88    switch nargin
89        case 1
90            if isdatestr
91                n = datenummx(datevec(arg1));
92            elseif (size(arg1,2)==3) || (size(arg1,2)==6)
93                n = datenummx(arg1);
94            else
95                n = arg1;
96            end
97        case 2
98            if isdateformat
99                if ischar(arg1)
100                                        arg1 = cellstr(arg1);
101                                end
102                n = dtstr2dtnummx(arg1,cnv2icudf(arg2));
103            else
104                n = datenummx(datevec(arg1,arg2));
105            end
106        case 3
107                        if any(isdateformat)
108                                if isdateformat(1)
109                                        format = arg2;
110                                        pivot = arg3;
111                                elseif isdateformat(2)
112                                        format = arg3;
113                                        pivot = arg2;
114                                end
115                                if ischar(arg1)
116                                        arg1 = cellstr(arg1);
117                                end
118                                icu_dtformat = cnv2icudf(format);
119                                showyr =  strfind(icu_dtformat,'y');
120                                if ~isempty(showyr)
121                                        wrtYr =  numel(showyr);
122                                        checkYr = diff(showyr);
123                                        if any(checkYr~=1)
124                                                error('MATLAB:datenum:YearFormat','Unrecognized year format');
125                                        end
126                                        switch wrtYr
127                                                case 4,
128                                                        icu_dtformat = strrep(icu_dtformat,'yyyy','yy');
129                                                case 3,
130                                                        icu_dtformat = strrep(icu_dtformat,'yyy','yy');
131                                        end
132                                end
133                                n = dtstr2dtnummx(arg1,icu_dtformat,pivot);
134                        else
135                n = datenummx(arg1,arg2,arg3);
136                        end
137        case 6, n = datenummx(arg1,arg2,arg3,h,min,s);
138        otherwise, error('MATLAB:datenum:Nargin',...
139                         'Incorrect number of arguments');
140    end
141catch
142    err = lasterror;
143    err.message = sprintf('DATENUM failed.\n%s',err.message);
144   
145    if (nargin == 1 && ~isdatestr)
146        err.identifier = 'MATLAB:datenum:ConvertDateNumber';
147    elseif (nargin == 1 && isdatestr) || (isdatestr && any(isdateformat))
148        err.identifier = 'MATLAB:datenum:ConvertDateString';
149    elseif (nargin > 1) && ~isdatestr && ~any(isdateformat)
150        err.identifier = 'MATLAB:datenum:ConvertDateVector';
151    end
152 
153    rethrow(err);
154end
155end
156
157function [y,mo,d,h,mi,s] = datevec(t,varargin)
158%DATEVEC Date components.
159%       V = DATEVEC(N) converts one or more date numbers N to date vectors V. N
160%       can be a scalar, vector, or multidimensional array of positive date
161%       numbers. DATEVEC returns an M-by-6 matrix containing M date vectors,
162%       where M is the total number of date numbers in N.
163%
164%       V = DATEVEC(S,F) converts one or more date strings S to date vectors
165%       V using format string F to interpret the date strings in S. S can be a
166%       cell array of strings or a character array where each row corresponds
167%       to one date string. All of the date strings in S must have the same
168%       format which must be composed of date format symbols according to
169%       Table 2 in DATESTR help. Formats with 'Q' are not accepted by DATEVEC.
170%       DATEVEC returns an M-by-6 matrix of date vectors, where M is the number
171%       of date strings in S.
172%
173%       Certain formats may not contain enough information to compute a date
174%       vector.  In those cases, hours, minutes, and seconds default to 0, days
175%       default to 1, months default to January, and years default to the
176%       current year. Date strings with two character years are interpreted to
177%       be within the 100 years centered around the current year.
178%
179%       V = DATEVEC(S,F,P) or V = DATEVEC(S,P,F) converts the date string S to
180%       a date vector V, using the pivot year P and the date format F.  The
181%       pivot year is the starting year of the 100-year range in which a
182%       two-character year resides.  The default pivot year is the current year
183%       minus 50 years.
184%
185%       [Y,MO,D,H,MI,S] = DATEVEC(...) takes any of the two syntaxes shown
186%       above and returns the components of the date vector as individual
187%       variables. 
188%
189%       V = DATEVEC(S) converts date string S to date vector V. S must be in
190%       one of the date formats 0,1,2,6,13,14,15,16,23 as defined by DATESTR. 
191%       This calling syntax is provided for backward compatibility, and is
192%       significantly slower than the syntax which specifies the format string.
193%       If the format is known, the V = DATEVEC(S,F) syntax should be used.
194%
195%       V = DAVEVEC(S,P) converts the date string S using pivot year P.
196%       If the format is known, the V = DATEVEC(S,F,P) or V = DATEVEC(S,P,F)
197%       syntax should be used.
198%
199%       Note 1:  If more than one input argument is used, the first argument
200%       must be a date string or array of date strings.
201%
202%       Note 2:  The vectorized calling syntax can offer significant performance
203%       improvement for large arrays.
204%
205%       Examples
206%               d = '12/24/1984';
207%               t = 725000.00;
208%               c = datevec(d) or c = datevec(t) produce c = [1984 12 24 0 0 0].
209%               [y,m,d,h,mi,s] = datevec(d) returns y=1984, m=12, d=24, h=0, mi=0, s=0.
210%               c = datevec('5/6/03') produces c = [2003 5 6 0 0 0] until 2054.
211%               c = datevec('5/6/03',1900) produces c = [1903 5 6 0 0 0].
212%               c = datevec('19.05.2000','dd.mm.yyyy') produces c = [2000 5 19 0 0 0].
213%
214%       See also DATENUM, DATESTR, CLOCK, DATETICK.
215
216%       Copyright 1984-2004 The MathWorks, Inc.
217%       $Revision: 1.28.4.11 $  $Date: 2004/10/27 23:53:59 $
218
219if (nargin<1) || (nargin>3)
220%     error('MATLAB:datevec:Nargin',nargchk(1,3,nargin));
221    return
222end
223
224% parse input arguments
225isdatestr = ~isnumeric(t);
226isdateformat = false;
227if ~isdatestr && nargin > 1
228    warning('MATLAB:datevec:Inputs', ...
229        'Unless the first input argument is a date string, all subsequent\narguments will be ignored.');
230elseif nargin > 1
231    isdateformat = cellfun('isclass',varargin,'char');
232    if (nargin == 3)
233        if ~isdateformat(1)
234            pivotyear = varargin{1};
235        elseif ~isdateformat(2)
236            pivotyear = varargin{2};
237        elseif isdateformat(1) && isdateformat(2)
238%             error('MATLAB:datevec:DateFormat',...
239%                 'You specified two date format strings.\nThere can only be one.');
240           return
241        end
242    elseif (nargin == 2) && ~isdateformat
243        pivotyear = varargin{1};
244    end
245end
246
247if isdatestr && isempty(t)
248    if nargout <= 1
249        y = zeros(0,6);
250        else
251                [y,mo,d,h,mi,s] = deal(zeros(0,0));
252    end;
253        warning('MATLAB:datevec:EmptyDate',...
254                'Usage of DATEVEC with empty date strings is not supported.\nResults may change in future versions.');
255    return;
256end
257
258% branch to appropriate date string parser
259if  isdatestr
260    % a date format string was specified
261    % map date format to ICU date format tokens
262    if ischar(t)
263        % convert to cellstring.
264        t = cellstr(t);
265    end
266    icu_dtformat = {};
267    if ~any(isdateformat)
268        format = getformat(t);
269        if ~isempty(format)
270            icu_dtformat = cnv2icudf(format);
271        end
272    else
273        icu_dtformat = cnv2icudf(varargin{isdateformat});
274    end
275    if ~isempty(icu_dtformat)
276        % call ICU MEX function to parse date string to date vector
277        try
278            if nargin < 2 || (nargin == 2 && any(isdateformat))
279                y = dtstr2dtvecmx(t,icu_dtformat);
280            else
281                                showyr =  findstr(icu_dtformat,'y');
282                                if ~isempty(showyr)
283                                        wrtYr =  numel(showyr);
284                                        if showyr(end) - showyr(1) >= wrtYr
285%                                               error('MATLAB:datevec:YearFormat','Unrecognized year format');
286                        return
287                                        end
288                                        switch wrtYr
289                                                case 4,
290                                                        icu_dtformat = strrep(icu_dtformat,'yyyy','yy');
291                                                case 3,
292                                                        icu_dtformat = strrep(icu_dtformat,'yyy','yy');
293                                        end
294                                end
295                y = dtstr2dtvecmx(t,icu_dtformat,pivotyear);
296            end
297            if nargout > 1
298                mo = y(:,2);
299                d  = y(:,3);
300                h  = y(:,4);
301                mi = y(:,5);
302                s  = y(:,6);
303                y  = y(:,1);
304            end
305        catch
306            err = lasterror;
307            err.identifier = 'MATLAB:datevec:dtstr2dtvecmx';
308            err.message = sprintf(['DATEVEC failed, calling DTSTR2DTVECMX.\n'...
309                    '%s'],err.message);
310            rethrow(err);
311        end
312    else
313        %last resort!!!
314       if ischar(t)
315          m = size(t,1);
316       else
317          m = length(t);
318       end
319       y = zeros(m,6);
320       t = lower(t);
321%        ampmtokens = lower(getampmtokensmx);
322        amtok = 'am'; %ampmtokens{1};
323       amtok0 = 'am';
324        pmtok = 'pm';%ampmtokens{2};
325       pmtok0 = 'pm';
326       M={'jan';'feb';'mar';'apr';'may';'jun';'jul';'aug';'sept';'oct';'nov';'dec'};
327       M0=M;
328%        M = lower(getmonthnames);
329%        M0 = lower(getmonthnames(0)); % fall-back list of English short month names.
330       try
331           for i = 1:m
332               % Convert date input to date vector
333               % Initially, the six fields are all unknown.
334               c(1,1:6) = NaN;
335               pm = -1; % means am or pm is not in datestr
336               if ischar(t)
337                   str = t(i,:);
338               else
339                   str = t{i};
340               end
341               d = [' ' str ' '];
342
343               % Replace 'a ' or 'am', 'p ' or 'pm' with ': '.
344               p = max(find(d == amtok(1) | d == pmtok(1) | ...
345                            d == amtok0(1)| d == pmtok0(1)));
346               if ~isempty(p)
347                   if (d(p+1) == amtok(2) | ...
348                       d(p+1) == amtok0(2)| isspace(d(p+1))) & ...
349                       d(p-1) ~= lower('e')
350                       pm = (d(p) == pmtok(1) | d(p) == pmtok0(1));
351                       if d(p-1) == ' '
352                           d(p-1:p+1) = ':  ';
353                       else
354                           d(p:p+1) = ': ';
355                       end
356                   end
357               end
358
359               % Any remaining letters must be in the month field
360               p = find(isletter(d));
361
362               % Test length of string to catch a bogus date string.
363               % Get index of month in list of months of year
364               % replace with spaces, month name in date string.
365               % If native month name lookup fails, fall back on
366               % list of English month names.
367               if ~isempty(p) && numel(d)>4
368                   k = min(p);
369                   if d(k+3) == '.', d(k+3) = ' '; end
370                   monthidx = ~cellfun('isempty',strfind(M,d(k:k+2)));
371                   if ~any(monthidx)
372                       monthidx = ~cellfun('isempty',strfind(M0,d(k:k+2)));
373                       if ~any(monthidx)
374%                            error('MATLAB:datevec:MonthOfYear',...
375%                                'Failed to lookup month of year.');
376                          return
377                       end
378                   end
379                   c(2) = find(monthidx);
380                   d(p) = char(' '*ones(size(p)));
381               end
382
383               % Find all nonnumbers.
384               p = find((d < '0' | d > '9') & (d ~= '.'));
385
386               % Pick off and classify numeric fields, one by one.
387               % Colons delinate hour, minutes and seconds.
388
389               k = 1;
390               while k < length(p)
391                   if d(p(k)) ~= ' ' && d(p(k)+1) == '-'
392                       f = str2double(d(p(k)+1:p(k+2)-1));
393                       k = k+1;
394                   else
395                       f = str2double(d(p(k)+1:p(k+1)-1));
396                   end
397                   if ~isnan(f)
398                       if d(p(k))==':' || d(p(k+1))==':'
399                           if isnan(c(4))
400                               c(4) = f;             % hour
401                               % Add 12 if pm specified and hour isn't 12
402                               if pm == 1 && f ~= 12
403                                   c(4) = f+12;
404                               elseif pm == 0 && f == 12
405                                   c(4) = 0;
406                               end
407                           elseif isnan(c(5))
408                               c(5) = f;             % minutes
409                           elseif isnan(c(6))
410                               c(6) = f;             % seconds
411                           else
412%                                error('MATLAB:datevec:NumberOfTimeFields',...
413%                                    'Too many time fields in %s', str);
414                                return
415                           end
416                       elseif isnan(c(2))
417                           if f > 12
418%                                error('MATLAB:datevec:IllegalDateField',...
419%                                    '%s is too large to be a month.',num2str(f));
420                                return
421                           end
422                           c(2) = f;                % month
423                       elseif isnan(c(3))
424                           c(3) = f;                % date
425                       elseif isnan(c(1))
426                           if (f >= 0) & (p(k+1)-p(k) == 3) % two char year
427                               if nargin < 2
428                                   clk = clock;
429                                   pivotyear = clk(1)-50;  %(current year-50 years)
430                               end
431                               % Moving 100 year window centered around current year
432                               c(1) = pivotyear+rem(f+100-rem(pivotyear,100),100);
433                           else
434                               c(1) = f;             % year
435                           end
436                       else
437%                            error('MATLAB:datevec:NumberOfDateFields',...
438%                                'Too many date fields in %s', str);
439                            return
440                       end
441                   end
442                   k = k+1;
443               end
444
445               if sum(isnan(c)) >= 5
446%                    error('MATLAB:datevec:ParseDateString',...
447%                        'Cannot parse date %s', str);
448                    return
449               end
450              % If any field has not been specified
451               if isnan(c(1)), clk = clock; c(1) = clk(1); end
452               if isnan(c(2)), c(2) = 1; end;
453               if isnan(c(3)), c(3) = 1; end;
454               if isnan(c(4)), c(4) = 0; end;               
455               if isnan(c(5)), c(5) = 0; end;                   
456               if isnan(c(6)), c(6) = 0; end;
457
458               % Normalize components to correct ranges.
459               y(i,:) = datevecmx(datenummx(c));
460           end
461       catch
462           err = lasterror;
463           err.message = sprintf('Failed to parse date string.\n%s',...
464                                 err.message);
465           rethrow(err);
466       end
467       if nargout > 1
468           mo = y(:,2);
469           d  = y(:,3);
470           h  = y(:,4);
471           mi = y(:,5);
472           s  = y(:,6);
473           y  = y(:,1);
474       end
475    end
476elseif nargout <= 1
477   % date number was specified
478   y = datevecmx(t);
479elseif nargout == 3
480    % date number was specified and first three date fields for output
481   [y,mo,d] = datevecmx(t);
482else
483   % date number was specified and all six date fields for output
484   [y,mo,d,h,mi,s] = datevecmx(t);
485end
486end
487%--------------------------------------------------------------------------
488%--
489function [format] = getformat(str)
490  format = '';
491  formatstr = cell(11,1);
492  formatstr(1) = {'dd-mmm-yyyy HH:MM:SS'};
493  formatstr(2) = {'dd-mmm-yyyy'};
494  formatstr(3) = {'mm/dd/yy'};
495  formatstr(4) = {'mm/dd'};
496  formatstr(5) = {'HH:MM:SS'};
497  formatstr(6) = {'HH:MM:SS PM'};
498  formatstr(7) = {'HH:MM'};
499  formatstr(8) = {'HH:MM PM'};
500  formatstr(9) = {'mm/dd/yyyy'};
501  formatstr(10) = {'dd-mmm-yyyy HH:MM'};  %used by finance
502  formatstr(11) = {'dd-mmm-yy'};  %used by finance
503 
504  AlphaFormats = [1 1 0 0 0 1 0 1 0 1 1];
505  %[1 2 6 8 10 11];
506  SlashFormats = [ 0 0 1 1 0 0 0 0 1 0 0];
507  %[3 4 9];
508  TwoSlashFormats = [ 0 0 1 0 0 0 0 0 1 0 0];
509  %[3 9];
510  DashFormats = [ 1 1 0 0 0 0 0 0 0 1 1];
511  %[1 2 10 11];
512  ColonFormats = [1 0 0 0 1 1 1 1 0 1 0];
513  %[1 5 6 7 8 10];
514  TwoColonFormats = [1 0 0 0 1 1 0 0 0 0 0];
515  %[1 5 6];
516  SpaceFormats = [1 0 0 0 0 1 0 1 0 1 0];
517  %[1 6 8 10];
518 
519  bMask = [ 1 1 1 1 1 1 1 1 1 1 1];
520 
521  if length(str) > 1
522      str = str(1,1);
523  end
524  str = strtrim(char(str));
525  slashes = strfind(str, '/');
526  if ~isempty(slashes)
527          bMask = bMask & SlashFormats;
528          if (length(slashes) > 0 && slashes(1) == 2)
529                  if (length(slashes) > 1 && slashes(2) == 4)
530                          str = ['0' str(1:slashes(1)) '0' str(slashes(1)+1:end)];
531                  else
532                          str = ['0' str];
533                  end
534          elseif (length(slashes) > 1 && slashes(2) - slashes(1) == 2)
535                  str = [str(1:slashes(1)) '0' str(slashes(1)+1:end)];
536          end
537          if length(slashes) > 1
538                  bMask = bMask & TwoSlashFormats;
539          else
540                  bMask = bMask & ~TwoSlashFormats;
541          end
542  else
543          bMask = bMask & ~SlashFormats;
544  end
545 
546  dashes = strfind(str,'-');
547  if ~isempty(dashes)
548          bMask = bMask & DashFormats;
549          if (length(dashes) > 0 && dashes(1) == 2)
550                str = ['0' str];
551          end
552  else
553          bMask = bMask & ~DashFormats;   
554  end
555 
556  colons = strfind(str,':');
557  if ~isempty(colons)
558          bMask = bMask & ColonFormats;
559          if (length(colons) > 0) && (colons(1) == 2) && (length(str) - colons(end) > 3)
560                str = ['0' str];
561          end
562          if length(colons) > 1
563                  bMask = bMask & TwoColonFormats;
564          else
565                  bMask = bMask & ~TwoColonFormats;
566          end     
567  else
568          bMask = bMask & ~ColonFormats;
569  end     
570 
571  spaces = strfind(str,' ');
572  if ~isempty(spaces)
573          bMask = bMask & SpaceFormats;
574  else
575          bMask = bMask & ~SpaceFormats;
576  end
577 
578  for i = 1:11
579          if bMask(i)
580                  try
581                          str1 = dateformverify(str,char(formatstr(i)));
582                        if (strcmpi(str, strtrim(str1)) == 1)
583                                format = char(formatstr(i));
584                                break;
585                        end
586                  catch
587                           lasterr('');
588                  end
589                  if AlphaFormats(i)
590                          try
591                                str1 = dateformverify(str,char(formatstr(i)),'local');
592                                if (strcmpi(str, strtrim(str1)) == 1)
593                                        format = char(formatstr(i));
594                                        break;
595                                end
596                          catch
597                                lasterr('');
598                          end       
599                  end
600          end
601  end
602 end
Note: See TracBrowser for help on using the repository browser.