changeset 5660:4c4d31ecb0e4

[project @ 2006-03-10 17:27:50 by jwe]
author jwe
date Fri, 10 Mar 2006 17:27:50 +0000
parents 960f4b9a26af
children 13be36ec8279
files scripts/time/datenum.m scripts/time/etime.m
diffstat 2 files changed, 104 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/scripts/time/datenum.m
@@ -0,0 +1,92 @@
+## -*- texinfo -*-
+## @deftypefn {Function File} {} datenum(Y, M, D [, h , m [, s]])
+## @deftypefnx {Function File} {} datenum('date' [, P])
+## Returns 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, corresponds to the portion of the specified day.
+##
+## Years can be negative and/or fractional.
+## Months below 1 are considered to be January.
+## Days of the month start at 1.
+## Days beyond the end of the month go into subsequent months.
+## Days before the beginning of the month go to the previous month.
+## Days can be fractional.
+##
+## WARNING: 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
+## 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.
+##
+## 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}
+## @end deftypefn
+
+## Algorithm: Peter Baum (http://vsg.cape.com/~pbaum/date/date0.htm)
+## Author: Paul Kienzle
+## This program is granted to the public domain.
+
+function [days,secs] = datenum(Y,M,D,h,m,s)
+  ## 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(Y)) || nargin > 6
+    usage("n=datenum('date' [, P]) or n=datenum(Y, M, D [, h, m [, s]])");
+  endif
+  if ischar(Y)
+    if nargin < 2, M=[]; endif
+    error('string form of dates not yet supported');
+    ## [Y,M,D,h,m,s] = datevec(Y,M);
+  else
+    if nargin < 6, s = 0; endif
+    if nargin < 5, m = 0; endif
+    if nargin < 4, h = 0; endif
+    if nargin == 1
+      nc = columns(Y);
+      if nc > 6 || nc < 3,
+        error("expected date vector containing [Y,M,D,h,m,s]");
+      endif
+      s=m=h = 0;
+      if nc >= 6, s = Y(:,6); endif
+      if nc >= 5, m = Y(:,5); endif
+      if nc >= 4, h = Y(:,4); endif
+      D = Y(:,3);
+      M = Y(:,2);
+      Y = Y(:,1);
+    endif 
+  endif
+
+  M(M<1) = 1; ## For compatibility.  Otherwise allow negative months.
+
+  ## Set start of year to March by moving Jan. and Feb. to previous year.
+  ## Correct for months > 12 by moving to subsequent years.
+  Y += fix((M-14)/12);
+
+  ## Lookup number of days since start of the current year.
+  D += monthstart (mod (M-1,12) + 1) + 60;
+
+  ## Add number of days to the start of the current year. Correct
+  ## for leap year every 4 years except centuries not divisible by 400.
+  D += 365*Y+floor(Y/4)-floor(Y/100)+floor(Y/400);
+
+  ## Add fraction representing current second of the day.
+  days = D + (h+(m+s/60)/60)/24;
+
+  ## Output seconds if asked so that etime can be more accurate
+  secs = 86400*D + h*3600 + m*60 + s;
+
+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)
+%!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);
--- a/scripts/time/etime.m
+++ b/scripts/time/etime.m
@@ -42,32 +42,18 @@
     usage ("etime (t1, t0)");
   endif
 
-  if (isvector (t1) && length (t1) == 6 && isvector (t0) && length (t0) == 6)
-
-    if (t1 (1) != t0 (1))
-      error ("etime: can't handle timings over year boundaries yet");
-    endif
-
-    ## XXX FIXME XXX -- could check here to ensure that t1 and t0 really do
-    ## make sense as vectors returned from clock().
-
-    days_in_months = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+  [d1, s1] = datenum (t1);
+  [d0, s0] = datenum (t0);
 
-    if (is_leap_year (t1 (1)))
-      days_in_months (2) = days_in_months (2) + 1;
-    endif
-
-    d1 = sum (days_in_months (1:(t1 (2) - 1))) + t1 (3);
-    d0 = sum (days_in_months (1:(t0 (2) - 1))) + t0 (3);
-
-    s1 = 86400 * d1 + 3600 * t1 (4) + 60 * t1 (5) + t1 (6);
-    s0 = 86400 * d0 + 3600 * t0 (4) + 60 * t0 (5) + t0 (6);
-
-    secs = s1 - s0;
-
-  else
-    error ("etime: args are not 6-element vectors");
-  endif
-
+  secs = s1 - s0;
 
 endfunction
+
+%!assert(etime([1900,12,31,23,59,59],[1901,1,1,0,0,0]),-1)
+%!assert(etime([1900,2,28,23,59,59],[1900,3,1,0,0,0]),-1)
+%!assert(etime([2000,2,28,23,59,59],[2000,3,1,0,0,0]),-86401)
+%!assert(etime([1996,2,28,23,59,59],[1996,3,1,0,0,0]),-86401)
+%!test
+%!  t1 = [1900,12,31,23,59,59; 1900,2,28,23,59,59];
+%!  t2 = [1901,1,1,0,0,0; 1900,3,1,0,0,0];
+%!  assert(etime(t2, t1), [1;1]);