![]() |
|
|
Generated: 24 Nov 2008 |
00001 // $Id: Time.cpp,v 1.1 2006/01/26 09:24:03 hmd Exp $ 00002 // Include files 00003 #include "GaudiKernel/Time.h" 00004 00005 #include <iostream> 00006 #include <cstdio> 00007 #include <ctime> 00008 #include <cerrno> 00009 #include <cstring> 00010 00011 // local 00012 using namespace Gaudi; 00013 00014 // architecture dependent includes 00015 #ifdef WIN32 00016 00017 // this turns off a lot of useless Win stuff which conflicts with Gaudi. (found empirically) 00018 #define NOATOM 00019 #define NOGDI 00020 #define NOGDICAPMASKS 00021 #define NOMETAFILE 00022 #define NOMINMAX 00023 #define NOMSG 00024 #define NOOPENFILE 00025 #define NORASTEROPS 00026 #define NOSCROLL 00027 #define NOSOUND 00028 #define NOSYSMETRICS 00029 #define NOTEXTMETRIC 00030 #define NOWH 00031 #define NOCOMM 00032 #define NOKANJI 00033 #define NOCRYPT 00034 #define NOMCX 00035 00036 #include <windows.h> 00037 00038 #else 00039 // Linux 00040 00041 #include <sys/time.h> 00042 00043 #endif 00044 00045 //----------------------------------------------------------------------------- 00046 // Implementation file for class : Gaudi::Time 00047 // Based on seal::Time 00048 // 2005-12-15 : Marco Clemencic 00049 //----------------------------------------------------------------------------- 00050 00051 #ifdef WIN32 00052 00061 //# define SECS_1601_TO_1970 ((369 * 365 + 89) * SECS_PER_DAY) 00062 # define SECS_1601_TO_1970 ((369 * 365 + 89) * 86400ui64) 00063 #endif 00064 00065 #ifdef WIN32 00066 static time_t timegm (struct tm *t) { 00067 // This code is adapted from wine, samba 00068 time_t t1 = mktime (t); 00069 struct tm gmt = *gmtime (&t1); 00070 time_t t2 = mktime (&gmt); 00071 return t1 + (t1 - t2); 00072 } 00073 #endif 00074 00075 //============================================================================= 00076 // Standard constructor, initializes variables 00077 //============================================================================= 00078 Time::Time( int year, int month, int day, 00079 int hour, int min, int sec, 00080 ValueType nsecs, 00081 bool local /* = true */ ) { 00082 tm val; 00083 memset (&val, sizeof (val), 0); 00084 val.tm_sec = sec; 00085 val.tm_min = min; 00086 val.tm_hour = hour; 00087 val.tm_mday = day; 00088 val.tm_mon = month; 00089 val.tm_year = year > 1900 ? year - 1900 : year; 00090 val.tm_isdst = -1; // FIXME? 00091 00092 m_nsecs = build (local, val, nsecs).m_nsecs; 00093 } 00094 00095 #ifdef WIN32 00096 00098 Time Time::from (const FILETIME *systime) { 00099 ValueType t = ((ValueType) systime->dwHighDateTime << 32) 00100 + (ValueType) systime->dwLowDateTime; 00101 00102 if (t) 00103 // Subtract bias (1970--1601 in 100ns), then convert to nanoseconds. 00104 t = (t - SECS_1601_TO_1970 * (SEC_NSECS/100)) * 100; 00105 00106 return Time (t); 00107 } 00108 #endif 00109 00111 Time Time::current (void) { 00112 #ifdef WIN32 00113 FILETIME ftime; 00114 GetSystemTimeAsFileTime (&ftime); 00115 return from (&ftime); 00116 #else 00117 timeval tv; 00118 if (gettimeofday (&tv, 0) != 0) { 00119 char buf[256]; 00120 std::ostringstream tag,msg; 00121 tag << "errno=" << errno; 00122 if( strerror_r(errno, buf, 256) == 0 ) { 00123 msg << buf; 00124 } else { 00125 msg << "Unknown error retriving current time"; 00126 } 00127 throw GaudiException(msg.str(),tag.str(),StatusCode::FAILURE); 00128 } 00129 return Time (tv.tv_sec, tv.tv_usec * 1000); 00130 #endif 00131 } 00132 00134 Time Time::build (bool local, const tm &base, TimeSpan diff /* = 0 */) { 00135 tm tmp (base); 00136 return Time (local ? mktime(&tmp) : timegm(&tmp), 0) + diff; 00137 } 00138 00143 tm Time::split (bool local, int *nsecpart /* = 0 */) const { 00144 if (nsecpart) 00145 *nsecpart = (int)(m_nsecs % SEC_NSECS); 00146 00147 time_t val = (time_t)(m_nsecs / SEC_NSECS); 00148 return *(local ? localtime (&val) : gmtime (&val)); 00149 } 00150 00154 tm Time::utc (int *nsecpart /* = 0 */) const { 00155 return split (false, nsecpart); 00156 } 00157 00161 tm Time::local (int *nsecpart /* = 0 */) const { 00162 return split (true, nsecpart); 00163 } 00164 00166 int Time::year (bool local) const { 00167 return split (local).tm_year + 1900; 00168 } 00169 00171 int Time::month (bool local) const { 00172 return split (local).tm_mon; 00173 } 00174 00176 int Time::day (bool local) const { 00177 return split (local).tm_mday; 00178 } 00179 00181 int Time::hour (bool local) const { 00182 return split (local).tm_hour; 00183 } 00184 00186 int Time::minute (bool local) const { 00187 return split (local).tm_min; 00188 } 00189 00193 int Time::second (bool local) const { 00194 return split (local).tm_sec; 00195 } 00196 00200 int Time::nsecond (void) const { 00201 return (int)(m_nsecs % SEC_NSECS); 00202 } 00203 00205 int Time::weekday (bool local) const { 00206 return split (local).tm_wday; 00207 } 00208 00212 bool Time::isdst (bool local) const { 00213 return split (local).tm_isdst > 0; 00214 } 00215 00222 Time::ValueType Time::utcoffset (int *daylight /* = 0 */) const { 00223 ValueType n = 0; 00224 00225 #ifndef WIN32 00226 tm localtm = local (); 00227 n = localtm.tm_gmtoff; 00228 if (daylight) *daylight = localtm.tm_isdst; 00229 #else 00230 // Adapted from WINE. 00231 time_t utctime = (time_t)(m_nsecs / SEC_NSECS); 00232 tm localtm = *localtime (&utctime); 00233 int savedaylight = localtm.tm_isdst; 00234 tm gmt = *gmtime (&utctime); 00235 00236 gmt.tm_isdst = savedaylight; 00237 n = utctime - mktime (&gmt); 00238 00239 if (daylight) *daylight = savedaylight; 00240 #endif 00241 return n * SEC_NSECS; 00242 } 00243 00248 const char * Time::timezone (int *daylight /* = 0 */) const { 00249 tm localtm = local (); 00250 if (daylight) *daylight = localtm.tm_isdst; 00251 // extern "C" { extern char *tzname [2]; } 00252 return tzname [localtm.tm_isdst > 0 ? 1 : 0]; 00253 } 00254 00256 std::string Time::format (bool local, const std::string &spec) const { 00257 // FIXME: This doesn't account for nsecs part! 00258 std::string result; 00259 tm time = split (local); 00260 int length = 0; 00261 00262 do 00263 { 00264 // Guess how much we'll expand. If we go wrong, we'll expand again. 00265 result.resize (result.size() ? result.size()*2 : spec.size()*2, 0); 00266 length = ::strftime (&result[0], result.size(), spec.c_str(), &time); 00267 } while (! length); 00268 00269 result.resize (length); 00270 return result; 00271 } 00272 00283 std::string Time::nanoformat (int minwidth /* = 1 */, int maxwidth /* = 9 */) const { 00284 TimeAssert( (minwidth >= 1) && (minwidth <= maxwidth) && (maxwidth <= 9), 00285 "nanoformat options do not satisfy: 1 <= minwidth <= maxwidth <= 9"); 00286 00287 // Calculate the nanosecond fraction. This will be < 1000000000. 00288 int value = (int)(m_nsecs % SEC_NSECS); 00289 00290 // Calculate modulus by which we truncate value. If maxwidth is 00291 // say 3, we want to mask of the last 6 digits. 00292 int modulus = 1; 00293 for (int i = 0; i < 9 - maxwidth; ++i) 00294 modulus *= 10; 00295 00296 // Round value by the desired modulus. 00297 int rem = value % modulus; 00298 value -= rem; 00299 if (rem > modulus / 2) 00300 value += modulus; 00301 00302 // Format it, then strip off digits from the right as long as 00303 // we zeroes. The above guarantees enough zeroes on right to 00304 // satisfy maxwidth so we need to concern ourselves only about 00305 // minwidth. 00306 char buf [10]; 00307 char *p = buf + 8; 00308 sprintf (buf, "%09d", value); 00309 while (p > buf + minwidth - 1 && *p == '0') 00310 *p-- = '\0'; 00311 00312 return buf; 00313 } 00314 00316 00317 unsigned Time::toDosDate (Time time) { 00318 // Use local time since DOS does too. 00319 struct tm localtm = time.local (); 00320 00321 unsigned mday = localtm.tm_mday; 00322 unsigned mon = localtm.tm_mon + 1; 00323 unsigned year = (localtm.tm_year > 80 ? localtm.tm_year - 80 : 0); 00324 unsigned sec = localtm.tm_sec / 2; 00325 unsigned min = localtm.tm_min; 00326 unsigned hour = localtm.tm_hour; 00327 return (mday << 16 | mon << 21 | year << 25 00328 | sec | min << 5 | hour << 11); 00329 } 00330 00332 Time Time::fromDosDate (unsigned dosDate) { 00333 // DOS times are generally local; treat it as UTC. This avoids 00334 // any round-trip conversion and leaves only a presentation as an 00335 // issue. Since not much can be known about the origin of the DOS 00336 // times, it's generally best to present them as such (= in UTC). 00337 struct tm localtm; 00338 memset (&localtm, 0, sizeof (localtm)); 00339 localtm.tm_mday = (dosDate >> 16) & 0x1f; 00340 localtm.tm_mon = ((dosDate >> 21) & 0xf) - 1; 00341 localtm.tm_year = ((dosDate >> 25) & 0x7f) + 80; 00342 localtm.tm_hour = (dosDate >> 11) & 0x1f; 00343 localtm.tm_min = (dosDate >> 5) & 0x3f; 00344 localtm.tm_sec = (dosDate & 0x1f) * 2; 00345 localtm.tm_isdst = -1; 00346 00347 return Time (mktime (&localtm), 0); 00348 } 00349 00350 //=============================================================================