| # Gaudi Framework, version v25r0 |

Home |  | Generated: Mon Feb 17 2014

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Time.cpp
Go to the documentation of this file.
1 // $Id: Time.cpp,v 1.1 2006/01/26 09:24:03 hmd Exp $
2 // Include files
3 #include "GaudiKernel/Time.h"
4
5 #include "GaudiKernel/time_r.h"
6
7 #include <iostream>
8 #include <cstdio>
9 #include <ctime>
10 #include <cerrno>
11 #include <cstring>
12
13 // local
14 using namespace Gaudi;
15
16 // architecture dependent includes
17 #ifdef WIN32
18
19 // this turns off a lot of useless Win stuff which conflicts with Gaudi. (found empirically)
20 #define NOATOM
21 #define NOGDI
22 #define NOGDICAPMASKS
23 #define NOMETAFILE
24 #define NOMINMAX
25 #define NOMSG
26 #define NOOPENFILE
27 #define NORASTEROPS
28 #define NOSCROLL
29 #define NOSOUND
30 #define NOSYSMETRICS
31 #define NOTEXTMETRIC
32 #define NOWH
33 #define NOCOMM
34 #define NOKANJI
35 #define NOCRYPT
36 #define NOMCX
37
38 #include <windows.h>
39
40 #else
41 // Linux
42
43 #include <sys/time.h>
44
45 #endif
46
47 //-----------------------------------------------------------------------------
48 // Implementation file for class : Gaudi::Time
49 // Based on seal::Time
50 // 2005-12-15 : Marco Clemencic
51 //-----------------------------------------------------------------------------
52
53 #ifdef WIN32
54
63 //# define SECS_1601_TO_1970 ((369 * 365 + 89) * SECS_PER_DAY)
64 # define SECS_1601_TO_1970 ((369 * 365 + 89) * 86400ui64)
65 #endif
66
67 #ifdef WIN32
68 static time_t timegm (struct tm *t) {
69 // This code is adapted from wine, samba
70 time_t t1 = mktime (t);
71 struct tm gmt;
72 gmtime_s(&gmt, &t1);
73 time_t t2 = mktime(&gmt);
74 return t1 + (t1 - t2);
75 }
76 #endif
77
78 //=============================================================================
79 // Standard constructor, initializes variables
80 //=============================================================================
81 Time::Time( int year, int month, int day,
82 int hour, int min, int sec,
83 ValueType nsecs,
84 bool local /* = true */ ) {
85 tm val;
86 memset (&val, 0, sizeof (val));
87 val.tm_sec = sec;
88 val.tm_min = min;
89 val.tm_hour = hour;
90 val.tm_mday = day;
91 val.tm_mon = month;
92 val.tm_year = year > 1900 ? year - 1900 : year;
93 val.tm_isdst = -1; // FIXME?
94
95 m_nsecs = build (local, val, nsecs).m_nsecs;
96 }
97
98 #ifdef WIN32
99
101 Time Time::from (const FILETIME *systime) {
102 ValueType t = ((ValueType) systime->dwHighDateTime << 32)
103 + (ValueType) systime->dwLowDateTime;
104
105 if (t)
106 // Subtract bias (1970--1601 in 100ns), then convert to nanoseconds.
107 t = (t - SECS_1601_TO_1970 * (SEC_NSECS/100)) * 100;
108
109 return Time (t);
110 }
111 #endif
112
114 Time Time::current (void) {
115 #ifdef WIN32
116 FILETIME ftime;
117 GetSystemTimeAsFileTime (&ftime);
118 return from (&ftime);
119 #else
120 timeval tv;
121 if (gettimeofday (&tv, 0) != 0) {
122 char buf[256];
123 std::ostringstream tag,msg;
124 tag << "errno=" << errno;
125 if( strerror_r(errno, buf, 256) == 0 ) {
126 msg << buf;
127 } else {
128 msg << "Unknown error retrieving current time";
129 }
130 throw GaudiException(msg.str(),tag.str(),StatusCode::FAILURE);
131 }
132 return Time (tv.tv_sec, tv.tv_usec * 1000);
133 #endif
134 }
135
137 Time Time::build (bool local, const tm &base, TimeSpan diff /* = 0 */) {
138 tm tmp (base);
139 return Time (local ? mktime(&tmp) : timegm(&tmp), 0) + diff;
140 }
141
146 tm Time::split (bool local, int *nsecpart /* = 0 */) const {
147 if (nsecpart)
148 *nsecpart = (int)(m_nsecs % SEC_NSECS);
149
150 time_t val = (time_t)(m_nsecs / SEC_NSECS);
151
152 tm retval;
153 if (local)
154 localtime_r(&val, &retval);
155 else
156 gmtime_r(&val, &retval);
157
158 return retval;
159 }
160
164 tm Time::utc (int *nsecpart /* = 0 */) const {
165 return split (false, nsecpart);
166 }
167
171 tm Time::local (int *nsecpart /* = 0 */) const {
172 return split (true, nsecpart);
173 }
174
176 int Time::year (bool local) const {
177 return split (local).tm_year + 1900;
178 }
179
181 int Time::month (bool local) const {
182 return split (local).tm_mon;
183 }
184
186 int Time::day (bool local) const {
187 return split (local).tm_mday;
188 }
189
191 int Time::hour (bool local) const {
192 return split (local).tm_hour;
193 }
194
196 int Time::minute (bool local) const {
197 return split (local).tm_min;
198 }
199
203 int Time::second (bool local) const {
204 return split (local).tm_sec;
205 }
206
210 int Time::nsecond (void) const {
211 return (int)(m_nsecs % SEC_NSECS);
212 }
213
215 int Time::weekday (bool local) const {
216 return split (local).tm_wday;
217 }
218
222 bool Time::isdst (bool local) const {
223 return split (local).tm_isdst > 0;
224 }
225
232 Time::ValueType Time::utcoffset (int *daylight /* = 0 */) const {
233 ValueType n = 0;
234
235 #ifndef WIN32
236 tm localtm = local ();
237 n = localtm.tm_gmtoff;
238 if (daylight) *daylight = localtm.tm_isdst;
239 #else
240 // Adapted from WINE.
241 time_t utctime = (time_t)(m_nsecs / SEC_NSECS);
242 tm localtm;
243 localtime_s(&localtm, &utctime);
244 int savedaylight = localtm.tm_isdst;
245 tm gmt;
246 gmtime_s(&gmt, &utctime);
247
248 gmt.tm_isdst = savedaylight;
249 n = utctime - mktime (&gmt);
250
251 if (daylight) *daylight = savedaylight;
252 #endif
253 return n * SEC_NSECS;
254 }
255
256 #ifdef WIN32
257 // disable warning
258 // C4996: 'tzname': This function or variable may be unsafe.
259 #pragma warning(push)
260 #pragma warning(disable:4996)
261 #endif
262
266 const char * Time::timezone (int *daylight /* = 0 */) const {
267 tm localtm = local ();
268 if (daylight) *daylight = localtm.tm_isdst;
269 // extern "C" { extern char *tzname [2]; }
270 return tzname [localtm.tm_isdst > 0 ? 1 : 0];
271 }
272 #ifdef WIN32
273 #pragma warning(pop)
274 #endif
275
280 std::string Time::format (bool local, std::string spec) const {
282 std::string result;
283 tm time = split (local);
284 std::string::size_type length = 0;
285
286 // handle the special case of "%f"
287 std::string::size_type pos = spec.find("%f");
288 if (std::string::npos != pos) {
289 // Get the milliseconds string
290 std::string ms = nanoformat(3,3);
291 // Replace all the occurrences of '%f' (if not preceded by '%')
292 while (std::string::npos != pos) {
293 if (pos != 0 && spec[pos-1] != '%') {
294 spec.replace(pos, 2, ms);
295 }
296 pos = spec.find("%f", pos + 1); // search for the next occurrence
297 }
298 }
299 const int MIN_BUF_SIZE = 128;
300 do
301 {
302 // Guess how much we'll expand. If we go wrong, we'll expand again. (with a minimum)
303 result.resize(std::max<std::string::size_type>(result.size()*2,
304 std::max<std::string::size_type>(spec.size()*2, MIN_BUF_SIZE))
305 , 0);
306 length = ::strftime (&result[0], result.size(), spec.c_str(), &time);
307 } while (! length);
308
309 result.resize (length);
310 return result;
311 }
312
323 std::string Time::nanoformat (size_t minwidth /* = 1 */, size_t maxwidth /* = 9 */) const {
324 TimeAssert( (minwidth >= 1) && (minwidth <= maxwidth) && (maxwidth <= 9),
325 "nanoformat options do not satisfy: 1 <= minwidth <= maxwidth <= 9");
326
327 // Calculate the nanosecond fraction. This will be < 1000000000.
328 int value = (int)(m_nsecs % SEC_NSECS);
329
330 std::ostringstream buf;
331 buf.fill('0');
332 buf.width(9);
333 buf << value;
334 std::string out = buf.str();
335 // Find the last non-0 char before maxwidth, but after minwidth
336 // (Note: -1 and +1 are to account for difference between position and size.
337 // moreover, npos + 1 == 0, so it is correct to say that 'not found' means size of 0)
338 size_t len = out.find_last_not_of('0', maxwidth - 1) + 1;
339 // Truncate the output string to at least minwidth chars
340 out.resize(std::max(len, minwidth));
341 return out;
342 }
343
345
346 unsigned Time::toDosDate (Time time) {
347 // Use local time since DOS does too.
348 struct tm localtm = time.local ();
349
350 unsigned mday = localtm.tm_mday;
351 unsigned mon = localtm.tm_mon + 1;
352 unsigned year = (localtm.tm_year > 80 ? localtm.tm_year - 80 : 0);
353 unsigned sec = localtm.tm_sec / 2;
354 unsigned min = localtm.tm_min;
355 unsigned hour = localtm.tm_hour;
356 return (mday << 16 | mon << 21 | year << 25
357 | sec | min << 5 | hour << 11);
358 }
359
361 Time Time::fromDosDate (unsigned dosDate) {
362 // DOS times are generally local; treat it as UTC. This avoids
363 // any round-trip conversion and leaves only a presentation as an
364 // issue. Since not much can be known about the origin of the DOS
365 // times, it's generally best to present them as such (= in UTC).
366 struct tm localtm;
367 memset (&localtm, 0, sizeof (localtm));
368 localtm.tm_mday = (dosDate >> 16) & 0x1f;
369 localtm.tm_mon = ((dosDate >> 21) & 0xf) - 1;
370 localtm.tm_year = ((dosDate >> 25) & 0x7f) + 80;
371 localtm.tm_hour = (dosDate >> 11) & 0x1f;
372 localtm.tm_min = (dosDate >> 5) & 0x3f;
373 localtm.tm_sec = (dosDate & 0x1f) * 2;
374 localtm.tm_isdst = -1;
375
376 return Time (mktime (&localtm), 0);
377 }
378
379 //=============================================================================