The Gaudi Framework  master (82fdf313)
Loading...
Searching...
No Matches
Time.cpp
Go to the documentation of this file.
1/***********************************************************************************\
2* (c) Copyright 1998-2025 CERN for the benefit of the LHCb and ATLAS collaborations *
3* *
4* This software is distributed under the terms of the Apache version 2 licence, *
5* copied verbatim in the file "LICENSE". *
6* *
7* In applying this licence, CERN does not waive the privileges and immunities *
8* granted to it by virtue of its status as an Intergovernmental Organization *
9* or submit itself to any jurisdiction. *
10\***********************************************************************************/
11#include <GaudiKernel/Time.h>
12#include <cerrno>
13#include <cstdio>
14#include <cstring>
15#include <ctime>
16#include <iostream>
17
18using namespace Gaudi;
19
20#include <sys/time.h>
21
22//-----------------------------------------------------------------------------
23// Implementation file for class : Gaudi::Time
24// Based on seal::Time
25// 2005-12-15 : Marco Clemencic
26//-----------------------------------------------------------------------------
27
28Time::Time( int year, int month, int day, int hour, int min, int sec, ValueType nsecs, bool local /* = true */ ) {
29 tm val;
30 memset( &val, 0, sizeof( val ) );
31 val.tm_sec = sec;
32 val.tm_min = min;
33 val.tm_hour = hour;
34 val.tm_mday = day;
35 val.tm_mon = month;
36 val.tm_year = year > 1900 ? year - 1900 : year;
37 val.tm_isdst = -1; // FIXME?
38
39 m_nsecs = build( local, val, nsecs ).m_nsecs;
40}
41
44 timeval tv;
45 if ( gettimeofday( &tv, nullptr ) != 0 ) {
46 char buf[256];
47 std::ostringstream tag, msg;
48 tag << "errno=" << errno;
49 if ( strerror_r( errno, buf, 256 ) == 0 ) {
50 msg << buf;
51 } else {
52 msg << "Unknown error retrieving current time";
53 }
54 throw GaudiException( msg.str(), tag.str(), StatusCode::FAILURE );
55 }
56 return Time( tv.tv_sec, tv.tv_usec * 1000 );
57}
58
60Time Time::build( bool local, const tm& base, TimeSpan diff /* = 0 */ ) {
61 tm tmp( base );
62 return Time( local ? mktime( &tmp ) : timegm( &tmp ), 0 ) + diff;
63}
64
69tm Time::split( bool local, int* nsecpart /* = 0 */ ) const {
70 if ( nsecpart ) *nsecpart = (int)( m_nsecs % SEC_NSECS );
71
72 time_t val = (time_t)( m_nsecs / SEC_NSECS );
73
74 tm retval;
75 if ( local )
76 localtime_r( &val, &retval );
77 else
78 gmtime_r( &val, &retval );
79
80 return retval;
81}
82
86tm Time::utc( int* nsecpart /* = 0 */ ) const { return split( false, nsecpart ); }
87
91tm Time::local( int* nsecpart /* = 0 */ ) const { return split( true, nsecpart ); }
92
94int Time::year( bool local ) const { return split( local ).tm_year + 1900; }
95
97int Time::month( bool local ) const { return split( local ).tm_mon; }
98
100int Time::day( bool local ) const { return split( local ).tm_mday; }
101
103int Time::hour( bool local ) const { return split( local ).tm_hour; }
104
106int Time::minute( bool local ) const { return split( local ).tm_min; }
107
111int Time::second( bool local ) const { return split( local ).tm_sec; }
112
116int Time::nsecond( void ) const { return (int)( m_nsecs % SEC_NSECS ); }
117
119int Time::weekday( bool local ) const { return split( local ).tm_wday; }
120
124bool Time::isdst( bool local ) const { return split( local ).tm_isdst > 0; }
125
132Time::ValueType Time::utcoffset( int* daylight /* = 0 */ ) const {
133 ValueType n = 0;
134
135 tm localtm = local();
136 n = localtm.tm_gmtoff;
137 if ( daylight ) *daylight = localtm.tm_isdst;
138
139 return n * SEC_NSECS;
140}
141
146const char* Time::timezone( int* daylight /* = 0 */ ) const {
147 tm localtm = local();
148 if ( daylight ) *daylight = localtm.tm_isdst;
149 // extern "C" { extern char *tzname [2]; }
150 return tzname[localtm.tm_isdst > 0 ? 1 : 0];
151}
152
157std::string Time::format( bool local, std::string spec ) const {
159 std::string result;
160 tm time = split( local );
161 std::string::size_type length = 0;
162
163 // handle the special case of "%f"
164 std::string::size_type pos = spec.find( "%f" );
165 if ( std::string::npos != pos ) {
166 // Get the milliseconds string
167 std::string ms = nanoformat( 3, 3 );
168 // Replace all the occurrences of '%f' (if not preceded by '%')
169 while ( std::string::npos != pos ) {
170 if ( pos != 0 && spec[pos - 1] != '%' ) { spec.replace( pos, 2, ms ); }
171 pos = spec.find( "%f", pos + 1 ); // search for the next occurrence
172 }
173 }
174 const int MIN_BUF_SIZE = 128;
175 do {
176 // Guess how much we'll expand. If we go wrong, we'll expand again. (with a minimum)
177 result.resize( std::max<std::string::size_type>(
178 result.size() * 2, std::max<std::string::size_type>( spec.size() * 2, MIN_BUF_SIZE ) ),
179 0 );
180 length = ::strftime( &result[0], result.size(), spec.c_str(), &time );
181 } while ( !length );
182
183 result.resize( length );
184 return result;
185}
186
197std::string Time::nanoformat( size_t minwidth /* = 1 */, size_t maxwidth /* = 9 */ ) const {
198 TimeAssert( ( minwidth >= 1 ) && ( minwidth <= maxwidth ) && ( maxwidth <= 9 ),
199 "nanoformat options do not satisfy: 1 <= minwidth <= maxwidth <= 9" );
200
201 // Calculate the nanosecond fraction. This will be < 1000000000.
202 int value = (int)( m_nsecs % SEC_NSECS );
203
204 std::ostringstream buf;
205 (void)buf.fill( '0' );
206 buf.width( 9 );
207 buf << value;
208 std::string out = buf.str();
209 // Find the last non-0 char before maxwidth, but after minwidth
210 // (Note: -1 and +1 are to account for difference between position and size.
211 // moreover, npos + 1 == 0, so it is correct to say that 'not found' means size of 0)
212 size_t len = out.find_last_not_of( '0', maxwidth - 1 ) + 1;
213 // Truncate the output string to at least minwidth chars
214 out.resize( std::max( len, minwidth ) );
215 return out;
216}
217
219unsigned Time::toDosDate( Time time ) {
220 // Use local time since DOS does too.
221 struct tm localtm = time.local();
222
223 unsigned mday = localtm.tm_mday;
224 unsigned mon = localtm.tm_mon + 1;
225 unsigned year = ( localtm.tm_year > 80 ? localtm.tm_year - 80 : 0 );
226 unsigned sec = localtm.tm_sec / 2;
227 unsigned min = localtm.tm_min;
228 unsigned hour = localtm.tm_hour;
229 return ( mday << 16 | mon << 21 | year << 25 | sec | min << 5 | hour << 11 );
230}
231
233Time Time::fromDosDate( unsigned dosDate ) {
234 // DOS times are generally local; treat it as UTC. This avoids
235 // any round-trip conversion and leaves only a presentation as an
236 // issue. Since not much can be known about the origin of the DOS
237 // times, it's generally best to present them as such (= in UTC).
238 struct tm localtm;
239 memset( &localtm, 0, sizeof( localtm ) );
240 localtm.tm_mday = ( dosDate >> 16 ) & 0x1f;
241 localtm.tm_mon = ( ( dosDate >> 21 ) & 0xf ) - 1;
242 localtm.tm_year = ( ( dosDate >> 25 ) & 0x7f ) + 80;
243 localtm.tm_hour = ( dosDate >> 11 ) & 0x1f;
244 localtm.tm_min = ( dosDate >> 5 ) & 0x3f;
245 localtm.tm_sec = ( dosDate & 0x1f ) * 2;
246 localtm.tm_isdst = -1;
247
248 return Time( mktime( &localtm ), 0 );
249}
tm local(int *nsecpart=0) const
Break up the time to the standard library representation, converting it first to local time.
Definition Time.cpp:91
int hour(bool local) const
Get the hour, numbered [0, 23].
Definition Time.cpp:103
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:60
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:111
friend class TimeSpan
Definition Time.h:236
int month(bool local) const
Get the month, numbered [0,11].
Definition Time.cpp:97
const char * timezone(int *daylight=0) const
Return the local timezone name that applies at this time value.
Definition Time.cpp:146
int weekday(bool local) const
Get the day of week, numbered [0,6] and starting from Sunday.
Definition Time.cpp:119
int nsecond() const
Get the nanoseconds.
Definition Time.cpp:116
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:197
std::string format(bool local, std::string spec="%c") const
Format the time using strftime.
Definition Time.cpp:157
int minute(bool local) const
Get the minute, numbered [0, 59].
Definition Time.cpp:106
static Time fromDosDate(unsigned dosDate)
Convert the MS-DOS date dosDate into a Time.
Definition Time.cpp:233
bool isdst(bool local) const
Check whether daylight savings is in effect.
Definition Time.cpp:124
Time()=default
Initialize an empty (zero) time value.
int year(bool local) const
Get the year.
Definition Time.cpp:94
tm utc(int *nsecpart=0) const
Break up the time to the standard library representation, keeping it in UTC.
Definition Time.cpp:86
ValueType m_nsecs
Definition Time.h:330
static Time current()
Returns the current time.
Definition Time.cpp:43
int day(bool local) const
Get the day of month, numbered [1,31].
Definition Time.cpp:100
static const ValueType SEC_NSECS
Nanoseconds in one second.
Definition Time.h:264
long long ValueType
Definition Time.h:239
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:132
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:69
void TimeAssert(bool cond, std::string_view msg="time assertion failed") const
Definition Time.h:333
static unsigned toDosDate(Time time)
Convert the Time t into a MS-DOS date format.
Definition Time.cpp:219
Define general base for Gaudi exception.
constexpr static const auto FAILURE
Definition StatusCode.h:100
This file provides a Grammar for the type Gaudi::Accumulators::Axis It allows to use that type from p...
Definition __init__.py:1