Gaudi Framework, version v22r2

Home   Generated: Tue May 10 2011

Time.cpp

Go to the documentation of this file.
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 "GaudiKernel/time_r.h"
00006 
00007 #include <iostream>
00008 #include <cstdio>
00009 #include <ctime>
00010 #include <cerrno>
00011 #include <cstring>
00012 
00013 // local
00014 using namespace Gaudi;
00015 
00016 // architecture dependent includes
00017 #ifdef WIN32
00018 
00019 // this turns off a lot of useless Win stuff which conflicts with Gaudi. (found empirically)
00020 #define NOATOM
00021 #define NOGDI
00022 #define NOGDICAPMASKS
00023 #define NOMETAFILE
00024 #define NOMINMAX
00025 #define NOMSG
00026 #define NOOPENFILE
00027 #define NORASTEROPS
00028 #define NOSCROLL
00029 #define NOSOUND
00030 #define NOSYSMETRICS
00031 #define NOTEXTMETRIC
00032 #define NOWH
00033 #define NOCOMM
00034 #define NOKANJI
00035 #define NOCRYPT
00036 #define NOMCX
00037 
00038 #include <windows.h>
00039 
00040 #else
00041 // Linux
00042 
00043 #include <sys/time.h>
00044 
00045 #endif
00046 
00047 //-----------------------------------------------------------------------------
00048 // Implementation file for class : Gaudi::Time
00049 // Based on seal::Time
00050 // 2005-12-15 : Marco Clemencic
00051 //-----------------------------------------------------------------------------
00052 
00053 #ifdef WIN32
00054 
00063 //# define SECS_1601_TO_1970    ((369 * 365 + 89) * SECS_PER_DAY)
00064 # define SECS_1601_TO_1970      ((369 * 365 + 89) * 86400ui64)
00065 #endif
00066 
00067 #ifdef WIN32
00068 static time_t timegm (struct tm *t) {
00069   // This code is adapted from wine, samba
00070   time_t t1 = mktime (t);
00071   struct tm gmt;
00072   gmtime_s(&gmt, &t1);
00073   time_t t2 = mktime(&gmt);
00074   return t1 + (t1 - t2);
00075 }
00076 #endif
00077 
00078 //=============================================================================
00079 // Standard constructor, initializes variables
00080 //=============================================================================
00081 Time::Time( int year, int month, int day,
00082             int hour, int min, int sec,
00083             ValueType nsecs,
00084             bool local /* = true */ ) {
00085   tm val;
00086   memset (&val, 0, sizeof (val));
00087   val.tm_sec = sec;
00088   val.tm_min = min;
00089   val.tm_hour = hour;
00090   val.tm_mday = day;
00091   val.tm_mon = month;
00092   val.tm_year = year > 1900 ? year - 1900 : year;
00093   val.tm_isdst = -1; // FIXME?
00094 
00095   m_nsecs = build (local, val, nsecs).m_nsecs;
00096 }
00097 
00098 #ifdef WIN32
00099 
00101 Time Time::from (const FILETIME *systime) {
00102   ValueType t = ((ValueType) systime->dwHighDateTime << 32)
00103     + (ValueType) systime->dwLowDateTime;
00104 
00105   if (t)
00106     // Subtract bias (1970--1601 in 100ns), then convert to nanoseconds.
00107     t = (t - SECS_1601_TO_1970 * (SEC_NSECS/100)) * 100;
00108 
00109   return Time (t);
00110 }
00111 #endif
00112 
00114 Time Time::current (void) {
00115 #ifdef WIN32
00116   FILETIME ftime;
00117   GetSystemTimeAsFileTime (&ftime);
00118   return from (&ftime);
00119 #else
00120   timeval tv;
00121   if (gettimeofday (&tv, 0) != 0) {
00122     char buf[256];
00123     std::ostringstream tag,msg;
00124     tag << "errno=" << errno;
00125     if( strerror_r(errno, buf, 256) == 0 ) {
00126       msg << buf;
00127     } else {
00128       msg << "Unknown error retrieving current time";
00129     }
00130     throw GaudiException(msg.str(),tag.str(),StatusCode::FAILURE);
00131   }
00132   return Time (tv.tv_sec, tv.tv_usec * 1000);
00133 #endif
00134 }
00135 
00137 Time Time::build (bool local, const tm &base, TimeSpan diff /* = 0 */) {
00138   tm tmp (base);
00139   return Time (local ? mktime(&tmp) : timegm(&tmp), 0) + diff;
00140 }
00141 
00146 tm Time::split (bool local, int *nsecpart /* = 0 */) const {
00147   if (nsecpart)
00148     *nsecpart = (int)(m_nsecs % SEC_NSECS);
00149 
00150   time_t val = (time_t)(m_nsecs / SEC_NSECS);
00151 
00152   tm retval;
00153   if (local)
00154         localtime_r(&val, &retval);
00155   else
00156         gmtime_r(&val, &retval);
00157 
00158   return retval;
00159 }
00160 
00164 tm Time::utc (int *nsecpart /* = 0 */) const {
00165   return split (false, nsecpart);
00166 }
00167 
00171 tm Time::local (int *nsecpart /* = 0 */) const {
00172   return split (true, nsecpart);
00173 }
00174 
00176 int Time::year (bool local) const {
00177   return split (local).tm_year + 1900;
00178 }
00179 
00181 int Time::month (bool local) const {
00182   return split (local).tm_mon;
00183 }
00184 
00186 int Time::day (bool local) const {
00187   return split (local).tm_mday;
00188 }
00189 
00191 int Time::hour (bool local) const {
00192   return split (local).tm_hour;
00193 }
00194 
00196 int Time::minute (bool local) const {
00197   return split (local).tm_min;
00198 }
00199 
00203 int Time::second (bool local) const {
00204   return split (local).tm_sec;
00205 }
00206 
00210 int Time::nsecond (void) const {
00211   return (int)(m_nsecs % SEC_NSECS);
00212 }
00213 
00215 int Time::weekday (bool local) const {
00216   return split (local).tm_wday;
00217 }
00218 
00222 bool Time::isdst (bool local) const {
00223   return split (local).tm_isdst > 0;
00224 }
00225 
00232 Time::ValueType Time::utcoffset (int *daylight /* = 0 */) const {
00233   ValueType n = 0;
00234 
00235 #ifndef WIN32
00236   tm localtm = local ();
00237   n = localtm.tm_gmtoff;
00238   if (daylight) *daylight = localtm.tm_isdst;
00239 #else
00240   // Adapted from WINE.
00241   time_t        utctime = (time_t)(m_nsecs / SEC_NSECS);
00242   tm            localtm;
00243   localtime_s(&localtm, &utctime);
00244   int           savedaylight = localtm.tm_isdst;
00245   tm            gmt;
00246   gmtime_s(&gmt, &utctime);
00247 
00248   gmt.tm_isdst = savedaylight;
00249   n = utctime - mktime (&gmt);
00250 
00251   if (daylight) *daylight = savedaylight;
00252 #endif
00253   return n * SEC_NSECS;
00254 }
00255 
00256 #ifdef WIN32
00257 // disable warning
00258 // C4996: 'tzname': This function or variable may be unsafe.
00259 #pragma warning(push)
00260 #pragma warning(disable:4996)
00261 #endif
00262 
00266 const char * Time::timezone (int *daylight /* = 0 */) const {
00267   tm localtm = local ();
00268   if (daylight) *daylight = localtm.tm_isdst;
00269   // extern "C" { extern char *tzname [2]; }
00270   return tzname [localtm.tm_isdst > 0 ? 1 : 0];
00271 }
00272 #ifdef WIN32
00273 #pragma warning(pop)
00274 #endif
00275 
00280 std::string Time::format (bool local, std::string spec) const {
00282   std::string            result;
00283   tm                     time = split (local);
00284   std::string::size_type length = 0;
00285 
00286   // handle the special case of "%f"
00287   std::string::size_type pos = spec.find("%f");
00288   if (std::string::npos != pos) {
00289     // Get the milliseconds string
00290     std::string ms = nanoformat(3,3);
00291     // Replace all the occurrences of '%f' (if not preceded by '%')
00292     while (std::string::npos != pos) {
00293       if (pos != 0 && spec[pos-1] != '%') {
00294         spec.replace(pos, 2, ms);
00295       }
00296       pos = spec.find("%f", pos + 1); // search for the next occurrence
00297     }
00298   }
00299   const int MIN_BUF_SIZE = 128;
00300   do
00301   {
00302     // Guess how much we'll expand.  If we go wrong, we'll expand again. (with a minimum)
00303     result.resize(std::max<std::string::size_type>(result.size()*2,
00304                     std::max<std::string::size_type>(spec.size()*2, MIN_BUF_SIZE))
00305                   , 0);
00306     length = ::strftime (&result[0], result.size(), spec.c_str(), &time);
00307   } while (! length);
00308 
00309   result.resize (length);
00310   return result;
00311 }
00312 
00323 std::string Time::nanoformat (size_t minwidth /* = 1 */, size_t maxwidth /* = 9 */) const {
00324   TimeAssert( (minwidth >= 1) && (minwidth <= maxwidth) && (maxwidth <= 9),
00325               "nanoformat options do not satisfy: 1 <= minwidth <= maxwidth <= 9");
00326 
00327   // Calculate the nanosecond fraction.  This will be < 1000000000.
00328   int value = (int)(m_nsecs % SEC_NSECS);
00329 
00330   std::ostringstream buf;
00331   buf.fill('0');
00332   buf.width(9);
00333   buf << value;
00334   std::string out = buf.str();
00335   // Find the last non-0 char before maxwidth, but after minwidth
00336   // (Note: -1 and +1 are to account for difference between position and size.
00337   //        moreover, npos + 1 == 0, so it is correct to say that 'not found' means size of 0)
00338   size_t len = out.find_last_not_of('0', maxwidth - 1) + 1;
00339   // Truncate the output string to at least minwidth chars
00340   out.resize(std::max(len, minwidth));
00341   return out;
00342 }
00343 
00345 
00346 unsigned Time::toDosDate (Time time) {
00347   // Use local time since DOS does too.
00348   struct tm localtm = time.local ();
00349 
00350   unsigned mday = localtm.tm_mday;
00351   unsigned mon  = localtm.tm_mon + 1;
00352   unsigned year = (localtm.tm_year > 80 ? localtm.tm_year - 80 : 0);
00353   unsigned sec  = localtm.tm_sec / 2;
00354   unsigned min  = localtm.tm_min;
00355   unsigned hour = localtm.tm_hour;
00356   return (mday << 16 | mon << 21 | year << 25
00357           | sec      | min << 5  | hour << 11);
00358 }
00359 
00361 Time Time::fromDosDate (unsigned dosDate) {
00362   // DOS times are generally local; treat it as UTC.  This avoids
00363   // any round-trip conversion and leaves only a presentation as an
00364   // issue.  Since not much can be known about the origin of the DOS
00365   // times, it's generally best to present them as such (= in UTC).
00366   struct tm localtm;
00367   memset (&localtm, 0, sizeof (localtm));
00368   localtm.tm_mday  = (dosDate >> 16) & 0x1f;
00369   localtm.tm_mon   = ((dosDate >> 21) & 0xf) - 1;
00370   localtm.tm_year  = ((dosDate >> 25) & 0x7f) + 80;
00371   localtm.tm_hour  = (dosDate >> 11) & 0x1f;
00372   localtm.tm_min   = (dosDate >> 5) & 0x3f;
00373   localtm.tm_sec   = (dosDate & 0x1f) * 2;
00374   localtm.tm_isdst = -1;
00375 
00376   return Time (mktime (&localtm), 0);
00377 }
00378 
00379 //=============================================================================
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines

Generated at Tue May 10 2011 18:53:46 for Gaudi Framework, version v22r2 by Doxygen version 1.7.2 written by Dimitri van Heesch, © 1997-2004