| # 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