changeset 5687:a2902024bc4e

[project @ 2006-03-16 20:22:40 by jwe]
author jwe
date Thu, 16 Mar 2006 20:22:41 +0000
parents e7790bb14cfc
children 6274256266d9
files scripts/ChangeLog scripts/time/calendar.m scripts/time/datenum.m scripts/time/datestr.m scripts/time/datevec.m scripts/time/eomday.m scripts/time/now.m scripts/time/weekday.m
diffstat 8 files changed, 930 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog
+++ b/scripts/ChangeLog
@@ -1,3 +1,8 @@
+2006-03-15  William Poetra Yoga Hadisoeseno  <williampoetra@gmail.com>
+
+	* time/calendar.m, time/datestr.m, time/datevec.m, time/eomday.m,
+	time/now.m, time/weekday.m: New functions from Octave Forge.
+
 2006-03-16  John W. Eaton  <jwe@octave.org>
 
 	* control/base/bode_bounds.m: Check for iip and iiz empty instead
new file mode 100644
--- /dev/null
+++ b/scripts/time/calendar.m
@@ -0,0 +1,102 @@
+## Copyright (C) 2004 Paul Kienzle
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, write to the Free
+## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {} calendar (@dots{})
+## @deftypefnx {Function File} {@var{c} =} calendar ()
+## @deftypefnx {Function File} {@var{c} =} calendar (@var{d})
+## @deftypefnx {Function File} {@var{c} =} calendar (@var{y}, @var{m})
+## If called with no arguments, return the current monthly calendar in
+## a 6x7 matrix.
+##
+## If @var{d} is specified, return the calendar for the month containing
+## the day @var{d}, which must be a serial date number or a date string.
+##
+## If @var{y} and @var{m} are specified, return the calendar for year @var{y}
+## and month @var{m}.
+##
+## If no output arguments are specified, print the calendar on the screen
+## instead of returning a matrix.
+## @seealso{datenum}
+## @end deftypefn
+
+## Author: pkienzle <pkienzle@users.sf.net>
+## Created: 25 July 2004
+## Adapted-By: William Poetra Yoga Hadisoeseno <williampoetra@gmail.com>
+
+function varargout = calendar (varargin)
+
+  switch (nargin)
+    case 0
+      v = clock ();
+      y = v(1);
+      m = v(2);
+      d = v(3);
+    case 1
+      v = datevec (varargin{1});
+      y = v(1);
+      m = v(2);
+      d = v(3);
+    case 2
+      y = varargin{1};
+      m = varargin{2};
+      d = [];
+    otherwise
+      usage ("calendar () or c = calendar (d) or c = calendar (y, m)");
+  endswitch
+
+  c = zeros (7, 6);
+  dayone = datenum (y, m, 1);
+  ndays = eomday (y, m);
+  c(weekday (dayone) - 1 + [1:ndays]) = 1:ndays;
+
+  if (nargout > 0)
+    varargout{1} = c';
+  else
+    ## Layout the calendar days, 6 columns per day, 7 days per row.
+    str = sprintf ("    %2d    %2d    %2d    %2d    %2d    %2d    %2d\n", c);
+
+    ## Print an asterisk before the specified date
+    if (! isempty (d) && d >= 1 && d <= ndays)
+      pos = weekday (dayone) + d - 1;
+      idx = 6 * (pos - 1) + floor (pos / 7) + 1;
+      while (str(idx) == " ")
+        ++idx;
+      endwhile
+      str(--idx) = "*";
+    endif
+
+    ## Display the calendar.
+    s.year = y - 1900;
+    s.mon = m - 1;
+    puts (strftime ("                    %b %Y\n", s));
+    puts ("     S     M    Tu     W    Th     F     S\n");
+    puts (str);
+  endif
+
+endfunction
+
+# tests
+%!assert((calendar(2000,2))'(2:31),[0:29]);
+%!assert((calendar(1957,10))'(2:33),[0:31]);
+# demos
+%!demo
+%! calendar ()
+%!demo
+%! calendar (1957, 10)
--- a/scripts/time/datenum.m
+++ b/scripts/time/datenum.m
@@ -59,7 +59,7 @@
 ## @end deftypefn
 
 ## Algorithm: Peter Baum (http://vsg.cape.com/~pbaum/date/date0.htm)
-## Author: Paul Kienzle
+## Author: pkienzle <pkienzle@users.sf.net>
 
 function [days, secs] = datenum (Y, M, D, h, m, s)
 
new file mode 100644
--- /dev/null
+++ b/scripts/time/datestr.m
@@ -0,0 +1,338 @@
+## Copyright (C) 2000, 2001, 2002, 2003, 2005 Paul Kienzle
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, write to the Free
+## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{str} =} datestr (@var{date}, [@var{f}, [@var{p}]])
+## Format the given date/time according to the format @code{f} and return
+## the result in @var{str}. @var{date} is a serial date number (see
+## @code{datenum}) or a date vector (see @code{datevec}). For compatibility
+## with Matlab, @var{date} may also be a string or cell array of strings.
+##
+## @var{f} can be an integer which corresponds to one of the codes in
+## the table below, or a date format string.
+##
+## @var{p} is the year at the start of the century in which two-digit years
+## are to be interpreted in. If not specified, it defaults to the current
+## year minus 50.
+##
+## For example, the date 730736.65149 (2000-09-07 15:38:09.0934) would be
+## formatted as follows:
+##
+## @multitable @columnfractions 0.1 0.45 0.35
+## @headitem Code @tab Format @tab Example
+## @item  0 @tab dd-mmm-yyyy HH:MM:SS   @tab 07-Sep-2000 15:38:09
+## @item  1 @tab dd-mmm-yyyy            @tab 07-Sep-2000
+## @item  2 @tab mm/dd/yy               @tab 09/07/00
+## @item  3 @tab mmm                    @tab Sep
+## @item  4 @tab m                      @tab S
+## @item  5 @tab mm                     @tab 09
+## @item  6 @tab mm/dd                  @tab 09/07
+## @item  7 @tab dd                     @tab 07
+## @item  8 @tab ddd                    @tab Thu
+## @item  9 @tab d                      @tab T
+## @item 10 @tab yyyy                   @tab 2000
+## @item 11 @tab yy                     @tab 00
+## @item 12 @tab mmmyy                  @tab Sep00
+## @item 13 @tab HH:MM:SS               @tab 15:38:09
+## @item 14 @tab HH:MM:SS PM            @tab 03:38:09 PM
+## @item 15 @tab HH:MM                  @tab 15:38
+## @item 16 @tab HH:MM PM               @tab 03:38 PM
+## @item 17 @tab QQ-YY                  @tab Q3-00
+## @item 18 @tab QQ                     @tab Q3
+## @item 19 @tab dd/mm                  @tab 13/03
+## @item 20 @tab dd/mm/yy               @tab 13/03/95
+## @item 21 @tab mmm.dd.yyyy HH:MM:SS   @tab Mar.03.1962 13:53:06
+## @item 22 @tab mmm.dd.yyyy            @tab Mar.03.1962
+## @item 23 @tab mm/dd/yyyy             @tab 03/13/1962
+## @item 24 @tab dd/mm/yyyy             @tab 12/03/1962
+## @item 25 @tab yy/mm/dd               @tab 95/03/13
+## @item 26 @tab yyyy/mm/dd             @tab 1995/03/13
+## @item 27 @tab QQ-YYYY                @tab Q4-2132
+## @item 28 @tab mmmyyyy                @tab Mar2047
+## @item 29 @tab yyyymmdd               @tab 20470313
+## @item 30 @tab yyyymmddTHHMMSS        @tab 20470313T132603
+## @item 31 @tab yyyy-mm-dd HH:MM:SS    @tab 1047-03-13 13:26:03
+## @end multitable
+##
+## If @var{f} is a format string, the following symbols are recognised:
+##
+## @multitable @columnfractions 0.1 0.7 0.2
+## @headitem Symbol @tab Meaning @tab Example
+## @item yyyy @tab Full year                                    @tab 2005
+## @item yy   @tab Two-digit year                               @tab 2005
+## @item mmmm @tab Full month name                              @tab December
+## @item mmm  @tab Abbreviated month name                       @tab Dec
+## @item mm   @tab Numeric month number (padded with zeros)     @tab 01, 08, 12
+## @item m    @tab First letter of month name (capitalized)     @tab D
+## @item dddd @tab Full weekday name                            @tab Sunday
+## @item ddd  @tab Abbreviated weekday name                     @tab Sun
+## @item dd   @tab Numeric day of month (padded with zeros)     @tab 11
+## @item d    @tab First letter of weekday name (capitalized)   @tab S
+## @item HH   @tab Hour of day, padded with zeros if PM is set  @tab 09:00
+## @item      @tab and not padded with zeros otherwise          @tab 9:00 AM
+## @item MM   @tab Minute of hour (padded with zeros)           @tab 10:05
+## @item SS   @tab Second of minute (padded with zeros)         @tab 10:05:03
+## @item PM   @tab Use 12-hour time format                      @tab 11:30 PM
+## @end multitable
+##
+## If @var{f} is not specified or is @code{-1}, then use 0, 1 or 16,
+## depending on whether the date portion or the time portion of
+## @var{date} is empty.
+##
+## If @var{p} is nor specified, it defaults to the current year minus 50.
+##
+## If a matrix or cell array of dates is given, a vector of date strings is
+## returned.
+##
+## @seealso{datenum, datevec, date, clock, now, datetick}
+## @end deftypefn
+
+## TODO: parse arbitrary code strings.
+## TODO: e.g., for  Wednesday 2001-03-05 09:04:06 AM, use
+## TODO:     yy    01
+## TODO:     yyyy  2001
+## TODO:     m     M
+## TODO:     mm    03
+## TODO:     mmm   Mar
+## TODO:     d     W
+## TODO:     dd    05
+## TODO:     ddd   Wed
+## TODO:     HH    09
+## TODO:     MM    04
+## TODO:     SS    06
+## TODO:     PM    AM
+## TODO: Vectorize.  It is particularly easy since all the codes are
+## TODO:    fixed width.  Just generate the parts in separate arrays and
+## TODO:    concatenate.
+
+## Author: pkienzle <pkienzle@users.sf.net>
+## Created: 10 October 2001 (CVS)
+## Adapted-By: William Poetra Yoga Hadisoeseno <williampoetra@gmail.com>
+
+function retval = datestr (date, f, p)
+
+  persistent dateform names_mmmm names_mmm names_m names_dddd names_ddd names_d;
+
+  if (isempty (dateform))
+
+    dateform = cell (32, 1);
+    dateform{1} = "dd-mmm-yyyy HH:MM:SS";
+    dateform{2} = "dd-mmm-yyyy";
+    dateform{3} = "mm/dd/yy";
+    dateform{4} = "mmm";
+    dateform{5} = "m";
+    dateform{6} = "mm";
+    dateform{7} = "mm/dd";
+    dateform{8} = "dd";
+    dateform{9} = "ddd";
+    dateform{10} = "d";
+    dateform{11} = "yyyy";
+    dateform{12} = "yy";
+    dateform{13} = "mmmyy";
+    dateform{14} = "HH:MM:SS";
+    dateform{15} = "HH:MM:SS PM";
+    dateform{16} = "HH:MM";
+    dateform{17} = "HH:MM PM";
+    dateform{18} = "QQ-YY";
+    dateform{19} = "QQ";
+    dateform{20} = "dd/mm";
+    dateform{21} = "dd/mm/yy";
+    dateform{22} = "mmm.dd.yyyy HH:MM:SS";
+    dateform{23} = "mmm.dd.yyyy";
+    dateform{24} = "mm/dd/yyyy";
+    dateform{25} = "dd/mm/yyyy";
+    dateform{26} = "yy/mm/dd";
+    dateform{27} = "yyyy/mm/dd";
+    dateform{28} = "QQ-YYYY";
+    dateform{29} = "mmmyyyy";
+    dateform{30} = "yyyymmdd";
+    dateform{31} = "yyyymmddTHHMMSS";
+    dateform{32} = "yyyy-mm-dd HH:MM:SS";
+
+    names_mmmm = {"January"; "February"; "March"; "April";
+                  "May"; "June"; "July"; "August";
+                  "September"; "October"; "November"; "December"};
+
+    names_mmm = {"Jan"; "Feb"; "Mar"; "Apr"; "May"; "Jun";
+                 "Jul"; "Aug"; "Sep"; "Oct"; "Nov"; "Dec"};
+
+    names_m = {"J"; "F"; "M"; "A"; "M"; "J"; "J"; "A"; "S"; "O"; "N"; "D"};
+
+    names_dddd = {"Sunday"; "Monday"; "Tuesday"; "Wednesday";
+                  "Thursday"; "Friday"; "Saturday"};
+
+    names_ddd = {"Sun"; "Mon"; "Tue"; "Wed"; "Thu"; "Fri"; "Sat"};
+
+    names_d = {"S"; "M"; "T"; "W"; "T"; "F"; "S"};
+
+  endif
+
+  if (nargin < 1 || nargin > 3)
+    usage("str = datestr (date, [f, [p]])");
+  endif
+
+  if (nargin < 2)
+    f = [];
+  endif
+  if (nargin < 3)
+    p = [];
+  endif
+
+  if (ischar (date))
+    t = date;
+    date = cell (1);
+    date{1} = t;
+  endif
+
+  # guess, so we might be wrong
+  if (iscell (date) || columns (date) != 6)
+    v = datevec (date, p);
+  else
+    v = date;
+  endif
+
+  for i = 1:(rows (v))
+
+    if (isempty (f) || f == -1)
+      if (v(i,4:6) == 0)
+        f = 1;
+      #elseif (v(i,1:3) == [0, 1, 1])
+      elseif (v(i,1:3) == [-1, 12, 31])
+        f = 16;
+      else
+        f = 0;
+      endif
+    endif
+
+    if (isnumeric (f))
+      df = dateform{f + 1};
+    else
+      df = f;
+    endif
+
+    ## dates to lowercase (note: we cannot convert MM to mm)
+    df = strrep (df, "YYYY", "yyyy");
+    df = strrep (df, "YY", "yy");
+    df = strrep (df, "QQ", "qq");
+    df = strrep (df, "MMMM", "mmmm");
+    df = strrep (df, "MMM", "mmm");
+    #### BEGIN NOT-SO-UGLY HACK ####
+    idx_MM = strfind (df, "MM");
+    idx_AM = strfind (df, "AM");
+    idx_PM = strfind (df, "PM");
+    df = strrep (df, "M", "m");
+    df([idx_MM, idx_MM + 1, idx_AM + 1, idx_PM + 1]) = "M";
+    df(idx_AM) = "A";
+    df(idx_PM) = "P";
+    ####  END NOT-SO-UGLY HACK  ####
+    df = strrep (df, "DDDD", "dddd");
+    df = strrep (df, "DDD", "ddd");
+    df = strrep (df, "DD", "dd");
+    df = strrep (df, "D", "d");
+    ## times to uppercase (also cannot convert mm to MM)
+    df = strrep (df, "hh", "HH");
+    df = strrep (df, "ss", "SS");
+    df = strrep (df, "am", "AM");
+    df = strrep (df, "pm", "PM");
+
+    str = df;
+    ## replace date symbols with actual values
+    str = strrep (str, "yyyy", sprintf ("%04d", v(i,1)));
+    str = strrep (str, "yy", sprintf ("%02d", rem (v(i,1), 100)));
+    str = strrep (str, "qq", sprintf ("Q%d", fix ((v(i,2) + 2) / 3)));
+    str = strrep (str, "mmmm", names_mmmm{v(i,2)});
+    str = strrep (str, "mmm", names_mmm{v(i,2)});
+    str = strrep (str, "mm", sprintf ("%02d", v(i,2)));
+    str = strrep (str, "m", names_m{v(i,2)});
+    str = strrep (str, "dddd", names_dddd{weekday (datenum (v(i,1), v(i,2), v(i,3)))});
+    str = strrep (str, "ddd", names_ddd{weekday (datenum (v(i,1), v(i,2), v(i,3)))});
+    str = strrep (str, "dd", sprintf ("%02d", v(i,3)));
+    str = strrep (str, "d", names_d{weekday (datenum (v(i,1), v(i,2), v(i,3)))});
+    ## replace time symbols with actual values
+    if ((any (strfind (str, "AM")) || any (strfind (str, "PM"))))
+      if (v(i,4) > 12)
+        str = strrep (str, "HH", sprintf ("%d", v(i,4) - 12));
+      else
+        str = strrep (str, "HH", sprintf ("%d", v(i,4)));
+      endif
+      if (v(i,4) < 12)
+        str = strrep (str, "AM", "AM");
+        str = strrep (str, "PM", "AM");
+      else
+        str = strrep (str, "AM", "PM");
+        str = strrep (str, "PM", "PM");
+      endif
+    else
+      str = strrep (str, "HH", sprintf ("%02d", v(i,4)));
+    endif
+    str = strrep (str, "MM", sprintf ("%02d", v(i,5)));
+    str = strrep (str, "SS", sprintf ("%02d", v(i,6)));
+
+    if (i == 1)
+      retval = str;
+    else
+      retval = [retval; str];
+    endif
+
+  endfor
+
+endfunction
+
+# simple tests
+%!shared testtime
+%! testtime = [2005.0000, 12.0000, 18.0000, 2.0000, 33.0000, 17.3822];
+%!assert(datestr(testtime,0),"18-Dec-2005 02:33:17");
+%!assert(datestr(testtime,1),"18-Dec-2005");
+%!assert(datestr(testtime,2),"12/18/05");
+%!assert(datestr(testtime,3),"Dec");
+%!assert(datestr(testtime,4),"D");
+%!assert(datestr(testtime,5),"12");
+%!assert(datestr(testtime,6),"12/18");
+%!assert(datestr(testtime,7),"18");
+%!assert(datestr(testtime,8),"Sun");
+%!assert(datestr(testtime,9),"S");
+%!assert(datestr(testtime,10),"2005");
+%!assert(datestr(testtime,11),"05");
+%!assert(datestr(testtime,12),"Dec05");
+%!assert(datestr(testtime,13),"02:33:17");
+%!assert(datestr(testtime,14),"2:33:17 AM");
+%!assert(datestr(testtime,15),"02:33");
+%!assert(datestr(testtime,16),"2:33 AM");
+%!assert(datestr(testtime,17),"Q4-05");
+%!assert(datestr(testtime,18),"Q4");
+%!assert(datestr(testtime,19),"18/12");
+%!assert(datestr(testtime,20),"18/12/05");
+%!assert(datestr(testtime,21),"Dec.18.2005 02:33:17");
+%!assert(datestr(testtime,22),"Dec.18.2005");
+%!assert(datestr(testtime,23),"12/18/2005");
+%!assert(datestr(testtime,24),"18/12/2005");
+%!assert(datestr(testtime,25),"05/12/18");
+%!assert(datestr(testtime,26),"2005/12/18");
+%!assert(datestr(testtime,27),"Q4-2005");
+%!assert(datestr(testtime,28),"Dec2005");
+%!assert(datestr(testtime,29),"20051218");
+%!assert(datestr(testtime,30),"20051218T023317");
+%!assert(datestr(testtime,31),"2005-12-18 02:33:17");
+# demos
+%!demo
+%! datestr (now ())
+%!demo
+%! datestr (rem (now (), 1))
+%!demo
+%! datestr (floor (now ()))
new file mode 100644
--- /dev/null
+++ b/scripts/time/datevec.m
@@ -0,0 +1,302 @@
+## Copyright (C) 2000, 2001, 2004, 2005 Paul Kienzle
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, write to the Free
+## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{v} =} datevec (@var{date})
+## @deftypefnx {Function File} {@var{v} =} datevec (@var{date}, @var{f})
+## @deftypefnx {Function File} {@var{v} =} datevec (@var{date}, @var{p})
+## @deftypefnx {Function File} {@var{v} =} datevec (@var{date}, @var{f}, @var{p})
+## @deftypefnx {Function File} {[@var{y}, @var{m}, @var{d}, @var{h}, @var{mi}, @var{s}] =} datevec (@dots{})
+## Convert a serial date number (see @code{datenum}) or date string (see
+## @code{datestr}) into a date vector.
+##
+## A date vector is a row vector with six members, representing the year,
+## month, day, hour, minute, and seconds respectively.
+##
+## @var{f} is the format string used to interpret date strings
+## (see @code{datestr}).
+##
+## @var{p} is the year at the start of the century in which two-digit years
+## are to be interpreted in. If not specified, it defaults to the current
+## year minus 50.
+## @seealso{datenum, datestr, date, clock, now}
+## @end deftypefn
+
+## Algorithm: Peter Baum (http://vsg.cape.com/~pbaum/date/date0.htm)
+
+## Author: pkienzle <pkienzle@users.sf.net>
+## Modified: bdenney <bill@givebillmoney.com>
+## Created: 10 October 2001 (CVS)
+## Adapted-By: William Poetra Yoga Hadisoeseno <williampoetra@gmail.com>
+
+## The function __date_str2vec__ is based on datesplit by Bill Denney.
+
+function [y, m, d, h, mi, s] = datevec (date, varargin)
+
+  persistent std_formats nfmt;
+
+  if (isempty (std_formats))
+    std_formats = cell ();
+    nfmt = 0;
+    std_formats{++nfmt} = "dd-mmm-yyyy HH:MM:SS";   # 0
+    std_formats{++nfmt} = "dd-mmm-yyyy";            # 1
+    std_formats{++nfmt} = "mm/dd/yy";               # 2
+    std_formats{++nfmt} = "mm/dd";                  # 6
+    std_formats{++nfmt} = "HH:MM:SS";               # 13
+    std_formats{++nfmt} = "HH:MM:SS PM";            # 14
+    std_formats{++nfmt} = "HH:MM";                  # 15
+    std_formats{++nfmt} = "HH:MM PM";               # 16
+    std_formats{++nfmt} = "mm/dd/yyyy";             # 23
+    # custom formats
+    std_formats{++nfmt} = "mmmyy";                  # 12
+    std_formats{++nfmt} = "mm/dd/yyyy HH:MM";
+  endif
+
+  if (nargin < 1 || nargin > 3)
+    usage("v = datevec (...) or [y, m, d, h, mi, s] = datevec (...)");
+  endif
+
+  switch (nargin)
+  case 1
+    f = [];
+    p = [];
+  case 2
+    if (ischar (varargin{1}))
+      f = varargin{1};
+      p = [];
+    else
+      f = [];
+      p = varargin{1};
+    endif
+  case 3
+      f = varargin{1};
+      p = varargin{2};
+  endswitch
+
+  if (isempty (f))
+    f = -1;
+  endif
+
+  if (isempty (p))
+    p = (localtime (time)).year + 1900 - 50;
+  endif
+
+  if (ischar (date))
+    t = date;
+    date = cell (1);
+    date{1} = t;
+  endif
+
+  if (iscell (date))
+
+    nd = numel (date);
+
+    y = m = d = h = mi = s = zeros (nd, 1);
+
+    if (f == -1)
+      for k = 1:nd
+        found = false;
+        for l = 1:nfmt
+          [found y(k) m(k) d(k) h(k) mi(k) s(k)] = __date_str2vec__ (date{k}, std_formats{l}, p);
+          if (found)
+            break;
+          endif
+        endfor
+        if (! found)
+          error ("datevec: none of the standard formats match the date string");
+        endif
+      endfor
+    else
+      for k = 1:nd
+        [found y(k) m(k) d(k) h(k) mi(k) s(k)] = __date_str2vec__ (date{k}, f, p);
+        if (! found)
+          error ("datevec: date not parsed correctly with given format");
+        endif
+      endfor
+    endif
+
+  else
+
+    date = date(:);
+
+    ## Move day 0 from midnight -0001-12-31 to midnight 0000-3-1
+    z = floor (date) - 60;
+    ## Calculate number of centuries; K1 = 0.25 is to avoid rounding problems.
+    a = floor ((z - 0.25) / 36524.25);
+    ## Days within century; K2 = 0.25 is to avoid rounding problems.
+    b = z - 0.25 + a - floor (a / 4);
+    ## Calculate the year (year starts on March 1).
+    y = floor (b / 365.25);
+    ## Calculate day in year.
+    c = fix (b - floor (365.25 * y)) + 1;
+    ## Calculate month in year.
+    m = fix ((5 * c + 456) / 153);
+    d = c - fix ((153 * m - 457) / 5);
+    ## Move to Jan 1 as start of year.
+    ++y(m > 12);
+    m(m > 12) -= 12;
+
+    ## Convert hour-minute-seconds
+    s = 86400 * (date - floor (date));
+    h = floor (s / 3600);
+    s = s - 3600 * h;
+    mi = floor (s / 60);
+    s = s - 60 * mi;
+
+  endif
+
+  if (nargout <= 1)
+    y = [y m d h mi s];
+  endif
+
+### endfunction
+
+function [found, y, m, d, h, mi, s] = __date_str2vec__ (ds, f, p)
+
+  # Play safe with percent signs
+  f = strrep(f, "%", "%%");
+
+  ## dates to lowercase (note: we cannot convert MM to mm)
+  f = strrep (f, "YYYY", "yyyy");
+  f = strrep (f, "YY", "yy");
+  f = strrep (f, "QQ", "qq");
+  f = strrep (f, "MMMM", "mmmm");
+  f = strrep (f, "MMM", "mmm");
+  f = strrep (f, "DDDD", "dddd");
+  f = strrep (f, "DDD", "ddd");
+  f = strrep (f, "DD", "dd");
+  ## times to uppercase (also cannot convert mm to MM)
+  f = strrep (f, "hh", "HH");
+  f = strrep (f, "ss", "SS");
+  f = strrep (f, "pm", "PM");
+  f = strrep (f, "am", "AM");
+
+  ## right now, the format string may only contain these tokens:
+  ## yyyy   4 digit year
+  ## yy     2 digit year
+  ## mmmm   month name, full
+  ## mmm    month name, abbreviated
+  ## mm     month number
+  ## dddd   weekday name, full
+  ## ddd    weekday name, abbreviated
+  ## dd     date
+  ## HH     hour
+  ## MM     minutes
+  ## SS     seconds
+  ## PM     AM/PM
+  ## AM     AM/PM
+
+  if (! isempty (strfind (f, "PM")) || ! isempty (strfind (f, "AM")))
+    ampm = true;
+  else
+    ampm = false;
+  endif
+
+  # date part
+  f = strrep (f, "yyyy", "%Y");
+  f = strrep (f, "yy", "%y");
+  f = strrep (f, "mmmm", "%B");
+  f = strrep (f, "mmm", "%b");
+  f = strrep (f, "mm", "%m");
+  f = strrep (f, "dddd", "%A");
+  f = strrep (f, "ddd", "%a");
+  f = strrep (f, "dd", "%d");
+
+  # time part
+  if (ampm)
+    f = strrep (f, "HH", "%I");
+    f = strrep (f, "PM", "%p");
+    f = strrep (f, "AM", "%p");
+  else
+    f = strrep (f, "HH", "%H");
+  endif
+  f = strrep (f, "MM", "%M");
+  f = strrep (f, "SS", "%S");
+
+  [tm, nc] = strptime (ds, f);
+
+  if (nc == length (ds) + 1)
+    y = tm.year + 1900; m = tm.mon + 1; d = tm.mday;
+    h = tm.hour; mi = tm.min; s = tm.sec + tm.usec / 1e6;
+    found = true;
+    rY = rindex (f, "%Y");
+    ry = rindex (f, "%y");
+    if (rY < ry)
+      if (y > 1999)
+        y -= 2000;
+      else
+        y -= 1900;
+      endif
+      y += p - mod (p, 100);
+      if (y < p)
+        y += 100;
+      endif
+    endif
+    # check whether we need to give default values
+    # possible error when string contains "%%"
+    fy = rY || ry;
+    fm = index (f, "%m") || index (f, "%b") || index (f, "%B");
+    fd = index (f, "%d") || index (f, "%a") || index (f, "%A");
+    fh = index (f, "%H") || index (f, "%I");
+    fmi = index (f, "%M");
+    fs = index (f, "%S");
+    if (! fy && ! fm && ! fd)
+      tvm = localtime (time ());  ## tvm: this very moment
+      y = tvm.year + 1900;
+      m = tvm.mon + 1;
+      d = tvm.mday;
+    elseif (! fy && fm && fd)
+      tvm = localtime (time ());  ## tvm: this very moment
+      y = tvm.year + 1900;
+    elseif (fy && fm && ! fd)
+      tvm = localtime (time ());  ## tvm: this very moment
+      d = 1;
+    endif
+    if (! fh && ! fmi && ! fs)
+      h = mi = s = 0;
+    elseif (fh && fmi && ! fs)
+      s = 0;
+    endif
+  else
+    y = m = d = h = mi = s = 0;
+    found = false;
+  endif
+
+### endfunction
+
+%!shared nowvec
+%! nowvec = datevec (now); # Some tests could fail around midnight!
+# tests for standard formats: 0, 1, 2, 6, 13, 14, 15, 16, 23
+%!assert(datevec("07-Sep-2000 15:38:09"),[2000,9,7,15,38,9]);
+%!assert(datevec("07-Sep-2000"),[2000,9,7,0,0,0]);
+%!assert(datevec("09/07/00"),[2000,9,7,0,0,0]);
+%!assert(datevec("09/13"),[nowvec(1),9,13,0,0,0]);
+%!assert(datevec("15:38:09"),[nowvec(1:3),15,38,9]);
+%!assert(datevec("3:38:09 PM"),[nowvec(1:3),15,38,9]);
+%!assert(datevec("15:38"),[nowvec(1:3),15,38,0]);
+%!assert(datevec("03:38 PM"),[nowvec(1:3),15,38,0]);
+%!assert(datevec("03/13/1962"),[1962,3,13,0,0,0]);
+# other tests
+%!assert(all(datenum(datevec([-1e4:1e4]))==[-1e4:1e4]'))
+%!test
+%! t = linspace (-2e5, 2e5, 10993);
+%! assert (all (datenum (datevec (t)) == t'));
+# demos
+%!demo
+%! datevec (now ())
new file mode 100644
--- /dev/null
+++ b/scripts/time/eomday.m
@@ -0,0 +1,57 @@
+## Copyright (C) 2004 Paul Kienzle
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, write to the Free
+## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {@var{e} =} eomday (@var{y}, @var{m})
+## Return the last day of the month @var{m} for the year @var{y}.
+## @seealso{datenum, datevec, weekday}
+## @end deftypefn
+
+## Author: pkienzle <pkienzle@users.sf.net>
+## Created: 25 July 2004
+## Adapted-By: William Poetra Yoga Hadisoeseno <williampoetra@gmail.com>
+
+function e = eomday (y, m)
+
+  if (nargin != 2)
+    usage ("e = eomday (y, m)");
+  endif
+
+  eom = [31, 28, 31, 30 ,31, 30, 31, 31, 30, 31, 30, 31];
+  e = eom(m);
+  e += (m == 2) & (mod (y, 4) == 0 & (mod (y, 100) != 0 | mod (y, 400) == 0));
+
+endfunction
+
+# tests
+%!assert(eomday([-4:4],2),[29,28,28,28,29,28,28,28,29])
+%!assert(eomday([-901,901],2),[28,28])
+%!assert(eomday([-100,100],2),[28,28])
+%!assert(eomday([-900,900],2),[28,28])
+%!assert(eomday([-400,400],2),[29,29])
+%!assert(eomday([-800,800],2),[29,29])
+%!assert(eomday(2001,1:12),[31,28,31,30,31,30,31,31,30,31,30,31])
+%!assert(eomday(1:3,1:3),[31,28,31])
+%!assert(eomday(1:2000,2)',datevec(datenum(1:2000,3,0))(:,3))
+%!assert([1900:1999](find(eomday(1900:1999,2*ones(1,100))==29)),[1904,1908,1912,1916,1920,1924,1928,1932,1936,1940,1944,1948,1952,1956,1960,1964,1968,1972,1976,1980,1984,1988,1992,1996])
+# demos
+%!demo
+%! y = 1900:1999;
+%! e = eomday (y, 2 * ones (1, 100));
+%! y (find (e == 29))
new file mode 100644
--- /dev/null
+++ b/scripts/time/now.m
@@ -0,0 +1,53 @@
+## Copyright (C) 2000, 2001, 2003, 2005 Paul Kienzle
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, write to the Free
+## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {t =} now ()
+## Returns the current local time as the number of days since Jan 1, 0000.
+## By this reckoning, Jan 1, 1970 is day number 719529.
+##
+## The integral part, @code{floor (now)} corresponds to 00:00:00 today.
+##
+## The fractional part, @code{rem (now, 1)} corresponds to the current
+## time on Jan 1, 0000.
+##
+## The returned value is also called a "serial date number"
+## (see @code{datenum}).
+## @seealso{clock, date, datenum}
+## @end deftypefn
+
+## Author: pkienzle <pkienzle@users.sf.net>
+## Created: 10 October 2001 (CVS)
+## Adapted-By: William Poetra Yoga Hadisoeseno <williampoetra@gmail.com>
+
+function t = now ()
+
+  t = datenum (clock ());
+
+  ## The following doesn't work (e.g., one hour off on 2005-10-04):
+  ##
+  ##   seconds since 1970-1-1 corrected by seconds from GMT to local time
+  ##   divided by 86400 sec/day plus day num for 1970-1-1
+  ##   t = (time - mktime(gmtime(0)))/86400 + 719529;
+  ##
+  ## mktime(gmtime(0)) does indeed return the offset from Greenwich to the
+  ## local time zone, but we need to account for daylight savings time
+  ## changing by an hour the offset from CUT for part of the year.
+
+endfunction
new file mode 100644
--- /dev/null
+++ b/scripts/time/weekday.m
@@ -0,0 +1,72 @@
+## Copyright (C) 2000, 2001, 2004, 2005 Paul Kienzle
+##
+## This file is part of Octave.
+##
+## Octave is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2, or (at your option)
+## any later version.
+##
+## Octave is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with Octave; see the file COPYING.  If not, write to the Free
+## Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+## 02110-1301, USA.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} {[@var{n}, @var{s}] =} weekday (@var{d}, [@var{form}])
+## Return the day of week as a number in @var{n} and a string in @var{s},
+## for example @code{[1, "Sun"]}, @code{[2, "Mon"]}, @dots{}, or
+## @code{[7, "Sat"]}.
+##
+## @var{d} is a serial date number or a date string.
+##
+## If the string @var{form} is given and is @code{"long"}, @var{s} will
+## contain the full name of the weekday; otherwise (or if @var{form} is
+## @code{"short"}), @var{s} will contain the abbreviated name of the weekday.
+## @seealso{datenum, datevec, eomday}
+## @end deftypefn
+
+## Author: pkienzle <pkienzle@users.sf.net>
+## Created: 10 October 2001 (CVS)
+## Adapted-By: William Poetra Yoga Hadisoeseno <williampoetra@gmail.com>
+
+function [n, s] = weekday (d, form)
+
+  if (nargin < 1 || nargin > 2)
+    usage("[n, s] = weekday (d, [form])");
+  endif
+
+  if (nargin < 2)
+    form = "short";
+  endif
+
+  v = datevec (d);
+  t = strptime (sprintf ("%d-%d-%d", v(3), v(2), v(1)), "%d-%m-%Y");
+
+  n = t.wday + 1;
+
+  if (nargout > 1)
+    if (strcmpi (form, "long"))
+      s = strftime ("%A", t);
+    else
+      s = strftime ("%a", t);
+    endif
+  endif
+
+endfunction
+
+# tests
+%!assert(weekday(728647),2)
+%!assert(weekday('19-Dec-1994'),2)
+# demos
+%!demo
+%! [n, s] = weekday (now ())
+%!demo
+%! [n, s] = weekday (728647)
+%!demo
+%! [n, s] = weekday ('19-Dec-1994')