GNU Octave  8.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
time.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1996-2023 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING. If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if defined (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #include <string>
31 
32 #include "defun.h"
33 #include "error.h"
34 #include "oct-map.h"
35 #include "oct-time.h"
36 #include "ov.h"
37 #include "ovl.h"
38 
40 
41 // Date and time functions.
42 
43 static octave_scalar_map
44 mk_tm_map (const sys::base_tm& t)
45 {
47 
48  m.assign ("usec", static_cast<double> (t.usec ()));
49  m.assign ("sec", static_cast<double> (t.sec ()));
50  m.assign ("min", static_cast<double> (t.min ()));
51  m.assign ("hour", static_cast<double> (t.hour ()));
52  m.assign ("mday", static_cast<double> (t.mday ()));
53  m.assign ("mon", static_cast<double> (t.mon ()));
54  m.assign ("year", static_cast<double> (t.year ()));
55  m.assign ("wday", static_cast<double> (t.wday ()));
56  m.assign ("yday", static_cast<double> (t.yday ()));
57  m.assign ("isdst", static_cast<double> (t.isdst ()));
58  m.assign ("gmtoff", static_cast<double> (t.gmtoff ()));
59  m.assign ("zone", t.zone ());
60 
61  return m;
62 }
63 
64 static inline int
65 intfield (const octave_scalar_map& m, const std::string& k, const char *who)
66 {
67  int retval = 0;
68 
69  octave_value v = m.getfield (k);
70 
71  if (! v.isempty ())
72  retval = v.xint_value ("%s: invalid TM_STRUCT argument", who);
73 
74  return retval;
75 }
76 
77 static inline std::string
78 stringfield (const octave_scalar_map& m, const std::string& k, const char *who)
79 {
80  std::string retval;
81 
82  octave_value v = m.getfield (k);
83 
84  if (! v.isempty ())
85  retval = v.xstring_value ("%s: invalid TM_STRUCT argument", who);
86 
87  return retval;
88 }
89 
90 static sys::base_tm
91 extract_tm (const octave_scalar_map& m, const char *who)
92 {
93  sys::base_tm tm;
94 
95  tm.usec (intfield (m, "usec", who));
96  tm.sec (intfield (m, "sec", who));
97  tm.min (intfield (m, "min", who));
98  tm.hour (intfield (m, "hour", who));
99  tm.mday (intfield (m, "mday", who));
100  tm.mon (intfield (m, "mon", who));
101  tm.year (intfield (m, "year", who));
102  tm.wday (intfield (m, "wday", who));
103  tm.yday (intfield (m, "yday", who));
104  tm.isdst (intfield (m, "isdst", who));
105  tm.gmtoff (intfield (m, "gmtoff", who));
106  tm.zone (stringfield (m, "zone", who));
107 
108  return tm;
109 }
110 
111 DEFUN (time, args, ,
112  doc: /* -*- texinfo -*-
113 @deftypefn {} {@var{seconds} =} time ()
114 Return the current time as the number of seconds since the epoch.
115 
116 The epoch is referenced to 00:00:00 UTC (Coordinated Universal Time) 1 Jan
117 1970. For example, on Monday February 17, 1997 at 07:15:06 UTC, the value
118 returned by @code{time} was 856163706.
119 @seealso{strftime, strptime, localtime, gmtime, mktime, now, date, clock,
120 datenum, datestr, datevec, calendar, weekday}
121 @end deftypefn */)
122 {
123  if (args.length () != 0)
124  print_usage ();
125 
126  return ovl (sys::time ());
127 }
128 
129 /*
130 %!assert (time () > 0)
131 
132 %!error time (1)
133 */
134 
135 DEFUN (gmtime, args, ,
136  doc: /* -*- texinfo -*-
137 @deftypefn {} {@var{tm_struct} =} gmtime (@var{t})
138 Given a value returned from @code{time}, or any non-negative integer,
139 return a time structure corresponding to UTC (Coordinated Universal Time).
140 
141 For example:
142 
143 @example
144 @group
145 gmtime (time ())
146  @result{} @{
147  usec = 0
148  sec = 6
149  min = 15
150  hour = 7
151  mday = 17
152  mon = 1
153  year = 97
154  wday = 1
155  yday = 47
156  isdst = 0
157  gmtoff = 0
158  zone = GMT
159  @}
160 @end group
161 @end example
162 @seealso{strftime, strptime, localtime, mktime, time, now, date, clock, datenum,
163 datestr, datevec, calendar, weekday}
164 @end deftypefn */)
165 {
166  if (args.length () != 1 || args(0).numel () != 1)
167  print_usage ();
168 
169  double tmp = args(0).double_value ();
170 
171  return ovl (mk_tm_map (sys::gmtime (tmp)));
172 }
173 
174 /*
175 %!test
176 %! ts = gmtime (time ());
177 %! assert (isstruct (ts));
178 %! assert (isfield (ts, "usec"));
179 %! assert (isfield (ts, "year"));
180 %! assert (isfield (ts, "mon"));
181 %! assert (isfield (ts, "mday"));
182 %! assert (isfield (ts, "sec"));
183 %! assert (isfield (ts, "min"));
184 %! assert (isfield (ts, "wday"));
185 %! assert (isfield (ts, "hour"));
186 %! assert (isfield (ts, "isdst"));
187 %! assert (isfield (ts, "yday"));
188 
189 %!error gmtime ()
190 %!error gmtime (1, 2)
191 */
192 
193 DEFUN (localtime, args, ,
194  doc: /* -*- texinfo -*-
195 @deftypefn {} {@var{tm_struct} =} localtime (@var{t})
196 Given a value returned from @code{time}, or any non-negative integer,
197 return a time structure corresponding to the local time zone.
198 
199 @example
200 @group
201 localtime (time ())
202  @result{} @{
203  usec = 0
204  sec = 6
205  min = 15
206  hour = 1
207  mday = 17
208  mon = 1
209  year = 97
210  wday = 1
211  yday = 47
212  isdst = 0
213  gmtoff = -21600
214  zone = CST
215  @}
216 @end group
217 @end example
218 @seealso{strftime, strptime, gmtime, mktime, time, now, date, clock, datenum,
219 datestr, datevec, calendar, weekday}
220 @end deftypefn */)
221 {
222  if (args.length () != 1 || args(0).numel () != 1)
223  print_usage ();
224 
225  double tmp = args(0).double_value ();
226 
227  return ovl (mk_tm_map (sys::localtime (tmp)));
228 }
229 
230 /*
231 %!test
232 %! ts = localtime (time ());
233 %! assert (isstruct (ts));
234 %! assert (isfield (ts, "usec"));
235 %! assert (isfield (ts, "year"));
236 %! assert (isfield (ts, "mon"));
237 %! assert (isfield (ts, "mday"));
238 %! assert (isfield (ts, "sec"));
239 %! assert (isfield (ts, "min"));
240 %! assert (isfield (ts, "wday"));
241 %! assert (isfield (ts, "hour"));
242 %! assert (isfield (ts, "isdst"));
243 %! assert (isfield (ts, "yday"));
244 
245 %!error localtime ()
246 %!error localtime (1, 2)
247 */
248 
249 DEFUN (mktime, args, ,
250  doc: /* -*- texinfo -*-
251 @deftypefn {} {@var{seconds} =} mktime (@var{tm_struct})
252 Convert a time structure corresponding to the local time to the number of
253 seconds since the epoch.
254 
255 For example:
256 
257 @example
258 @group
259 mktime (localtime (time ()))
260  @result{} 856163706
261 @end group
262 @end example
263 @seealso{strftime, strptime, localtime, gmtime, time, now, date, clock, datenum,
264 datestr, datevec, calendar, weekday}
265 @end deftypefn */)
266 {
267  if (args.length () != 1)
268  print_usage ();
269 
270  octave_scalar_map map = args(
271  0).xscalar_map_value ("mktime: TM_STRUCT argument must be a structure");
272 
273  sys::base_tm tm = extract_tm (map, "mktime");
274 
275  return ovl (sys::time (tm));
276 }
277 
278 /*
279 %!test
280 %! t = time ();
281 %! assert (fix (mktime (localtime (t))) == fix (t));
282 
283 ## These tests fail on systems with mktime functions of limited
284 ## intelligence:
285 %!assert (datestr (datenum (1969, 1, 1), 0), "01-Jan-1969 00:00:00")
286 %!assert (datestr (datenum (1901, 1, 1), 0), "01-Jan-1901 00:00:00")
287 %!assert (datestr (datenum (1795, 1, 1), 0), "01-Jan-1795 00:00:00")
288 
289 %!error mktime ()
290 %!error mktime (1)
291 %!error mktime (1, 2, 3)
292 %!error mktime (struct ("year", "foo"))
293 */
294 
295 DEFUN (strftime, args, ,
296  doc: /* -*- texinfo -*-
297 @deftypefn {} {@var{str} =} strftime (@var{fmt}, @var{tm_struct})
298 Format the time structure @var{tm_struct} in a flexible way using the format
299 string @var{fmt} that contains @samp{%} substitutions similar to those in
300 @code{printf}.
301 
302 Except where noted, substituted fields have a fixed size; numeric fields are
303 padded if necessary. Padding is with zeros by default; for fields that
304 display a single number, padding can be changed or inhibited by following
305 the @samp{%} with one of the modifiers described below. Unknown field
306 specifiers are copied as normal characters. All other characters are copied
307 to the output without change. For example:
308 
309 @example
310 @group
311 strftime ("%r (%Z) %A %e %B %Y", localtime (time ()))
312  @result{} "01:15:06 AM (CST) Monday 17 February 1997"
313 @end group
314 @end example
315 
316 Octave's @code{strftime} function supports a superset of the ANSI C field
317 specifiers.
318 
319 @noindent
320 Literal character fields:
321 
322 @table @code
323 @item %%
324 % character.
325 
326 @item %n
327 Newline character.
328 
329 @item %t
330 Tab character.
331 @end table
332 
333 @noindent
334 Numeric modifiers (a nonstandard extension):
335 
336 @table @code
337 @item - (dash)
338 Do not pad the field.
339 
340 @item _ (underscore)
341 Pad the field with spaces.
342 @end table
343 
344 @noindent
345 Time fields:
346 
347 @table @code
348 @item %H
349 Hour (00-23).
350 
351 @item %I
352 Hour (01-12).
353 
354 @item %k
355 Hour (0-23).
356 
357 @item %l
358 Hour (1-12).
359 
360 @item %M
361 Minute (00-59).
362 
363 @item %p
364 Locale's AM or PM.
365 
366 @item %r
367 Time, 12-hour (hh:mm:ss [AP]M).
368 
369 @item %R
370 Time, 24-hour (hh:mm).
371 
372 @item %s
373 Time in seconds since 00:00:00, Jan 1, 1970 (a nonstandard extension).
374 
375 @item %S
376 Second (00-61).
377 
378 @item %T
379 Time, 24-hour (hh:mm:ss).
380 
381 @item %X
382 Locale's time representation (%H:%M:%S).
383 
384 @item %z
385 Offset from UTC (±@nospell{hhmm}), or nothing if no time zone is
386 determinable.
387 
388 @item %Z
389 Time zone (EDT), or nothing if no time zone is determinable.
390 @end table
391 
392 @noindent
393 Date fields:
394 
395 @table @code
396 @item %a
397 Locale's abbreviated weekday name (Sun-Sat).
398 
399 @item %A
400 Locale's full weekday name, variable length (Sunday-Saturday).
401 
402 @item %b
403 Locale's abbreviated month name (Jan-Dec).
404 
405 @item %B
406 Locale's full month name, variable length (January-December).
407 
408 @item %c
409 Locale's date and time (Sat Nov 04 12:02:33 EST 1989).
410 
411 @item %C
412 Century (00-99).
413 
414 @item %d
415 Day of month (01-31).
416 
417 @item %e
418 Day of month ( 1-31).
419 
420 @item %D
421 Date (mm/dd/yy).
422 
423 @item %h
424 Same as %b.
425 
426 @item %j
427 Day of year (001-366).
428 
429 @item %m
430 Month (01-12).
431 
432 @item %U
433 Week number of year with Sunday as first day of week (00-53).
434 
435 @item %w
436 Day of week (0-6).
437 
438 @item %W
439 Week number of year with Monday as first day of week (00-53).
440 
441 @item %x
442 Locale's date representation (mm/dd/yy).
443 
444 @item %y
445 Last two digits of year (00-99).
446 
447 @item %Y
448 Year (1970-).
449 @end table
450 @seealso{strptime, localtime, gmtime, mktime, time, now, date, clock, datenum,
451 datestr, datevec, calendar, weekday}
452 @end deftypefn */)
453 {
454  if (args.length () != 2)
455  print_usage ();
456 
457  std::string fmt = args(0).xstring_value ("strftime: FMT must be a string");
458 
459  octave_scalar_map map = args(1).xscalar_map_value ("strftime: TM_STRUCT must be a structure");
460 
461  sys::base_tm tm = extract_tm (map, "strftime");
462 
463  return ovl (tm.strftime (fmt));
464 }
465 
466 /*
467 %!assert (ischar (strftime ("%%%n%t%H%I%k%l", localtime (time ()))))
468 %!assert (ischar (strftime ("%M%p%r%R%s%S%T", localtime (time ()))))
469 %!assert (ischar (strftime ("%X%Z%z%a%A%b%B", localtime (time ()))))
470 %!assert (ischar (strftime ("%c%C%d%e%D%h%j", localtime (time ()))))
471 %!assert (ischar (strftime ("%m%U%w%W%x%y%Y", localtime (time ()))))
472 
473 %!error strftime ()
474 %!error strftime ("foo", 1)
475 %!error strftime ("foo", struct ("year", "foo"))
476 %!error strftime ("foo", localtime (time ()), 1)
477 */
478 
479 DEFUN (strptime, args, ,
480  doc: /* -*- texinfo -*-
481 @deftypefn {} {[@var{tm_struct}, @var{nchars}] =} strptime (@var{str}, @var{fmt})
482 Convert the string @var{str} to the time structure @var{tm_struct} under
483 the control of the format string @var{fmt}.
484 
485 If @var{fmt} fails to match, @var{nchars} is 0; otherwise, it is set to the
486 position of last matched character plus 1. Always check for this unless
487 you're absolutely sure the date string will be parsed correctly.
488 @seealso{strftime, localtime, gmtime, mktime, time, now, date, clock, datenum,
489 datestr, datevec, calendar, weekday}
490 @end deftypefn */)
491 {
492  if (args.length () != 2)
493  print_usage ();
494 
495  std::string str = args(0).xstring_value ("strptime: argument STR must be a string");
496 
497  std::string fmt = args(1).xstring_value ("strptime: FMT must be a string");
498 
499  sys::strptime t (str, fmt);
500 
501  return ovl (mk_tm_map (t), t.characters_converted ());
502 }
503 
504 /*
505 %!test
506 %! fmt = "%Y-%m-%d %H:%M:%S";
507 %! s = strftime (fmt, localtime (time ()));
508 %! ts = strptime (s, fmt);
509 %! assert (isstruct (ts));
510 %! assert (isfield (ts, "usec"));
511 %! assert (isfield (ts, "year"));
512 %! assert (isfield (ts, "mon"));
513 %! assert (isfield (ts, "mday"));
514 %! assert (isfield (ts, "sec"));
515 %! assert (isfield (ts, "min"));
516 %! assert (isfield (ts, "wday"));
517 %! assert (isfield (ts, "hour"));
518 %! assert (isfield (ts, "isdst"));
519 %! assert (isfield (ts, "yday"));
520 
521 %!error strptime ()
522 */
523 
OCTAVE_END_NAMESPACE(octave)
OCTINTERP_API std::string xstring_value(const char *fmt,...) const
OCTINTERP_API int xint_value(const char *fmt,...) const
bool isempty(void) const
Definition: ov.h:646
Definition: oct-time.h:52
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
OCTINTERP_API void print_usage(void)
Definition: defun-int.h:72
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
Definition: defun.h:56
T octave_idx_type m
Definition: mx-inlines.cc:773
T::size_type numel(const T &str)
Definition: oct-string.cc:71
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
Definition: ovl.h:211
static std::string stringfield(const octave_scalar_map &m, const std::string &k, const char *who)
Definition: time.cc:78
static int intfield(const octave_scalar_map &m, const std::string &k, const char *who)
Definition: time.cc:65
static octave_scalar_map mk_tm_map(const sys::base_tm &t)
Definition: time.cc:44
static sys::base_tm extract_tm(const octave_scalar_map &m, const char *who)
Definition: time.cc:91