Loading [MathJax]/extensions/tex2jax.js
The Gaudi Framework  v31r0 (aeb156f0)
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 <cerrno>
7 #include <cstdio>
8 #include <cstring>
9 #include <ctime>
10 #include <iostream>
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, int hour, int min, int sec, ValueType nsecs, bool local /* = true */ ) {
81  tm val;
82  memset( &val, 0, sizeof( val ) );
83  val.tm_sec = sec;
84  val.tm_min = min;
85  val.tm_hour = hour;
86  val.tm_mday = day;
87  val.tm_mon = month;
88  val.tm_year = year > 1900 ? year - 1900 : year;
89  val.tm_isdst = -1; // FIXME?
90 
91  m_nsecs = build( local, val, nsecs ).m_nsecs;
92 }
93 
94 #ifdef WIN32
95 
97 Time Time::from( const FILETIME* systime ) {
98  ValueType t = ( (ValueType)systime->dwHighDateTime << 32 ) + (ValueType)systime->dwLowDateTime;
99 
100  if ( t )
101  // Subtract bias (1970--1601 in 100ns), then convert to nanoseconds.
102  t = ( t - SECS_1601_TO_1970 * ( SEC_NSECS / 100 ) ) * 100;
103 
104  return Time( t );
105 }
106 #endif
107 
110 #ifdef WIN32
111  FILETIME ftime;
112  GetSystemTimeAsFileTime( &ftime );
113  return from( &ftime );
114 #else
115  timeval tv;
116  if ( gettimeofday( &tv, nullptr ) != 0 ) {
117  char buf[256];
118  std::ostringstream tag, msg;
119  tag << "errno=" << errno;
120  if ( strerror_r( errno, buf, 256 ) == 0 ) {
121  msg << buf;
122  } else {
123  msg << "Unknown error retrieving current time";
124  }
125  throw GaudiException( msg.str(), tag.str(), StatusCode::FAILURE );
126  }
127  return Time( tv.tv_sec, tv.tv_usec * 1000 );
128 #endif
129 }
130 
132 Time Time::build( bool local, const tm& base, TimeSpan diff /* = 0 */ ) {
133  tm tmp( base );
134  return Time( local ? mktime( &tmp ) : timegm( &tmp ), 0 ) + diff;
135 }
136 
141 tm Time::split( bool local, int* nsecpart /* = 0 */ ) const {
142  if ( nsecpart ) *nsecpart = (int)( m_nsecs % SEC_NSECS );
143 
144  time_t val = ( time_t )( m_nsecs / SEC_NSECS );
145 
146  tm retval;
147  if ( local )
148  localtime_r( &val, &retval );
149  else
150  gmtime_r( &val, &retval );
151 
152  return retval;
153 }
154 
158 tm Time::utc( int* nsecpart /* = 0 */ ) const { return split( false, nsecpart ); }
159 
163 tm Time::local( int* nsecpart /* = 0 */ ) const { return split( true, nsecpart ); }
164 
166 int Time::year( bool local ) const { return split( local ).tm_year + 1900; }
167 
169 int Time::month( bool local ) const { return split( local ).tm_mon; }
170 
172 int Time::day( bool local ) const { return split( local ).tm_mday; }
173 
175 int Time::hour( bool local ) const { return split( local ).tm_hour; }
176 
178 int Time::minute( bool local ) const { return split( local ).tm_min; }
179 
183 int Time::second( bool local ) const { return split( local ).tm_sec; }
184 
188 int Time::nsecond( void ) const { return (int)( m_nsecs % SEC_NSECS ); }
189 
191 int Time::weekday( bool local ) const { return split( local ).tm_wday; }
192 
196 bool Time::isdst( bool local ) const { return split( local ).tm_isdst > 0; }
197 
204 Time::ValueType Time::utcoffset( int* daylight /* = 0 */ ) const {
205  ValueType n = 0;
206 
207 #ifndef WIN32
208  tm localtm = local();
209  n = localtm.tm_gmtoff;
210  if ( daylight ) *daylight = localtm.tm_isdst;
211 #else
212  // Adapted from WINE.
213  time_t utctime = ( time_t )( m_nsecs / SEC_NSECS );
214  tm localtm;
215  localtime_s( &localtm, &utctime );
216  int savedaylight = localtm.tm_isdst;
217  tm gmt;
218  gmtime_s( &gmt, &utctime );
219 
220  gmt.tm_isdst = savedaylight;
221  n = utctime - mktime( &gmt );
222 
223  if ( daylight ) *daylight = savedaylight;
224 #endif
225  return n * SEC_NSECS;
226 }
227 
228 #ifdef WIN32
229 // disable warning
230 // C4996: 'tzname': This function or variable may be unsafe.
231 # pragma warning( push )
232 # pragma warning( disable : 4996 )
233 #endif
234 
238 const char* Time::timezone( int* daylight /* = 0 */ ) const {
239  tm localtm = local();
240  if ( daylight ) *daylight = localtm.tm_isdst;
241  // extern "C" { extern char *tzname [2]; }
242  return tzname[localtm.tm_isdst > 0 ? 1 : 0];
243 }
244 #ifdef WIN32
245 # pragma warning( pop )
246 #endif
247 
254  std::string result;
255  tm time = split( local );
256  std::string::size_type length = 0;
257 
258  // handle the special case of "%f"
259  std::string::size_type pos = spec.find( "%f" );
260  if ( std::string::npos != pos ) {
261  // Get the milliseconds string
262  std::string ms = nanoformat( 3, 3 );
263  // Replace all the occurrences of '%f' (if not preceded by '%')
264  while ( std::string::npos != pos ) {
265  if ( pos != 0 && spec[pos - 1] != '%' ) { spec.replace( pos, 2, ms ); }
266  pos = spec.find( "%f", pos + 1 ); // search for the next occurrence
267  }
268  }
269  const int MIN_BUF_SIZE = 128;
270  do {
271  // Guess how much we'll expand. If we go wrong, we'll expand again. (with a minimum)
272  result.resize( std::max<std::string::size_type>(
273  result.size() * 2, std::max<std::string::size_type>( spec.size() * 2, MIN_BUF_SIZE ) ),
274  0 );
275  length = ::strftime( &result[0], result.size(), spec.c_str(), &time );
276  } while ( !length );
277 
278  result.resize( length );
279  return result;
280 }
281 
292 std::string Time::nanoformat( size_t minwidth /* = 1 */, size_t maxwidth /* = 9 */ ) const {
293  TimeAssert( ( minwidth >= 1 ) && ( minwidth <= maxwidth ) && ( maxwidth <= 9 ),
294  "nanoformat options do not satisfy: 1 <= minwidth <= maxwidth <= 9" );
295 
296  // Calculate the nanosecond fraction. This will be < 1000000000.
297  int value = (int)( m_nsecs % SEC_NSECS );
298 
299  std::ostringstream buf;
300  buf.fill( '0' );
301  buf.width( 9 );
302  buf << value;
303  std::string out = buf.str();
304  // Find the last non-0 char before maxwidth, but after minwidth
305  // (Note: -1 and +1 are to account for difference between position and size.
306  // moreover, npos + 1 == 0, so it is correct to say that 'not found' means size of 0)
307  size_t len = out.find_last_not_of( '0', maxwidth - 1 ) + 1;
308  // Truncate the output string to at least minwidth chars
309  out.resize( std::max( len, minwidth ) );
310  return out;
311 }
312 
314 
315 unsigned Time::toDosDate( Time time ) {
316  // Use local time since DOS does too.
317  struct tm localtm = time.local();
318 
319  unsigned mday = localtm.tm_mday;
320  unsigned mon = localtm.tm_mon + 1;
321  unsigned year = ( localtm.tm_year > 80 ? localtm.tm_year - 80 : 0 );
322  unsigned sec = localtm.tm_sec / 2;
323  unsigned min = localtm.tm_min;
324  unsigned hour = localtm.tm_hour;
325  return ( mday << 16 | mon << 21 | year << 25 | sec | min << 5 | hour << 11 );
326 }
327 
329 Time Time::fromDosDate( unsigned dosDate ) {
330  // DOS times are generally local; treat it as UTC. This avoids
331  // any round-trip conversion and leaves only a presentation as an
332  // issue. Since not much can be known about the origin of the DOS
333  // times, it's generally best to present them as such (= in UTC).
334  struct tm localtm;
335  memset( &localtm, 0, sizeof( localtm ) );
336  localtm.tm_mday = ( dosDate >> 16 ) & 0x1f;
337  localtm.tm_mon = ( ( dosDate >> 21 ) & 0xf ) - 1;
338  localtm.tm_year = ( ( dosDate >> 25 ) & 0x7f ) + 80;
339  localtm.tm_hour = ( dosDate >> 11 ) & 0x1f;
340  localtm.tm_min = ( dosDate >> 5 ) & 0x3f;
341  localtm.tm_sec = ( dosDate & 0x1f ) * 2;
342  localtm.tm_isdst = -1;
343 
344  return Time( mktime( &localtm ), 0 );
345 }
346 
347 //=============================================================================
int hour(bool local) const
Get the hour, numbered [0, 23].
Definition: Time.cpp:175
Time()=default
Initialize an empty (zero) time value.
const char * timezone(int *daylight=0) const
Return the local timezone name that applies at this time value.
Definition: Time.cpp:238
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:141
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:132
Define general base for Gaudi exception.
int day(bool local) const
Get the day of month, numbered [1,31].
Definition: Time.cpp:172
static unsigned toDosDate(Time time)
Convert the Time t into a MS-DOS date format.
Definition: Time.cpp:315
int month(bool local) const
Get the month, numbered [0,11].
Definition: Time.cpp:169
EventIDBase min(const EventIDBase &lhs, const EventIDBase &rhs)
Definition: EventIDBase.h:202
tm utc(int *nsecpart=0) const
Break up the time to the standard library representation, keeping it in UTC.
Definition: Time.cpp:158
static Time current()
Returns the current time.
Definition: Time.cpp:109
bool isdst(bool local) const
Check whether daylight savings is in effect.
Definition: Time.cpp:196
void TimeAssert(bool cond, const std::string &msg="time assertion failed") const
Definition: Time.h:330
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:183
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:163
static const ValueType SEC_NSECS
Nanoseconds in one second.
Definition: Time.h:260
STL class.
T replace(T...args)
Based on seal::Time.
Definition: Time.h:231
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:204
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:292
T max(T...args)
static Time fromDosDate(unsigned dosDate)
Convert the MS-DOS date dosDate into a Time.
Definition: Time.cpp:329
T find_last_not_of(T...args)
T find(T...args)
T size(T...args)
ValueType m_nsecs
Definition: Time.h:328
T c_str(T...args)
int nsecond() const
Get the nanoseconds.
Definition: Time.cpp:188
constexpr static const auto FAILURE
Definition: StatusCode.h:86
int weekday(bool local) const
Get the day of week, numbered [0,6] and starting from Sunday.
Definition: Time.cpp:191
T fill(T...args)
int year(bool local) const
Get the year.
Definition: Time.cpp:166
Based on seal::TimeSpan.
Definition: Time.h:52
constexpr double ms
Helper functions to set/get the application return code.
Definition: __init__.py:1
long long ValueType
Definition: Time.h:235
std::string format(bool local, std::string spec="%c") const
Format the time using strftime.
Definition: Time.cpp:252
int minute(bool local) const
Get the minute, numbered [0, 59].
Definition: Time.cpp:178