GNU Octave  9.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
oct-time.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 1999-2024 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 <cmath>
31 #include <ctime>
32 
33 #include <iomanip>
34 #include <limits>
35 #include <ostream>
36 
37 #if defined (OCTAVE_USE_WINDOWS_API)
38 # include <windows.h>
39 #else
40 # include "file-stat.h"
41 #endif
42 
43 #include "lo-error.h"
44 #include "lo-utils.h"
45 #include "lo-sysdep.h"
46 #include "oct-locbuf.h"
47 #include "oct-time.h"
49 #include "strftime-wrapper.h"
50 #include "strptime-wrapper.h"
51 #include "time-wrappers.h"
52 
54 
56 
57 time::time (double d)
58  : m_ot_unix_time (static_cast<OCTAVE_TIME_T> (d)), m_ot_usec (0)
59 {
60  double ip;
61  m_ot_usec = static_cast<int> (std::modf (d, &ip) * 1e6);
62 }
63 
64 time::time (const base_tm& tm)
65  : m_ot_unix_time (), m_ot_usec ()
66 {
67  struct ::tm t;
68 
69  t.tm_sec = tm.sec ();
70  t.tm_min = tm.min ();
71  t.tm_hour = tm.hour ();
72  t.tm_mday = tm.mday ();
73  t.tm_mon = tm.mon ();
74  t.tm_year = tm.year ();
75  t.tm_wday = tm.wday ();
76  t.tm_yday = tm.yday ();
77  t.tm_isdst = tm.isdst ();
78 
79 #if defined (HAVE_TM_GMTOFF)
80  t.tm_gmtoff = tm.gmtoff ();
81 #endif
82 
83 #if defined (HAVE_STRUCT_TM_TM_ZONE)
84  std::string s = tm.zone ();
85  char *ps = strsave (s.c_str ());
86  t.tm_zone = ps;
87 #endif
88 
89  m_ot_unix_time = octave_mktime_wrapper (&t);
90 
91 #if defined (HAVE_STRUCT_TM_TM_ZONE)
92  delete [] ps;
93 #endif
94 
95  m_ot_usec = tm.usec ();
96 }
97 
98 std::string
99 time::ctime () const
100 {
101  return localtime (*this).asctime ();
102 }
103 
104 std::ostream&
105 operator << (std::ostream& os, const time& ot)
106 {
107  preserve_stream_state stream_state (os);
108 
109  os << ot.m_ot_unix_time << '.'
110  << std::setw (6) << std::setfill ('0') << ot.m_ot_usec;
111 
112  return os;
113 }
114 
115 void
117 {
118  time_t ot_unix_time;
119  octave_gettimeofday_wrapper (&ot_unix_time, &m_ot_usec);
120  m_ot_unix_time = ot_unix_time;
121 }
122 
123 // From the mktime() manual page:
124 //
125 // The mktime() function converts a broken-down time structure,
126 // expressed as local time, to calendar time representation.
127 //
128 // <snip>
129 //
130 // If structure members are outside their legal interval, they
131 // will be normalized (so that, e.g., 40 October is changed into
132 // 9 November).
133 //
134 // So, we no longer check limits here.
135 
136 #define DEFINE_SET_FIELD_FCN(type, f, lo, hi) \
137  base_tm& \
138  base_tm::f (type v) \
139  { \
140  m_ ## f = v; \
141  \
142  return *this; \
143  }
144 
145 #define DEFINE_SET_INT_FIELD_FCN(f, lo, hi) \
146  DEFINE_SET_FIELD_FCN (int, f, lo, hi)
147 
148 DEFINE_SET_INT_FIELD_FCN (usec, 0, 1000000)
154 DEFINE_SET_INT_FIELD_FCN (year, std::numeric_limits<int>::min (),
155  std::numeric_limitd<int>::max ())
159 DEFINE_SET_FIELD_FCN (long, gmtoff, -86400, 0)
160 
161 base_tm&
162 base_tm::zone (const std::string& s)
163 {
164  m_zone = s;
165  return *this;
166 }
167 
168 #if ! defined STRFTIME_BUF_INITIAL_SIZE
169 # define STRFTIME_BUF_INITIAL_SIZE 128
170 #endif
171 
172 std::string
173 base_tm::strftime (const std::string& fmt) const
174 {
175  std::string retval;
176 
177  if (! fmt.empty ())
178  {
179  struct ::tm t;
180 
181  t.tm_sec = m_sec;
182  t.tm_min = m_min;
183  t.tm_hour = m_hour;
184  t.tm_mday = m_mday;
185  t.tm_mon = m_mon;
186  t.tm_year = m_year;
187  t.tm_wday = m_wday;
188  t.tm_yday = m_yday;
189  t.tm_isdst = m_isdst;
190 
191 #if defined (HAVE_TM_GMTOFF)
192  t.tm_gmtoff = m_gmtoff;
193 #endif
194 
195 #if defined (HAVE_STRUCT_TM_TM_ZONE)
196  char *ps = strsave (m_zone.c_str ());
197  t.tm_zone = ps;
198 #endif
199 
200  const char *fmt_str = fmt.c_str ();
201 
202  char *buf = nullptr;
203  std::size_t bufsize = STRFTIME_BUF_INITIAL_SIZE;
204  std::size_t chars_written = 0;
205 
206  while (chars_written == 0)
207  {
208  delete [] buf;
209  buf = new char [bufsize];
210  buf[0] = '\0';
211 
212  chars_written
213  = octave_strftime_wrapper (buf, bufsize, fmt_str, &t);
214 
215  bufsize *= 2;
216  }
217 
218 #if defined (HAVE_STRUCT_TM_TM_ZONE)
219  delete [] ps;
220 #endif
221 
222  retval = buf;
223 
224  delete [] buf;
225  }
226 
227  return retval;
228 }
229 
230 void
231 base_tm::init (void *p)
232 {
233  if (! p)
234  return;
235 
236  struct ::tm *t = static_cast<struct ::tm *> (p);
237 
238  m_sec = t->tm_sec;
239  m_min = t->tm_min;
240  m_hour = t->tm_hour;
241  m_mday = t->tm_mday;
242  m_mon = t->tm_mon;
243  m_year = t->tm_year;
244  m_wday = t->tm_wday;
245  m_yday = t->tm_yday;
246  m_isdst = t->tm_isdst;
247 
248 #if defined (HAVE_TM_GMTOFF)
249  m_gmtoff = t->tm_gmtoff;
250 #elif defined (OCTAVE_USE_WINDOWS_API)
251  TIME_ZONE_INFORMATION tzi;
252 
253  GetTimeZoneInformationForYear (m_year, nullptr, &tzi);
254 
255  if (m_isdst)
256  m_gmtoff = -60 * (tzi.Bias + tzi.DaylightBias);
257  else
258  m_gmtoff = -60 * (tzi.Bias + tzi.StandardBias);
259 #endif
260 
261 #if defined (HAVE_STRUCT_TM_TM_ZONE)
262  if (t->tm_zone)
263  m_zone = t->tm_zone;
264 #elif defined (OCTAVE_USE_WINDOWS_API)
265  if (m_isdst)
266  m_zone = sys::u8_from_wstring (tzi.DaylightName);
267  else
268  m_zone = sys::u8_from_wstring (tzi.StandardName);
269 #elif defined (HAVE_TZNAME)
270  if (t->tm_isdst == 0 || t->tm_isdst == 1)
271  m_zone = tzname[t->tm_isdst];
272 #endif
273 }
274 
275 void
276 localtime::init (const time& ot)
277 {
278  m_usec = ot.usec ();
279 
280  time_t t = ot.unix_time ();
281 
282  base_tm::init (std::localtime (&t));
283 }
284 
285 void
286 gmtime::init (const time& ot)
287 {
288  m_usec = ot.usec ();
289 
290  time_t t = ot.unix_time ();
291 
292  base_tm::init (std::gmtime (&t));
293 }
294 
295 void
296 strptime::init (const std::string& str, const std::string& fmt)
297 {
298  struct ::tm t;
299 
300  t.tm_sec = 0;
301  t.tm_min = 0;
302  t.tm_hour = 0;
303  t.tm_mday = 0;
304  t.tm_mon = -1;
305  t.tm_year = std::numeric_limits<int>::min ();
306  t.tm_wday = 0;
307  t.tm_yday = 0;
308  t.tm_isdst = 0;
309 
310 #if defined (HAVE_TM_GMTOFF)
311  t.tm_gmtoff = 0;
312 #endif
313 
314 #if defined (HAVE_STRUCT_TM_TM_ZONE)
315  char *ps = strsave ("");
316  t.tm_zone = ps;
317 #endif
318 
319  const char *p = str.c_str ();
320 
321  char *q = octave_strptime_wrapper (p, fmt.c_str (), &t);
322 
323  // Fill in wday and yday, but only if mday is valid and the mon and year
324  // are filled in, avoiding issues with mktime and invalid dates.
325  if (t.tm_mday != 0 && t.tm_mon >= 0
326  && t.tm_year != std::numeric_limits<int>::min ())
327  {
328  t.tm_isdst = -1;
330  }
331 
332  if (t.tm_mon < 0)
333  t.tm_mon = 0;
334 
335  if (t.tm_year == std::numeric_limits<int>::min ())
336  t.tm_year = 0;
337 
338  if (q)
339  m_nchars = q - p + 1;
340  else
341  m_nchars = 0;
342 
343  base_tm::init (&t);
344 
345 #if defined (HAVE_STRUCT_TM_TM_ZONE)
346  delete [] ps;
347 #endif
348 }
349 
350 void
352 {
353  time_t usr_sec, sys_sec;
354  octave_cpu_time (&usr_sec, &sys_sec, &m_usr_usec, &m_sys_usec);
355  m_usr_sec = usr_sec;
356  m_sys_sec = sys_sec;
357 }
358 
359 void
361 {
362  time_t usr_sec, sys_sec;
363  long usr_usec, sys_usec;
364 
365  octave_getrusage_wrapper (&usr_sec, &sys_sec, &usr_usec,
366  &sys_usec, &m_maxrss, &m_ixrss,
367  &m_idrss, &m_isrss, &m_minflt,
368  &m_majflt, &m_nswap, &m_inblock,
369  &m_oublock, &m_msgsnd, &m_msgrcv,
370  &m_nsignals, &m_nvcsw, &m_nivcsw);
371 
372  m_cpu = cpu_time (usr_sec, sys_sec, usr_usec, sys_usec);
373 }
374 
376 {
377 #if defined (OCTAVE_USE_WINDOWS_API)
378  FILETIME curr_file_time;
379  GetSystemTimeAsFileTime (&curr_file_time);
380  m_time
381  = (static_cast<OCTAVE_TIME_T> (curr_file_time.dwHighDateTime)) >> 32
382  | curr_file_time.dwLowDateTime;
383 #else
384  time_t ot_unix_time;
385  long ot_usec;
386  octave_gettimeofday_wrapper (&ot_unix_time, &ot_usec);
387  // Discard usec. We are assuming a 1 second resolution anyway.
388  m_time = ot_unix_time;
389 #endif
390 }
391 
392 file_time::file_time (const std::string& filename)
393 {
394 #if defined (OCTAVE_USE_WINDOWS_API)
395  std::wstring wfull_name = sys::u8_to_wstring (filename);
396  WIN32_FILE_ATTRIBUTE_DATA file_attributes;
397 
398  if (! GetFileAttributesExW (wfull_name.c_str (), GetFileExInfoStandard,
399  &file_attributes))
400  {
401  m_time = 0;
402  return;
403  }
404 
405  FILETIME last_write_time = file_attributes.ftLastWriteTime;
406 
407  m_time
408  = (static_cast<OCTAVE_TIME_T> (last_write_time.dwHighDateTime)) >> 32
409  | last_write_time.dwLowDateTime;
410 #else
411  file_stat fs = file_stat (filename);
412  m_time = fs.mtime ().unix_time ();
413 #endif
414 }
415 
416 OCTAVE_END_NAMESPACE(sys)
417 OCTAVE_END_NAMESPACE(octave)
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:230
charNDArray min(char d, const charNDArray &m)
Definition: chNDArray.cc:207
sys::time mtime() const
Definition: file-stat.h:131
int mday() const
Definition: oct-time.h:241
int yday() const
Definition: oct-time.h:245
int m_sec
Definition: oct-time.h:274
int m_isdst
Definition: oct-time.h:298
int m_year
Definition: oct-time.h:289
int hour() const
Definition: oct-time.h:240
int m_usec
Definition: oct-time.h:271
int m_mday
Definition: oct-time.h:283
int wday() const
Definition: oct-time.h:244
int m_min
Definition: oct-time.h:277
std::string m_zone
Definition: oct-time.h:304
int mon() const
Definition: oct-time.h:242
void init(void *p)
Definition: oct-time.cc:231
int min() const
Definition: oct-time.h:239
std::string asctime() const
Definition: oct-time.h:265
long m_gmtoff
Definition: oct-time.h:301
int isdst() const
Definition: oct-time.h:246
int m_hour
Definition: oct-time.h:280
int sec() const
Definition: oct-time.h:238
long gmtoff() const
Definition: oct-time.h:247
std::string zone() const
Definition: oct-time.h:248
int usec() const
Definition: oct-time.h:237
int m_wday
Definition: oct-time.h:292
int year() const
Definition: oct-time.h:243
std::string strftime(const std::string &fmt) const
Definition: oct-time.cc:173
int m_yday
Definition: oct-time.h:295
int m_mon
Definition: oct-time.h:286
void stamp()
Definition: oct-time.cc:351
void stamp()
Definition: oct-time.cc:360
Definition: oct-time.h:64
time()
Definition: oct-time.h:67
void stamp()
Definition: oct-time.cc:116
std::string ctime() const
Definition: oct-time.cc:99
long usec() const
Definition: oct-time.h:124
OCTAVE_TIME_T unix_time() const
Definition: oct-time.h:122
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE * d
std::string u8_from_wstring(const std::wstring &wchar_string)
Definition: lo-sysdep.cc:746
std::wstring u8_to_wstring(const std::string &utf8_string)
Definition: lo-sysdep.cc:723
char * strsave(const char *s)
Definition: lo-utils.cc:78
#define DEFINE_SET_INT_FIELD_FCN(f, lo, hi)
Definition: oct-time.cc:145
#define STRFTIME_BUF_INITIAL_SIZE
Definition: oct-time.cc:169
std::ostream & operator<<(std::ostream &os, const time &ot)
Definition: oct-time.cc:105
#define DEFINE_SET_FIELD_FCN(type, f, lo, hi)
Definition: oct-time.cc:136
size_t octave_strftime_wrapper(char *buf, size_t len, const char *fmt, const struct tm *t)
char * octave_strptime_wrapper(const char *p, const char *fmt, struct tm *t)
int octave_cpu_time(time_t *usr_sec, time_t *sys_sec, long *usr_usec, long *sys_usec)
Definition: time-wrappers.c:63
int octave_gettimeofday_wrapper(time_t *sec, long *usec)
Definition: time-wrappers.c:42
time_t octave_mktime_wrapper(struct tm *tp)
int octave_getrusage_wrapper(time_t *usr_sec, time_t *sys_sec, long *usr_usec, long *sys_usec, long *maxrss, long *ixrss, long *idrss, long *isrss, long *minflt, long *majflt, long *nswap, long *inblock, long *oublock, long *msgsnd, long *msgrcv, long *nsignals, long *nvcsw, long *nivcsw)
Definition: time-wrappers.c:91