Gaudi Framework, version v21r11

Home   Generated: 30 Sep 2010

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 <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 //=============================================================================

Generated at Thu Sep 30 09:57:35 2010 for Gaudi Framework, version v21r11 by Doxygen version 1.5.6 written by Dimitri van Heesch, © 1997-2004