Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:32:10

0001 #include <ctime>
0002 #include <iostream>
0003 #include <string>
0004 #include <stdexcept>
0005 #include <cmath>
0006 #include <cstdio>
0007 
0008 #include "OnlineDB/EcalCondDB/interface/Tm.h"
0009 
0010 using namespace std;
0011 
0012 /**
0013  * GO: the maximum UNIX time is restricted to INT_MAX, corresponding to
0014  *     2038-01-19 03:14:07. Take it into account in str()
0015  * 
0016  */
0017 
0018 std::ostream &operator<<(std::ostream &out, const Tm &t) {
0019   out << t.str();
0020   return out;
0021 }
0022 
0023 // Default Constructor
0024 Tm::Tm() { this->setNull(); }
0025 
0026 // Initialized Constructor
0027 Tm::Tm(struct tm *initTm) { m_tm = *initTm; }
0028 
0029 Tm::Tm(uint64_t micros) {
0030   this->setNull();
0031   if (micros > PLUS_INF_MICROS) {
0032     //micros = PLUS_INF_MICROS;
0033     this->setToCmsNanoTime(micros);
0034   } else {
0035     this->setToMicrosTime(micros);
0036   }
0037 }
0038 
0039 // Destructor
0040 Tm::~Tm() {}
0041 
0042 struct tm Tm::c_tm() const {
0043   return m_tm;
0044 }
0045 
0046 int Tm::isNull() const {
0047   if (m_tm.tm_year == 0 && m_tm.tm_mon == 0 && m_tm.tm_mday == 0) {
0048     return 1;
0049   } else {
0050     return 0;
0051   }
0052 }
0053 
0054 void Tm::setNull() {
0055   m_tm.tm_hour = 0;
0056   m_tm.tm_isdst = 0;
0057   m_tm.tm_mday = 0;
0058   m_tm.tm_min = 0;
0059   m_tm.tm_mon = 0;
0060   m_tm.tm_sec = 0;
0061   m_tm.tm_wday = 0;
0062   m_tm.tm_yday = 0;
0063   m_tm.tm_year = 0;
0064 }
0065 
0066 string Tm::str() const {
0067   if (this->isNull()) {
0068     return "";
0069   }
0070 
0071   /** 
0072    *   \brief "One hour shif" fix
0073    *   Create a temporary dummy object that is in GMT and use it 
0074    *   to generate the output. This is to avoid the "one hour 
0075    *   shift" related to the Summer time and the value of 
0076    *   m_tm.tm_isdst, see [1].  It guaranties that the output
0077    *   is always in GMT / UTC.
0078    *   [1] https://hypernews.cern.ch/HyperNews/CMS/get/ecalDB/66.html
0079    */
0080   char timebuf[20] = "";
0081   if (this->microsTime() >= PLUS_INF_MICROS) {
0082     sprintf(timebuf, "9999-12-12 23:59:59");
0083   } else {
0084     Tm dummy_Tm;
0085     dummy_Tm.setToGMTime(this->microsTime() / 1000000);
0086     struct tm dummy_tm = dummy_Tm.c_tm();
0087     strftime(timebuf, 20, "%Y-%m-%d %H:%M:%S", &dummy_tm);
0088   }
0089   return string(timebuf);
0090 }
0091 
0092 uint64_t Tm::cmsNanoSeconds() const { return microsTime() / 1000000 << 32; }
0093 
0094 uint64_t Tm::unixTime() const { return microsTime() / 1000000; }
0095 
0096 uint64_t Tm::microsTime() const {
0097   uint64_t result = 0;
0098   /*  
0099   result += (uint64_t)ceil((m_tm.tm_year - 70 ) * 365.25) * 24 * 3600;
0100   result += (m_tm.tm_yday) * 24 * 3600;
0101   result += m_tm.tm_hour * 3600;
0102   result += m_tm.tm_min * 60;
0103   result += m_tm.tm_sec;
0104   return (uint64_t) (result * 1000000);
0105   */
0106 
0107   struct tm time_struct;
0108   time_struct.tm_year = 1970 - 1900;
0109   time_struct.tm_mon = 0;
0110   time_struct.tm_mday = 1;
0111   time_struct.tm_sec = 0;
0112   time_struct.tm_min = 0;
0113   time_struct.tm_hour = 0;
0114   time_struct.tm_isdst = 0;
0115 
0116   time_t t1970 = mktime(&time_struct);
0117   tm s = m_tm;
0118   time_t t_this = mktime(&s);
0119 
0120   double x = difftime(t_this, t1970);
0121   result = (uint64_t)x * 1000000;
0122 
0123   return result;
0124 }
0125 
0126 void Tm::setToCmsNanoTime(uint64_t nanos) { setToMicrosTime((nanos >> 32) * 1000000); }
0127 
0128 void Tm::setToMicrosTime(uint64_t micros) {
0129   time_t t = micros / 1000000;
0130   if (t >= INT_MAX) {
0131     t = INT_MAX;
0132   }
0133   m_tm = *gmtime(&t);
0134 }
0135 
0136 void Tm::setToCurrentLocalTime() {
0137   time_t t = time(nullptr);
0138   m_tm = *localtime(&t);
0139 }
0140 
0141 void Tm::setToCurrentGMTime() {
0142   time_t t = time(nullptr);
0143   m_tm = *gmtime(&t);
0144 }
0145 
0146 void Tm::setToLocalTime(time_t t) { m_tm = *localtime(&t); }
0147 
0148 void Tm::setToGMTime(time_t t) { m_tm = *gmtime(&t); }
0149 
0150 void Tm::setToString(const string s) noexcept(false) {
0151   sscanf(s.c_str(),
0152          "%04d-%02d-%02d %02d:%02d:%02d",
0153          &m_tm.tm_year,
0154          &m_tm.tm_mon,
0155          &m_tm.tm_mday,
0156          &m_tm.tm_hour,
0157          &m_tm.tm_min,
0158          &m_tm.tm_sec);
0159 
0160   try {
0161     if (m_tm.tm_year > 9999 || m_tm.tm_year < 1900) {
0162       throw(std::runtime_error("Year out of bounds"));
0163     } else if (m_tm.tm_mon > 12 || m_tm.tm_mon < 1) {
0164       throw(std::runtime_error("Month out of bounds"));
0165     } else if (m_tm.tm_mday > 31 || m_tm.tm_mday < 1) {
0166       throw(std::runtime_error("Day out of bounds"));
0167     } else if (m_tm.tm_hour > 23 || m_tm.tm_mday < 0) {
0168       throw(std::runtime_error("Hour out of bounds"));
0169     } else if (m_tm.tm_min > 59 || m_tm.tm_min < 0) {
0170       throw(std::runtime_error("Minute out of bounds"));
0171     } else if (m_tm.tm_sec > 59 || m_tm.tm_sec < 0) {
0172       throw(std::runtime_error("Day out of bounds"));
0173     }
0174 
0175     if (m_tm.tm_year >= 2038) {
0176       // take into account UNIX time limits
0177       m_tm.tm_year = 2038;
0178       if (m_tm.tm_mon > 1) {
0179         m_tm.tm_mon = 1;
0180       }
0181       if (m_tm.tm_mday > 19) {
0182         m_tm.tm_mday = 19;
0183       }
0184       if (m_tm.tm_hour > 3) {
0185         m_tm.tm_hour = 3;
0186       }
0187       if (m_tm.tm_min > 14) {
0188         m_tm.tm_min = 14;
0189       }
0190       if (m_tm.tm_sec > 7) {
0191         m_tm.tm_sec = 7;
0192       }
0193     }
0194     m_tm.tm_year -= 1900;
0195     m_tm.tm_mon -= 1;
0196   } catch (std::runtime_error &e) {
0197     this->setNull();
0198     string msg("Tm::setToString():  ");
0199     msg.append(e.what());
0200     throw(std::runtime_error(msg));
0201   }
0202 }
0203 
0204 void Tm::dumpTm() {
0205   cout << "=== dumpTm() ===" << endl;
0206   cout << "tm_year  " << m_tm.tm_year << endl;
0207   cout << "tm_mon   " << m_tm.tm_mon << endl;
0208   cout << "tm_mday  " << m_tm.tm_mday << endl;
0209   cout << "tm_hour  " << m_tm.tm_hour << endl;
0210   cout << "tm_min   " << m_tm.tm_min << endl;
0211   cout << "tm_sec   " << m_tm.tm_sec << endl;
0212   cout << "tm_yday  " << m_tm.tm_yday << endl;
0213   cout << "tm_wday  " << m_tm.tm_wday << endl;
0214   cout << "tm_isdst " << m_tm.tm_isdst << endl;
0215   cout << "================" << endl;
0216 }