3253
|
1 /* |
|
2 |
7017
|
3 Copyright (C) 1999, 2000, 2002, 2005, 2006, 2007 John W. Eaton |
3253
|
4 |
|
5 This file is part of Octave. |
|
6 |
|
7 Octave is free software; you can redistribute it and/or modify it |
|
8 under the terms of the GNU General Public License as published by the |
7016
|
9 Free Software Foundation; either version 3 of the License, or (at your |
|
10 option) any later version. |
3253
|
11 |
|
12 Octave is distributed in the hope that it will be useful, but WITHOUT |
|
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
15 for more details. |
|
16 |
|
17 You should have received a copy of the GNU General Public License |
7016
|
18 along with Octave; see the file COPYING. If not, see |
|
19 <http://www.gnu.org/licenses/>. |
3253
|
20 |
|
21 */ |
|
22 |
|
23 #ifdef HAVE_CONFIG_H |
|
24 #include <config.h> |
|
25 #endif |
|
26 |
3290
|
27 #include <climits> |
6941
|
28 #include <ctime> |
3253
|
29 |
3607
|
30 #ifdef HAVE_UNISTD_H |
|
31 #ifdef HAVE_SYS_TYPES_H |
|
32 #include <sys/types.h> |
|
33 #endif |
|
34 #include <unistd.h> |
|
35 #endif |
|
36 |
4101
|
37 #if defined (OCTAVE_USE_WINDOWS_API) |
4085
|
38 #include <windows.h> |
6113
|
39 #undef min |
|
40 #undef max |
4085
|
41 #endif |
|
42 |
3253
|
43 #include "lo-error.h" |
7231
|
44 #include "lo-math.h" |
3253
|
45 #include "lo-utils.h" |
|
46 #include "oct-time.h" |
|
47 |
6119
|
48 #ifndef HAVE_STRFTIME |
|
49 // Override any previous definition and use local version. |
|
50 extern "C" size_t |
|
51 strftime (char *s, size_t maxsize, const char *format, const struct tm *tp); |
|
52 #endif |
|
53 |
3253
|
54 octave_time::octave_time (const octave_base_tm& tm) |
|
55 { |
|
56 struct tm t; |
|
57 |
|
58 t.tm_sec = tm.sec (); |
|
59 t.tm_min = tm.min (); |
|
60 t.tm_hour = tm.hour (); |
|
61 t.tm_mday = tm.mday (); |
|
62 t.tm_mon = tm.mon (); |
|
63 t.tm_year = tm.year (); |
|
64 t.tm_wday = tm.wday (); |
|
65 t.tm_yday = tm.yday (); |
|
66 t.tm_isdst = tm.isdst (); |
|
67 |
3887
|
68 #if defined (HAVE_STRUCT_TM_TM_ZONE) |
3504
|
69 std::string s = tm.zone (); |
3344
|
70 char *ps = strsave (s.c_str ()); |
|
71 t.tm_zone = ps; |
3253
|
72 #endif |
|
73 |
|
74 ot_unix_time = mktime (&t); |
|
75 |
3887
|
76 #if defined (HAVE_STRUCT_TM_TM_ZONE) |
3344
|
77 delete [] ps; |
|
78 #endif |
|
79 |
3253
|
80 ot_usec = tm.usec (); |
|
81 } |
|
82 |
3504
|
83 std::string |
3255
|
84 octave_time::ctime (void) const |
|
85 { |
|
86 return octave_localtime (*this) . asctime (); |
|
87 } |
|
88 |
3253
|
89 void |
|
90 octave_time::stamp (void) |
|
91 { |
|
92 #if defined (HAVE_GETTIMEOFDAY) |
|
93 |
|
94 struct timeval tp; |
|
95 |
|
96 #if defined (GETTIMEOFDAY_NO_TZ) |
|
97 gettimeofday (&tp); |
|
98 #else |
|
99 gettimeofday (&tp, 0); |
|
100 #endif |
|
101 |
|
102 ot_unix_time = tp.tv_sec; |
4085
|
103 ot_usec = tp.tv_usec; |
3253
|
104 |
4101
|
105 #elif defined (OCTAVE_USE_WINDOWS_API) |
4085
|
106 |
|
107 // Loosely based on the code from Cygwin |
7016
|
108 // Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. |
4085
|
109 // Licenced under the GPL. |
|
110 |
|
111 const LONGLONG TIME_OFFSET = 0x19db1ded53e8000LL; |
|
112 |
|
113 static int init = 1; |
|
114 static LARGE_INTEGER base; |
|
115 static LARGE_INTEGER t0; |
|
116 static double dt; |
|
117 |
|
118 if (init) |
|
119 { |
|
120 LARGE_INTEGER ifreq; |
|
121 |
|
122 if (QueryPerformanceFrequency (&ifreq)) |
|
123 { |
|
124 // Get clock frequency |
|
125 dt = (double) 1000000.0 / (double) ifreq.QuadPart; |
|
126 |
|
127 // Get base time as microseconds from Jan 1. 1970 |
|
128 int priority = GetThreadPriority (GetCurrentThread ()); |
|
129 SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); |
|
130 if (QueryPerformanceCounter (&base)) |
|
131 { |
|
132 FILETIME f; |
|
133 |
|
134 GetSystemTimeAsFileTime (&f); |
|
135 |
|
136 t0.HighPart = f.dwHighDateTime; |
|
137 t0.LowPart = f.dwLowDateTime; |
|
138 t0.QuadPart -= TIME_OFFSET; |
|
139 t0.QuadPart /= 10; |
|
140 |
|
141 init = 0; |
|
142 } |
|
143 |
|
144 SetThreadPriority (GetCurrentThread (), priority); |
|
145 } |
|
146 |
|
147 if (! init) |
|
148 { |
|
149 ot_unix_time = time (0); |
|
150 ot_usec = 0; |
|
151 |
|
152 return; |
|
153 } |
|
154 } |
|
155 |
|
156 LARGE_INTEGER now; |
|
157 |
|
158 if (QueryPerformanceCounter (&now)) |
|
159 { |
|
160 now.QuadPart = (LONGLONG) (dt * (double)(now.QuadPart - base.QuadPart)); |
|
161 now.QuadPart += t0.QuadPart; |
|
162 |
|
163 ot_unix_time = now.QuadPart / 1000000LL; |
|
164 ot_usec = now.QuadPart % 1000000LL; |
|
165 } |
|
166 else |
|
167 { |
|
168 ot_unix_time = time (0); |
|
169 ot_usec = 0; |
|
170 } |
3253
|
171 |
|
172 #else |
|
173 |
|
174 ot_unix_time = time (0); |
|
175 |
|
176 #endif |
|
177 } |
|
178 |
3736
|
179 // From the mktime() manual page: |
|
180 // |
|
181 // The mktime() function converts a broken-down time structure, |
|
182 // expressed as local time, to calendar time representation. |
|
183 // |
|
184 // <snip> |
|
185 // |
|
186 // If structure members are outside their legal interval, they |
|
187 // will be normalized (so that, e.g., 40 October is changed into |
|
188 // 9 November). |
|
189 // |
|
190 // So, we no longer check limits here. |
|
191 |
|
192 #if 0 |
3253
|
193 #define DEFINE_SET_INT_FIELD_FCN(f, lo, hi) \ |
|
194 octave_base_tm& \ |
|
195 octave_base_tm::f (int v) \ |
|
196 { \ |
|
197 if (v < lo || v > hi) \ |
|
198 (*current_liboctave_error_handler) \ |
|
199 ("invalid value specified for " #f); \ |
|
200 \ |
|
201 tm_ ## f = v; \ |
|
202 \ |
|
203 return *this; \ |
|
204 } |
3736
|
205 #else |
|
206 #define DEFINE_SET_INT_FIELD_FCN(f, lo, hi) \ |
|
207 octave_base_tm& \ |
|
208 octave_base_tm::f (int v) \ |
|
209 { \ |
|
210 tm_ ## f = v; \ |
|
211 \ |
|
212 return *this; \ |
|
213 } |
|
214 #endif |
3253
|
215 |
|
216 DEFINE_SET_INT_FIELD_FCN (usec, 0, 1000000) |
|
217 DEFINE_SET_INT_FIELD_FCN (sec, 0, 61) |
|
218 DEFINE_SET_INT_FIELD_FCN (min, 0, 59) |
|
219 DEFINE_SET_INT_FIELD_FCN (hour, 0, 23) |
|
220 DEFINE_SET_INT_FIELD_FCN (mday, 1, 31) |
|
221 DEFINE_SET_INT_FIELD_FCN (mon, 0, 11) |
|
222 DEFINE_SET_INT_FIELD_FCN (year, INT_MIN, INT_MAX) |
|
223 DEFINE_SET_INT_FIELD_FCN (wday, 0, 6) |
|
224 DEFINE_SET_INT_FIELD_FCN (yday, 0, 365) |
|
225 DEFINE_SET_INT_FIELD_FCN (isdst, 0, 1) |
|
226 |
|
227 octave_base_tm& |
3504
|
228 octave_base_tm::zone (const std::string& s) |
3253
|
229 { |
|
230 tm_zone = s; |
|
231 return *this; |
|
232 } |
|
233 |
|
234 #if !defined STRFTIME_BUF_INITIAL_SIZE |
|
235 #define STRFTIME_BUF_INITIAL_SIZE 128 |
|
236 #endif |
|
237 |
3504
|
238 std::string |
|
239 octave_base_tm::strftime (const std::string& fmt) const |
3253
|
240 { |
3504
|
241 std::string retval; |
3253
|
242 |
3709
|
243 if (! fmt.empty ()) |
|
244 { |
|
245 struct tm t; |
3253
|
246 |
3709
|
247 t.tm_sec = tm_sec; |
|
248 t.tm_min = tm_min; |
|
249 t.tm_hour = tm_hour; |
|
250 t.tm_mday = tm_mday; |
|
251 t.tm_mon = tm_mon; |
|
252 t.tm_year = tm_year; |
|
253 t.tm_wday = tm_wday; |
|
254 t.tm_yday = tm_yday; |
|
255 t.tm_isdst = tm_isdst; |
3253
|
256 |
3887
|
257 #if defined (HAVE_STRUCT_TM_TM_ZONE) |
3709
|
258 char *ps = strsave (tm_zone.c_str ()); |
|
259 t.tm_zone = ps; |
3253
|
260 #endif |
|
261 |
3709
|
262 const char *fmt_str = fmt.c_str (); |
3253
|
263 |
3709
|
264 char *buf = 0; |
|
265 size_t bufsize = STRFTIME_BUF_INITIAL_SIZE; |
|
266 size_t chars_written = 0; |
3253
|
267 |
3709
|
268 while (chars_written == 0) |
|
269 { |
|
270 delete [] buf; |
|
271 buf = new char[bufsize]; |
|
272 buf[0] = '\0'; |
3253
|
273 |
3709
|
274 chars_written = ::strftime (buf, bufsize, fmt_str, &t); |
3253
|
275 |
3709
|
276 bufsize *= 2; |
|
277 } |
3253
|
278 |
3887
|
279 #if defined (HAVE_STRUCT_TM_TM_ZONE) |
3709
|
280 delete [] ps; |
3344
|
281 #endif |
|
282 |
3709
|
283 retval = buf; |
3253
|
284 |
3709
|
285 delete [] buf; |
|
286 } |
3253
|
287 |
|
288 return retval; |
|
289 } |
|
290 |
|
291 void |
|
292 octave_base_tm::init (void *p) |
|
293 { |
|
294 struct tm *t = static_cast<struct tm*> (p); |
|
295 |
|
296 tm_sec = t->tm_sec; |
|
297 tm_min = t->tm_min; |
|
298 tm_hour = t->tm_hour; |
|
299 tm_mday = t->tm_mday; |
|
300 tm_mon = t->tm_mon; |
|
301 tm_year = t->tm_year; |
|
302 tm_wday = t->tm_wday; |
|
303 tm_yday = t->tm_yday; |
|
304 tm_isdst = t->tm_isdst; |
|
305 |
3887
|
306 #if defined (HAVE_STRUCT_TM_TM_ZONE) |
7270
|
307 if (t->tm_zone) |
|
308 tm_zone = t->tm_zone; |
3253
|
309 #elif defined (HAVE_TZNAME) |
|
310 if (t->tm_isdst == 0 || t->tm_isdst == 1) |
|
311 tm_zone = tzname[t->tm_isdst]; |
|
312 #endif |
|
313 } |
|
314 |
|
315 void |
|
316 octave_localtime::init (const octave_time& ot) |
|
317 { |
|
318 tm_usec = ot.usec (); |
|
319 |
7065
|
320 time_t t = ot.unix_time (); |
3253
|
321 |
|
322 octave_base_tm::init (localtime (&t)); |
|
323 } |
|
324 |
|
325 void |
|
326 octave_gmtime::init (const octave_time& ot) |
|
327 { |
|
328 tm_usec = ot.usec (); |
|
329 |
7065
|
330 time_t t = ot.unix_time (); |
3253
|
331 |
|
332 octave_base_tm::init (gmtime (&t)); |
|
333 } |
|
334 |
3465
|
335 void |
3504
|
336 octave_strptime::init (const std::string& str, const std::string& fmt) |
3465
|
337 { |
|
338 struct tm t; |
|
339 |
|
340 t.tm_sec = 0; |
|
341 t.tm_min = 0; |
|
342 t.tm_hour = 0; |
|
343 t.tm_mday = 0; |
6996
|
344 t.tm_mon = -1; |
|
345 t.tm_year = INT_MIN; |
3465
|
346 t.tm_wday = 0; |
|
347 t.tm_yday = 0; |
|
348 t.tm_isdst = 0; |
|
349 |
3887
|
350 #if defined (HAVE_STRUCT_TM_TM_ZONE) |
3465
|
351 char *ps = strsave (""); |
|
352 t.tm_zone = ps; |
|
353 #endif |
|
354 |
|
355 char *p = strsave (str.c_str ()); |
|
356 |
3706
|
357 char *q = oct_strptime (p, fmt.c_str (), &t); |
3465
|
358 |
6995
|
359 // Fill in wday and yday, but only if mday is valid and the mon and year |
|
360 // are filled in, avoiding issues with mktime and invalid dates. |
6996
|
361 if (t.tm_mday != 0 && t.tm_mon >= 0 && t.tm_year != INT_MIN) |
6995
|
362 { |
|
363 t.tm_isdst = -1; |
|
364 mktime (&t); |
|
365 } |
6941
|
366 |
6996
|
367 if (t.tm_mon < 0) |
|
368 t.tm_mon = 0; |
|
369 |
|
370 if (t.tm_year == INT_MIN) |
|
371 t.tm_year = 0; |
|
372 |
5675
|
373 if (q) |
|
374 nchars = q - p + 1; |
|
375 else |
|
376 nchars = 0; |
3465
|
377 |
|
378 delete [] p; |
|
379 |
|
380 octave_base_tm::init (&t); |
|
381 |
3887
|
382 #if defined (HAVE_STRUCT_TM_TM_ZONE) |
7058
|
383 delete [] ps; |
3465
|
384 #endif |
|
385 } |
|
386 |
3253
|
387 /* |
|
388 ;;; Local Variables: *** |
|
389 ;;; mode: C++ *** |
|
390 ;;; End: *** |
|
391 */ |