# HG changeset patch
# User Ben Kurtz
# Date 1691858673 14400
#      Sat Aug 12 12:44:33 2023 -0400
# Node ID 94596528d6e60ecb6952e05710430668840ff7e2
# Parent  28562a1b2fcbb326d1e06fab6b75186456fc4eec
datevec: Allow partial matching when date format specified (bug #42241)

* datevec.m: Modify __date_str2vec__ subfunction and all calls to that
subfunction to take an exact_match that will allow partial matching when
a date format is supplied. Add BISTs to test partial matching.
* NEWS.9.md: Add note to matlab compatability section on new behavior.

diff -r 28562a1b2fcb -r 94596528d6e6 etc/NEWS.9.md
--- a/etc/NEWS.9.md	Thu Aug 10 17:37:03 2023 -0400
+++ b/etc/NEWS.9.md	Sat Aug 12 12:44:33 2023 -0400
@@ -126,6 +126,9 @@
 - `optimget` and `optimset` now error on an ambiguous match of an incomplete
 option name instead of emitting a warning.
 
+- `datevec` when provided a date format will ignore extra characters following
+an exact match in the provided date string.
+
 ### Alphabetical list of new functions added in Octave 9
 
 * `isenv`
diff -r 28562a1b2fcb -r 94596528d6e6 scripts/time/datevec.m
--- a/scripts/time/datevec.m	Thu Aug 10 17:37:03 2023 -0400
+++ b/scripts/time/datevec.m	Sat Aug 12 12:44:33 2023 -0400
@@ -136,7 +136,8 @@
           [f, rY, ry, fy, fm, fd, fh, fmi, fs] = ...
             __date_vfmt2sfmt__ (std_formats{l});
           [found y(k) m(k) d(k) h(k) mi(k) s(k)] = ...
-            __date_str2vec__ (date{k}, p, f, rY, ry, fy, fm, fd, fh, fmi, fs);
+            __date_str2vec__ (date{k}, p, f, rY, ry, fy, fm, fd, fh, fmi, ...
+                              fs, true);
           if (found)
             break;
           endif
@@ -150,7 +151,8 @@
       [f, rY, ry, fy, fm, fd, fh, fmi, fs] = __date_vfmt2sfmt__ (f);
       for k = 1:nd
         [found y(k) m(k) d(k) h(k) mi(k) s(k)] = ...
-          __date_str2vec__ (date{k}, p, f, rY, ry, fy, fm, fd, fh, fmi, fs);
+          __date_str2vec__ (date{k}, p, f, rY, ry, fy, fm, fd, fh, fmi, ...
+                            fs, false);
         if (! found)
           error ("datevec: DATE not parsed correctly with given format");
         endif
@@ -290,7 +292,7 @@
 
 endfunction
 
-function [found, y, m, d, h, mi, s] = __date_str2vec__ (ds, p, f, rY, ry, fy, fm, fd, fh, fmi, fs)
+function [found, y, m, d, h, mi, s] = __date_str2vec__ (ds, p, f, rY, ry, fy, fm, fd, fh, fmi, fs, exact_match)
 
   ## Local time zone is irrelevant, and potentially dangerous, when using
   ## strptime to simply convert a string into a broken down struct tm.
@@ -341,7 +343,10 @@
     endif
   end_unwind_protect
 
-  if (nc == columns (ds) + 1)
+  ## Require an exact match unless the user supplied a format to use, then use
+  ## that format as long as it matches the start of the string and ignore any
+  ## trailing characters.
+  if ((! exact_match && nc > 0) || (nc == columns (ds) + 1))
     found = true;
     y = tm.year + 1900; m = tm.mon + 1; d = tm.mday;
     h = tm.hour; mi = tm.min; s = tm.sec + tm.usec / 1e6;
@@ -472,6 +477,13 @@
 %!   endif
 %! end_unwind_protect
 
+## Test matching string and ignoring trailing characters
+%!test <*42241>
+%! fail ("datevec ('2013-08-01 08:00:00/xyzpdq')");
+%! assert (datevec('2013-08-01 08:00:00/xyzpdq', 'yyyy-mm-dd HH:MM:SS'), ...
+%!              [2013, 8, 1, 8, 0, 0]);
+
+
 ## Test input validation
 %!error <Invalid call> datevec ()
 %!error <none of the standard formats match> datevec ("foobar")
