Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:23:13

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