changeset 23267:afa48a26e684 stable

datenum.m: Accept legal input of vectors with fractional months (bug #50508). * datenum.m: Accept vector inputs which contain fractional months. Include the effects of leap years for fractional February months. Add BIST tests for February calculations.
author Rik <rik@octave.org>
date Sun, 12 Mar 2017 11:27:52 -0700
parents b53dfa60f045
children a21f8372bb76
files scripts/time/datenum.m
diffstat 1 files changed, 14 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/time/datenum.m	Fri Mar 10 16:29:19 2017 -0800
+++ b/scripts/time/datenum.m	Sun Mar 12 11:27:52 2017 -0700
@@ -123,19 +123,17 @@
     error ("datenum: all inputs must be of class double");
   endif
 
-  month(month < 1) = 1;  # For compatibility.  Otherwise allow negative months.
+  ## For Matlab compatibility.  Otherwise, could allow negative months.
+  month(month < 1) = 1;
 
   ## Treat fractional months, by converting the fraction to days
-  if (floor (month) != month)
+  if (any (month != fix (month)))
     fracmonth = month - floor (month);
     month = floor (month);
-    if ((mod (month-1,12) + 1) == 2
-        && (floor (year/4) - floor (year/100) + floor (year/400)) != 0)
-      ## leap year
-      day += fracmonth * 29;
-    else
-      day += fracmonth * monthlength ((mod (month-1,12) + 1));
-    endif
+    ## Separate regular months from leap months
+    idx = mod (month-1,12) + 1 != 2 | ! is_leap_year (floor (year));
+    day(idx) += fracmonth(idx) .* monthlength ((mod (month(idx)-1,12) + 1));
+    day(! idx) += fracmonth(! idx) * 29;
   endif
 
   ## Set start of year to March by moving Jan. and Feb. to previous year.
@@ -176,6 +174,7 @@
 %!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];
@@ -186,6 +185,10 @@
 %! n = n';
 %! assert (datenum (t(1,:), t(2,:), t(3,:), t(4,:), t(5,:), t(6,:)), n, 2*eps);
 
+## Test fractional months including leap months
+%!assert (fix (datenum ([2001 1.999 1; 2001 2.999 1])), [730882; 730910])
+%!assert (fix (datenum ([2004 1.999 1; 2004 2.999 1])), [731977; 732006])
+
 ## Test mixed vectors and scalars
 %!assert (datenum ([2008;2009],1,1), [datenum(2008,1,1);datenum(2009,1,1)])
 %!assert (datenum (2008, [1;2], 1), [datenum(2008,1,1);datenum(2008,2,1)])
@@ -200,11 +203,13 @@
 %!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 string input with format string
 %!assert (datenum ("5-19, 2001", "mm-dd, yyyy"), 730990)