From bug-request at octave dot org Sat Jan 14 02:01:07 2006 Subject: Re: etime doc string patch From: Paul Kienzle To: "John W. Eaton" Cc: Keith Goodman , bug@octave.org Date: Sat, 14 Jan 2006 02:59:45 -0500 --Apple-Mail-8-4595149 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed On Jan 13, 2006, at 2:42 PM, John W. Eaton wrote: > On 10-Jan-2006, Keith Goodman wrote: > > | An etime.m doc string patch that adds the sentence: "An error is > | returned if T1 and T2 are in different years." > > I would prefer to fix the code to avoid this error. Paul Kienzle * time/etime.m: Use datenum to support times spanning year boundaries. * time/datenum.m: New function to compute day number from time. --Apple-Mail-8-4595149 Content-Transfer-Encoding: 7bit Content-Type: application/octet-stream; x-unix-mode=0644; name="etime.patch" Content-Disposition: attachment; filename=etime.patch Index: etime.m =================================================================== RCS file: /cvs/octave/scripts/time/etime.m,v retrieving revision 1.1 diff -c -p -r1.1 etime.m *** etime.m 13 Jan 2006 20:05:51 -0000 1.1 --- etime.m 14 Jan 2006 07:56:19 -0000 *************** function secs = etime (t1, t0) *** 43,74 **** 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]; ! ! 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 ! endfunction --- 43,59 ---- usage ("etime (t1, t0)"); endif ! [d1,s1] = datenum (t1); ! [d0,s0] = datenum (t0); ! 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]); --Apple-Mail-8-4595149 Content-Transfer-Encoding: 7bit Content-Type: application/octet-stream; x-unix-mode=0644; name="datenum.m" Content-Disposition: attachment; filename=datenum.m ## -*- texinfo -*- ## at deftypefn {Function File} {} datenum(Y, M, D [, h , m [, s]]) ## at 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. ## ## at seealso{date,clock,now,datestr,datevec,calendar,weekday} ## at 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); --Apple-Mail-8-4595149 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; format=flowed --Apple-Mail-8-4595149-- ------------------------------------------------------------- Octave is freely available under the terms of the GNU GPL. Octave's home on the web: http://www.octave.org How to fund new projects: http://www.octave.org/funding.html Subscription information: http://www.octave.org/archive.html -------------------------------------------------------------