| # Gaudi Framework, version v21r7 |

Home |  | Generated: 22 Jan 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 //=============================================================================