comparison scripts/time/datenum.m @ 13848:40e32fe44aaa

Ugrade time functions to accept millisecond format string FFF (Bug #34586) * datestr.m: Add millisecond FFF format. Change numerical formats 21,22,29 to match Matlab. Remove unused persistent variables. Vectorize some for loops. Use strrep rather than regexp where possible for speed. * datevec.m: Add millisecond FFF format. Use strrep rather than regexp where possible for speed. * datenum.m: Update docstring. Use modern coding style. Only calculate second output argument if requested. Allow cellstr inputs.
author Rik <octave@nomad.inbox5.com>
date Wed, 09 Nov 2011 14:49:09 -0800
parents b80b18f537ca
children d490ca8ab1a5
comparison
equal deleted inserted replaced
13847:9fc597693b0b 13848:40e32fe44aaa
15 ## You should have received a copy of the GNU General Public License 15 ## You should have received a copy of the GNU General Public License
16 ## along with Octave; see the file COPYING. If not, see 16 ## along with Octave; see the file COPYING. If not, see
17 ## <http://www.gnu.org/licenses/>. 17 ## <http://www.gnu.org/licenses/>.
18 18
19 ## -*- texinfo -*- 19 ## -*- texinfo -*-
20 ## @deftypefn {Function File} {} datenum (@var{year}, @var{month}, @var{day}) 20 ## @deftypefn {Function File} {@var{days} =} datenum (@var{datevec})
21 ## @deftypefnx {Function File} {} datenum (@var{year}, @var{month}, @var{day}, @var{hour}) 21 ## @deftypefnx {Function File} {@var{days} =} datenum (@var{year}, @var{month}, @var{day})
22 ## @deftypefnx {Function File} {} datenum (@var{year}, @var{month}, @var{day}, @var{hour}, @var{minute}) 22 ## @deftypefnx {Function File} {@var{days} =} datenum (@var{year}, @var{month}, @var{day}, @var{hour})
23 ## @deftypefnx {Function File} {} datenum (@var{year}, @var{month}, @var{day}, @var{hour}, @var{minute}, @var{second}) 23 ## @deftypefnx {Function File} {@var{days} =} datenum (@var{year}, @var{month}, @var{day}, @var{hour}, @var{minute})
24 ## @deftypefnx {Function File} {} datenum ("date") 24 ## @deftypefnx {Function File} {@var{days} =} datenum (@var{year}, @var{month}, @var{day}, @var{hour}, @var{minute}, @var{second})
25 ## @deftypefnx {Function File} {} datenum ("date", @var{p}) 25 ## @deftypefnx {Function File} {@var{days} =} datenum ("datestr")
26 ## Return the specified local time as a day number, with Jan 1, 0000 26 ## @deftypefnx {Function File} {@var{days} =} datenum ("datestr", @var{p})
27 ## being day 1. By this reckoning, Jan 1, 1970 is day number 719529. 27 ## @deftypefnx {Function File} {[@var{days}, @var{secs}] =} datenum (@dots{})
28 ## The fractional portion, @var{p}, corresponds to the portion of the 28 ## Return the date/time input as a serial day number, with Jan 1, 0000
29 ## specified day. 29 ## being day 1. The fractional portion of @var{days} corresponds to the time
30 ## on the given day. The input may be a date vector (see @code{datevec}),
31 ## datestr (see @code{datestr}), or directly specified as input.
32 ##
33 ## When processing datestrings, @var{p} is the year at the start of the century
34 ## to which two-digit years will be referenced. If not specified, it defaults
35 ## to the current year minus 50.
36 ##
37 ## The optional output @var{secs} holds the time on the specified day with greater
38 ## precision than @var{days}.
30 ## 39 ##
31 ## Notes: 40 ## Notes:
32 ## 41 ##
33 ## @itemize 42 ## @itemize
34 ## @item 43 ## @item
50 ## Days can be fractional. 59 ## Days can be fractional.
51 ## @end itemize 60 ## @end itemize
52 ## 61 ##
53 ## @strong{Caution:} this function does not attempt to handle Julian 62 ## @strong{Caution:} this function does not attempt to handle Julian
54 ## calendars so dates before Octave 15, 1582 are wrong by as much 63 ## calendars so dates before Octave 15, 1582 are wrong by as much
55 ## as eleven days. Also be aware that only Roman Catholic countries 64 ## as eleven days. Also, be aware that only Roman Catholic countries
56 ## adopted the calendar in 1582. It took until 1924 for it to be 65 ## adopted the calendar in 1582. It took until 1924 for it to be
57 ## adopted everywhere. See the Wikipedia entry on the Gregorian 66 ## adopted everywhere. See the Wikipedia entry on the Gregorian
58 ## calendar for more details. 67 ## calendar for more details.
59 ## 68 ##
60 ## @strong{Warning:} leap seconds are ignored. A table of leap seconds 69 ## @strong{Warning:} leap seconds are ignored. A table of leap seconds
61 ## is available on the Wikipedia entry for leap seconds. 70 ## is available on the Wikipedia entry for leap seconds.
62 ## @seealso{date, clock, now, datestr, datevec, calendar, weekday} 71 ## @seealso{datestr, datevec, date, clock, now, calendar, weekday}
63 ## @end deftypefn 72 ## @end deftypefn
64 73
65 ## Algorithm: Peter Baum (http://vsg.cape.com/~pbaum/date/date0.htm) 74 ## Algorithm: Peter Baum (http://vsg.cape.com/~pbaum/date/date0.htm)
66 ## Author: pkienzle <pkienzle@users.sf.net> 75 ## Author: pkienzle <pkienzle@users.sf.net>
67 76
68 function [days, secs] = datenum (year, month, day, hour, minute, second) 77 function [days, secs] = datenum (year, month = [], day = [], hour = 0, minute = 0, second = 0)
69 78
70 ## Days until start of month assuming year starts March 1. 79 ## Days until start of month assuming year starts March 1.
71 persistent monthstart = [306; 337; 0; 31; 61; 92; 122; 153; 184; 214; 245; 275]; 80 persistent monthstart = [306; 337; 0; 31; 61; 92; 122; 153; 184; 214; 245; 275];
72 81
73 if (nargin == 0 || (nargin > 2 && ischar (year)) || nargin > 6) 82 if (nargin == 0 || nargin > 6 ||
83 (nargin > 2 && (ischar (year) || iscellstr (year))))
74 print_usage (); 84 print_usage ();
75 endif 85 endif
76 if (ischar (year)) 86
77 if (nargin < 2) 87 if (ischar (year) || iscellstr (year))
78 month = [];
79 endif
80 [year, month, day, hour, minute, second] = datevec (year, month); 88 [year, month, day, hour, minute, second] = datevec (year, month);
81 else 89 else
82 if (nargin < 6) second = 0; endif
83 if (nargin < 5) minute = 0; endif
84 if (nargin < 4) hour = 0; endif
85 if (nargin == 1) 90 if (nargin == 1)
86 nc = columns (year); 91 nc = columns (year);
87 if (nc > 6 || nc < 3) 92 if (nc > 6 || nc < 3)
88 error ("datenum: expected date vector containing [YEAR, MONTH, DAY, HOUR, MINUTE, SECOND]"); 93 error ("datenum: expected date vector containing [YEAR, MONTH, DAY, HOUR, MINUTE, SECOND]");
89 endif 94 endif
90 second = minute = hour = 0;
91 if (nc >= 6) second = year(:,6); endif 95 if (nc >= 6) second = year(:,6); endif
92 if (nc >= 5) minute = year(:,5); endif 96 if (nc >= 5) minute = year(:,5); endif
93 if (nc >= 4) hour = year(:,4); endif 97 if (nc >= 4) hour = year(:,4); endif
94 day = year(:,3); 98 day = year(:,3);
95 month = year(:,2); 99 month = year(:,2);
96 year = year(:,1); 100 year = year(:,1);
97 endif 101 endif
98 endif 102 endif
99 103
100 month(month<1) = 1; ## For compatibility. Otherwise allow negative months. 104 month(month<1) = 1; ## For compatibility. Otherwise allow negative months.
101 105
118 ## Add number of days to the start of the current year. Correct 122 ## Add number of days to the start of the current year. Correct
119 ## for leap year every 4 years except centuries not divisible by 400. 123 ## for leap year every 4 years except centuries not divisible by 400.
120 day += 365*year + floor (year/4) - floor (year/100) + floor (year/400); 124 day += 365*year + floor (year/4) - floor (year/100) + floor (year/400);
121 125
122 ## Add fraction representing current second of the day. 126 ## Add fraction representing current second of the day.
123 days = day + (hour+(minute+second/60)/60)/24; 127 days = day + (hour + (minute + second/60)/60)/24;
124 128
125 ## Output seconds if asked so that etime can be more accurate 129 ## Output seconds if asked so that etime can be more accurate
126 secs = 86400*day + hour*3600 + minute*60 + second; 130 if (isargout (2))
131 secs = day*86400 + hour*3600 + minute*60 + second;
132 endif
127 133
128 endfunction 134 endfunction
129 135
136
130 %!shared part 137 %!shared part
131 %! part = 0.514623842592593; 138 %! part = 0.514623842592593;
132 %!assert(datenum(2001,5,19), 730990) 139 %!assert (datenum (2001,5,19), 730990)
133 %!assert(datenum([1417,6,12]), 517712) 140 %!assert (datenum ([1417,6,12]), 517712)
134 %!assert(datenum([2001,5,19;1417,6,12]), [730990;517712]) 141 %!assert (datenum ([2001,5,19;1417,6,12]), [730990;517712])
135 %!assert(datenum(2001,5,19,12,21,3.5), 730990+part, eps) 142 %!assert (datenum (2001,5,19,12,21,3.5), 730990+part, eps)
136 %!assert(datenum([1417,6,12,12,21,3.5]), 517712+part, eps) 143 %!assert (datenum ([1417,6,12,12,21,3.5]), 517712+part, eps)
137 ## Test vector inputs 144 ## Test vector inputs
138 %!test 145 %!test
139 %! t = [2001,5,19,12,21,3.5; 1417,6,12,12,21,3.5]; 146 %! t = [2001,5,19,12,21,3.5; 1417,6,12,12,21,3.5];
140 %! n = [730990; 517712] + part; 147 %! n = [730990; 517712] + part;
141 %! assert(datenum(t), n, 2*eps); 148 %! assert (datenum (t), n, 2*eps);
142 ## Make sure that the vectors can have either orientation 149 %! ## Check that vectors can have either orientation
143 %!test 150 %! t = t';
144 %! t = [2001,5,19,12,21,3.5; 1417,6,12,12,21,3.5]'; 151 %! n = n';
145 %! n = [730990 517712] + part; 152 %! assert (datenum (t(1,:), t(2,:), t(3,:), t(4,:), t(5,:), t(6,:)), n, 2*eps);
146 %! assert(datenum(t(1,:), t(2,:), t(3,:), t(4,:), t(5,:), t(6,:)), n, 2*eps);
147 153
148 ## Test mixed vectors and scalars 154 ## Test mixed vectors and scalars
149 %!assert (datenum([2008;2009], 1, 1), [datenum(2008, 1, 1);datenum(2009, 1, 1)]); 155 %!assert (datenum([2008;2009], 1, 1), [datenum(2008, 1, 1);datenum(2009, 1, 1)]);
150 %!assert (datenum(2008, [1;2], 1), [datenum(2008, 1, 1);datenum(2008, 2, 1)]); 156 %!assert (datenum(2008, [1;2], 1), [datenum(2008, 1, 1);datenum(2008, 2, 1)]);
151 %!assert (datenum(2008, 1, [1;2]), [datenum(2008, 1, 1);datenum(2008, 1, 2)]); 157 %!assert (datenum(2008, 1, [1;2]), [datenum(2008, 1, 1);datenum(2008, 1, 2)]);
157 %!assert (datenum(2008, [1 2], 1), [datenum(2008, 1, 1) datenum(2008, 2, 1)]); 163 %!assert (datenum(2008, [1 2], 1), [datenum(2008, 1, 1) datenum(2008, 2, 1)]);
158 %!assert (datenum(2008, 1, [1 2]), [datenum(2008, 1, 1) datenum(2008, 1, 2)]); 164 %!assert (datenum(2008, 1, [1 2]), [datenum(2008, 1, 1) datenum(2008, 1, 2)]);
159 %!assert (datenum([2008 2009], [1 2], 1), [datenum(2008, 1, 1) datenum(2009, 2, 1)]); 165 %!assert (datenum([2008 2009], [1 2], 1), [datenum(2008, 1, 1) datenum(2009, 2, 1)]);
160 %!assert (datenum([2008 2009], 1, [1 2]), [datenum(2008, 1, 1) datenum(2009, 1, 2)]); 166 %!assert (datenum([2008 2009], 1, [1 2]), [datenum(2008, 1, 1) datenum(2009, 1, 2)]);
161 %!assert (datenum(2008, [1 2], [1 2]), [datenum(2008, 1, 1) datenum(2008, 2, 2)]); 167 %!assert (datenum(2008, [1 2], [1 2]), [datenum(2008, 1, 1) datenum(2008, 2, 2)]);
168 ## Test string and cellstr inputs
169 %!assert (datenum ("5/19/2001"), 730990)
170 %!assert (datenum ({"5/19/2001"}), 730990)
171 %!assert (datenum (char ("5/19/2001", "6/6/1944")), [730990; 710189])
172 %!assert (datenum ({"5/19/2001", "6/6/1944"}), [730990; 710189])
173
174 %% Test input validation
175 %!error datenum ()
176 %!error datenum (1,2,3,4,5,6,7)
177 %!error datenum ([1, 2])
178 %!error datenum ([1,2,3,4,5,6,7])