| The Gaudi Framework v32r1 (f65d50dc)

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
109 Time Time::current( void ) {
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
252 std::string Time::format( bool local, std::string spec ) const {
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 //=============================================================================
plotSpeedupsPyRoot.time
def time
Definition: plotSpeedupsPyRoot.py:152
Gaudi::Time::year
int year(bool local) const
Get the year.
Definition: Time.cpp:166
Gaudi::Time::Time
Time()=default
Initialize an empty (zero) time value.
Gaudi::Time::build
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
GaudiException
Define general base for Gaudi exception.
Definition: GaudiException.h:21
Gaudi::Time::day
int day(bool local) const
Get the day of month, numbered [1,31].
Definition: Time.cpp:172
Gaudi::Time::toDosDate
static unsigned toDosDate(Time time)
Convert the Time t into a MS-DOS date format.
Definition: Time.cpp:315
Gaudi::Time::utcoffset
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
min
EventIDBase min(const EventIDBase &lhs, const EventIDBase &rhs)
Definition: EventIDBase.h:202
Gaudi::Time::current
static Time current()
Returns the current time.
Definition: Time.cpp:109
Gaudi::Time::hour
int hour(bool local) const
Get the hour, numbered [0, 23].
Definition: Time.cpp:175
compareRootHistos.retval
def retval
Definition: compareRootHistos.py:458
std::string::resize
T resize(T... args)
Gaudi::Time::SEC_NSECS
static const ValueType SEC_NSECS
Nanoseconds in one second.
Definition: Time.h:260
std::string
STL class.
GaudiPluginService.cpluginsvc.n
n
Definition: cpluginsvc.py:210
Gaudi::Time::timezone
const char * timezone(int *daylight=0) const
Return the local timezone name that applies at this time value.
Definition: Time.cpp:238
std::string::replace
T replace(T... args)
Gaudi::Time
Based on seal::Time.
Definition: Time.h:231
std::ostringstream
STL class.
Gaudi::Time::second
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
Gaudi::Time::nsecond
int nsecond() const
Get the nanoseconds.
Definition: Time.cpp:188
std::ostringstream::width
T width(T... args)
std::mktime
T mktime(T... args)
time_r.h
std::ostringstream::str
T str(T... args)
Gaudi::Time::split
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
Time.h
std::max
T max(T... args)
Gaudi::Time::fromDosDate
static Time fromDosDate(unsigned dosDate)
Convert the MS-DOS date dosDate into a Time.
Definition: Time.cpp:329
Gaudi::Time::month
int month(bool local) const
Get the month, numbered [0,11].
Definition: Time.cpp:169
std::string::find_last_not_of
T find_last_not_of(T... args)
Gaudi::Time::weekday
int weekday(bool local) const
Get the day of week, numbered [0,6] and starting from Sunday.
Definition: Time.cpp:191
std::string::find
T find(T... args)
Gaudi::Time::isdst
bool isdst(bool local) const
Check whether daylight savings is in effect.
Definition: Time.cpp:196
std::string::size
T size(T... args)
Gaudi::Time::format
std::string format(bool local, std::string spec="%c") const
Format the time using strftime.
Definition: Time.cpp:252
Gaudi::Time::m_nsecs
ValueType m_nsecs
Definition: Time.h:328
std::string::c_str
T c_str(T... args)
GaudiMP.FdsRegistry.msg
msg
Definition: FdsRegistry.py:8
StatusCode::FAILURE
constexpr static const auto FAILURE
Definition: StatusCode.h:86
std::ostringstream::fill
T fill(T... args)
Gaudi::Time::local
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
Gaudi::Time::minute
int minute(bool local) const
Get the minute, numbered [0, 59].
Definition: Time.cpp:178
Gaudi::TimeSpan
Based on seal::TimeSpan.
Definition: Time.h:52
Gaudi::Units::ms
constexpr double ms
Definition: SystemOfUnits.h:134
Gaudi
Header file for std:chrono::duration-based Counters.
Definition: __init__.py:1
Gaudi::Time::utc
tm utc(int *nsecpart=0) const
Break up the time to the standard library representation, keeping it in UTC.
Definition: Time.cpp:158
Gaudi::Time::ValueType
long long ValueType
Definition: Time.h:235
Gaudi::Time::TimeAssert
void TimeAssert(bool cond, const std::string &msg="time assertion failed") const
Definition: Time.h:330
Gaudi::Time::nanoformat
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