Mercurial > hg > octave-lyh
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]) |