00001
00002
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
00014 using namespace Gaudi;
00015
00016
00017 #ifdef WIN32
00018
00019
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
00042
00043 #include <sys/time.h>
00044
00045 #endif
00046
00047
00048
00049
00050
00051
00052
00053 #ifdef WIN32
00054
00063
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
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
00080
00081 Time::Time( int year, int month, int day,
00082 int hour, int min, int sec,
00083 ValueType nsecs,
00084 bool local ) {
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;
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
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 ) {
00138 tm tmp (base);
00139 return Time (local ? mktime(&tmp) : timegm(&tmp), 0) + diff;
00140 }
00141
00146 tm Time::split (bool local, int *nsecpart ) 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 ) const {
00165 return split (false, nsecpart);
00166 }
00167
00171 tm Time::local (int *nsecpart ) 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 ) 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
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
00258
00259 #pragma warning(push)
00260 #pragma warning(disable:4996)
00261 #endif
00262
00266 const char * Time::timezone (int *daylight ) const {
00267 tm localtm = local ();
00268 if (daylight) *daylight = localtm.tm_isdst;
00269
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
00287 std::string::size_type pos = spec.find("%f");
00288 if (std::string::npos != pos) {
00289
00290 std::string ms = nanoformat(3,3);
00291
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);
00297 }
00298 }
00299 const int MIN_BUF_SIZE = 128;
00300 do
00301 {
00302
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 , size_t maxwidth ) const {
00324 TimeAssert( (minwidth >= 1) && (minwidth <= maxwidth) && (maxwidth <= 9),
00325 "nanoformat options do not satisfy: 1 <= minwidth <= maxwidth <= 9");
00326
00327
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
00336
00337
00338 size_t len = out.find_last_not_of('0', maxwidth - 1) + 1;
00339
00340 out.resize(std::max(len, minwidth));
00341 return out;
00342 }
00343
00345
00346 unsigned Time::toDosDate (Time time) {
00347
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
00363
00364
00365
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