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