diff scripts/time/datenum.m @ 13848:40e32fe44aaa

Ugrade time functions to accept millisecond format string FFF (Bug #34586) * datestr.m: Add millisecond FFF format. Change numerical formats 21,22,29 to match Matlab. Remove unused persistent variables. Vectorize some for loops. Use strrep rather than regexp where possible for speed. * datevec.m: Add millisecond FFF format. Use strrep rather than regexp where possible for speed. * datenum.m: Update docstring. Use modern coding style. Only calculate second output argument if requested. Allow cellstr inputs.
author Rik <octave@nomad.inbox5.com>
date Wed, 09 Nov 2011 14:49:09 -0800
parents b80b18f537ca
children d490ca8ab1a5
line wrap: on
line diff
--- a/scripts/time/datenum.m
+++ b/scripts/time/datenum.m
@@ -17,16 +17,25 @@
 ## <http://www.gnu.org/licenses/>.
 
 ## -*- texinfo -*-
-## @deftypefn  {Function File} {} datenum (@var{year}, @var{month}, @var{day})
-## @deftypefnx {Function File} {} datenum (@var{year}, @var{month}, @var{day}, @var{hour})
-## @deftypefnx {Function File} {} datenum (@var{year}, @var{month}, @var{day}, @var{hour}, @var{minute})
-## @deftypefnx {Function File} {} datenum (@var{year}, @var{month}, @var{day}, @var{hour}, @var{minute}, @var{second})
-## @deftypefnx {Function File} {} datenum ("date")
-## @deftypefnx {Function File} {} datenum ("date", @var{p})
-## Return the specified local time as a day number, with Jan 1, 0000
-## being day 1.  By this reckoning, Jan 1, 1970 is day number 719529.
-## The fractional portion, @var{p}, corresponds to the portion of the
-## specified day.
+## @deftypefn  {Function File} {@var{days} =} datenum (@var{datevec})
+## @deftypefnx {Function File} {@var{days} =} datenum (@var{year}, @var{month}, @var{day})
+## @deftypefnx {Function File} {@var{days} =} datenum (@var{year}, @var{month}, @var{day}, @var{hour})
+## @deftypefnx {Function File} {@var{days} =} datenum (@var{year}, @var{month}, @var{day}, @var{hour}, @var{minute})
+## @deftypefnx {Function File} {@var{days} =} datenum (@var{year}, @var{month}, @var{day}, @var{hour}, @var{minute}, @var{second})
+## @deftypefnx {Function File} {@var{days} =} datenum ("datestr")
+## @deftypefnx {Function File} {@var{days} =} datenum ("datestr", @var{p})
+## @deftypefnx {Function File} {[@var{days}, @var{secs}] =} datenum (@dots{})
+## Return the date/time input as a serial day number, with Jan 1, 0000
+## being day 1.  The fractional portion of @var{days} corresponds to the time
+## on the given day.  The input may be a date vector (see @code{datevec}), 
+## datestr (see @code{datestr}), or directly specified as input.
+##
+## When processing datestrings, @var{p} is the year at the start of the century
+## to which two-digit years will be referenced.  If not specified, it defaults
+## to the current year minus 50.
+##
+## The optional output @var{secs} holds the time on the specified day with greater
+## precision than @var{days}.
 ##
 ## Notes:
 ##
@@ -52,48 +61,43 @@
 ##
 ## @strong{Caution:} this function does not attempt to handle Julian
 ## calendars so dates before Octave 15, 1582 are wrong by as much
-## as eleven days.  Also be aware that only Roman Catholic countries
+## as eleven days.  Also, be aware that only Roman Catholic countries
 ## adopted the calendar in 1582.  It took until 1924 for it to be
 ## adopted everywhere.  See the Wikipedia entry on the Gregorian
 ## calendar for more details.
 ##
 ## @strong{Warning:} leap seconds are ignored.  A table of leap seconds
 ## is available on the Wikipedia entry for leap seconds.
-## @seealso{date, clock, now, datestr, datevec, calendar, weekday}
+## @seealso{datestr, datevec, date, clock, now, calendar, weekday}
 ## @end deftypefn
 
 ## Algorithm: Peter Baum (http://vsg.cape.com/~pbaum/date/date0.htm)
 ## Author: pkienzle <pkienzle@users.sf.net>
 
-function [days, secs] = datenum (year, month, day, hour, minute, second)
+function [days, secs] = datenum (year, month = [], day = [], hour = 0, minute = 0, second = 0)
 
   ## Days until start of month assuming year starts March 1.
   persistent monthstart = [306; 337; 0; 31; 61; 92; 122; 153; 184; 214; 245; 275];
 
-  if (nargin == 0 || (nargin > 2  && ischar (year)) || nargin > 6)
+  if (nargin == 0 || nargin > 6 || 
+     (nargin > 2 && (ischar (year) || iscellstr (year))))
     print_usage ();
   endif
-  if (ischar (year))
-    if (nargin < 2)
-      month = [];
-    endif
+
+  if (ischar (year) || iscellstr (year))
     [year, month, day, hour, minute, second] = datevec (year, month);
   else
-    if (nargin < 6) second = 0; endif
-    if (nargin < 5) minute = 0; endif
-    if (nargin < 4) hour = 0; endif
     if (nargin == 1)
       nc = columns (year);
       if (nc > 6 || nc < 3)
         error ("datenum: expected date vector containing [YEAR, MONTH, DAY, HOUR, MINUTE, SECOND]");
       endif
-      second = minute = hour = 0;
       if (nc >= 6) second = year(:,6); endif
       if (nc >= 5) minute = year(:,5); endif
-      if (nc >= 4) hour = year(:,4); endif
-      day = year(:,3);
+      if (nc >= 4) hour   = year(:,4); endif
+      day   = year(:,3);
       month = year(:,2);
-      year = year(:,1);
+      year  = year(:,1);
     endif
   endif
 
@@ -120,30 +124,32 @@
   day += 365*year + floor (year/4) - floor (year/100) + floor (year/400);
 
   ## Add fraction representing current second of the day.
-  days = day + (hour+(minute+second/60)/60)/24;
+  days = day + (hour + (minute + second/60)/60)/24;
 
   ## Output seconds if asked so that etime can be more accurate
-  secs = 86400*day + hour*3600 + minute*60 + second;
+  if (isargout (2))
+    secs = day*86400 + hour*3600 + minute*60 + second;
+  endif
 
 endfunction
 
+
 %!shared part
 %! part = 0.514623842592593;
-%!assert(datenum(2001,5,19), 730990)
-%!assert(datenum([1417,6,12]), 517712)
-%!assert(datenum([2001,5,19;1417,6,12]), [730990;517712])
-%!assert(datenum(2001,5,19,12,21,3.5), 730990+part, eps)
-%!assert(datenum([1417,6,12,12,21,3.5]), 517712+part, eps)
+%!assert (datenum (2001,5,19), 730990)
+%!assert (datenum ([1417,6,12]), 517712)
+%!assert (datenum ([2001,5,19;1417,6,12]), [730990;517712])
+%!assert (datenum (2001,5,19,12,21,3.5), 730990+part, eps)
+%!assert (datenum ([1417,6,12,12,21,3.5]), 517712+part, eps)
 ## Test vector inputs
 %!test
 %! t = [2001,5,19,12,21,3.5; 1417,6,12,12,21,3.5];
 %! n = [730990; 517712] + part;
-%! assert(datenum(t), n, 2*eps);
-## Make sure that the vectors can have either orientation
-%!test
-%! t = [2001,5,19,12,21,3.5; 1417,6,12,12,21,3.5]';
-%! n = [730990 517712] + part;
-%! assert(datenum(t(1,:), t(2,:), t(3,:), t(4,:), t(5,:), t(6,:)), n, 2*eps);
+%! assert (datenum (t), n, 2*eps);
+%! ## Check that vectors can have either orientation
+%! t = t';
+%! n = n';
+%! assert (datenum (t(1,:), t(2,:), t(3,:), t(4,:), t(5,:), t(6,:)), n, 2*eps);
 
 ## Test mixed vectors and scalars
 %!assert (datenum([2008;2009], 1, 1), [datenum(2008, 1, 1);datenum(2009, 1, 1)]);
@@ -159,3 +165,14 @@
 %!assert (datenum([2008 2009], [1 2], 1), [datenum(2008, 1, 1) datenum(2009, 2, 1)]);
 %!assert (datenum([2008 2009], 1, [1 2]), [datenum(2008, 1, 1) datenum(2009, 1, 2)]);
 %!assert (datenum(2008, [1 2], [1 2]), [datenum(2008, 1, 1) datenum(2008, 2, 2)]);
+## Test string and cellstr inputs
+%!assert (datenum ("5/19/2001"), 730990)
+%!assert (datenum ({"5/19/2001"}), 730990)
+%!assert (datenum (char ("5/19/2001", "6/6/1944")), [730990; 710189])
+%!assert (datenum ({"5/19/2001", "6/6/1944"}), [730990; 710189])
+
+%% Test input validation
+%!error datenum ()
+%!error datenum (1,2,3,4,5,6,7)
+%!error datenum ([1, 2])
+%!error datenum ([1,2,3,4,5,6,7])