00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00036 #include "OW_config.h"
00037 #include "OW_CIMDateTime.hpp"
00038 #include "OW_DateTime.hpp"
00039 #include "OW_String.hpp"
00040 #include "OW_BinarySerialization.hpp"
00041 #include "OW_StrictWeakOrdering.hpp"
00042 #include "OW_COWIntrusiveCountableBase.hpp"
00043 #include "OW_ExceptionIds.hpp"
00044 #include "OW_Assertion.hpp"
00045 
00046 #include <cstdio>
00047 #if defined(OW_HAVE_ISTREAM) && defined(OW_HAVE_OSTREAM)
00048 #include <istream>
00049 #include <ostream>
00050 #else
00051 #include <iostream>
00052 #endif
00053 
00054 namespace OW_NAMESPACE
00055 {
00056 
00057 using std::ostream;
00058 using std::istream;
00059 
00060 OW_DEFINE_EXCEPTION_WITH_ID(CIMDateTime);
00061 
00063 struct CIMDateTime::DateTimeData : public COWIntrusiveCountableBase
00064 {
00065    DateTimeData() :
00066       m_year(0), m_month(0), m_days(0), m_hours(0),
00067       m_minutes(0), m_seconds(0), m_microSeconds(0), m_utc(0),
00068       m_isInterval(1) {}
00069 
00070    UInt16 m_year;
00071    UInt8 m_month;
00072    UInt32 m_days;
00073    UInt8 m_hours;
00074    UInt8 m_minutes;
00075    UInt8 m_seconds;
00076    UInt32 m_microSeconds;
00077    Int16 m_utc;
00078    UInt8 m_isInterval;
00079    DateTimeData* clone() const { return new DateTimeData(*this); }
00080 };
00081 
00082 
00083 static void fillDateTimeData(CIMDateTime::DateTimeData& data, const char* str);
00085 CIMDateTime::CIMDateTime()
00086    : m_dptr(new DateTimeData)
00087 {
00088 }
00090 CIMDateTime::~CIMDateTime()
00091 {
00092 }
00094 CIMDateTime::CIMDateTime(CIMNULL_t)
00095    : m_dptr(0)
00096 {
00097 }
00099 CIMDateTime::CIMDateTime(const CIMDateTime& arg)
00100    : m_dptr(arg.m_dptr)
00101 {
00102 }
00104 CIMDateTime::CIMDateTime(const String& arg) :
00105    m_dptr(new DateTimeData)
00106 {
00107    fillDateTimeData(*m_dptr, arg.c_str());
00108 }
00110 CIMDateTime::CIMDateTime(const DateTime& arg) :
00111    m_dptr(new DateTimeData)
00112 {
00113    struct tm t_loc;
00114    m_dptr->m_isInterval = 0;
00115    m_dptr->m_utc = arg.toLocal(t_loc);
00116    m_dptr->m_year = t_loc.tm_year + 1900;
00117    m_dptr->m_month = t_loc.tm_mon + 1;
00118    m_dptr->m_days = t_loc.tm_mday;
00119    m_dptr->m_hours = t_loc.tm_hour;
00120    m_dptr->m_minutes = t_loc.tm_min;
00121    m_dptr->m_seconds = t_loc.tm_sec;
00122    m_dptr->m_microSeconds = arg.getMicrosecond();
00123 }
00125 CIMDateTime::CIMDateTime(UInt64 microSeconds) :
00126    m_dptr(new DateTimeData)
00127 {
00128    m_dptr->m_isInterval = 1;
00129    UInt32 secs = microSeconds / 1000000ULL;
00130    microSeconds -= secs * 1000000;
00131    UInt32 minutes = secs / 60;
00132    secs -= minutes * 60;
00133    UInt32 hours = minutes / 60;
00134    minutes -= hours * 60;
00135    UInt32 days = hours / 24;
00136    hours -= days * 24;
00137    m_dptr->m_days = days;
00138    m_dptr->m_hours = hours;
00139    m_dptr->m_minutes = minutes;
00140    m_dptr->m_seconds = secs;
00141    m_dptr->m_microSeconds = microSeconds;
00142 }
00144 CIMDateTime&
00145 CIMDateTime::operator= (const CIMDateTime& arg)
00146 {
00147    m_dptr = arg.m_dptr;
00148    return *this;
00149 }
00151 CIMDateTime::operator CIMDateTime::safe_bool() const
00152 {
00153    if (m_dptr)
00154    {
00155       return (m_dptr->m_days != 0
00156          || m_dptr->m_year != 0
00157          || m_dptr->m_month != 0
00158          || m_dptr->m_hours != 0
00159          || m_dptr->m_minutes != 0
00160          || m_dptr->m_seconds != 0
00161          || m_dptr->m_microSeconds != 0) ?
00162          &CIMDateTime::m_dptr : 0;
00163    }
00164    return 0;
00165 }
00167 bool
00168 CIMDateTime::operator !() const
00169 {
00170    if (m_dptr)
00171    {
00172       return (m_dptr->m_days == 0
00173          && m_dptr->m_year == 0
00174          && m_dptr->m_month == 0
00175          && m_dptr->m_hours == 0
00176          && m_dptr->m_minutes == 0
00177          && m_dptr->m_seconds == 0
00178          && m_dptr->m_microSeconds == 0);
00179    }
00180    return true;
00181 }
00183 CIMDateTime&
00184 CIMDateTime::setYear(UInt16 arg)
00185 {
00186    m_dptr->m_year = arg;
00187    return *this;
00188 }
00190 CIMDateTime&
00191 CIMDateTime::setMonth(UInt8 arg)
00192 {
00193    m_dptr->m_month = arg;
00194    return *this;
00195 }
00197 CIMDateTime&
00198 CIMDateTime::setDays(UInt32 arg)
00199 {
00200    m_dptr->m_days = arg;
00201    return *this;
00202 }
00204 CIMDateTime&
00205 CIMDateTime::setDay(UInt32 arg)
00206 {
00207    m_dptr->m_days = arg;
00208    return *this;
00209 }
00211 CIMDateTime&
00212 CIMDateTime::setHours(UInt8 arg)
00213 {
00214    m_dptr->m_hours = arg;
00215    return *this;
00216 }
00218 CIMDateTime&
00219 CIMDateTime::setMinutes(UInt8 arg)
00220 {
00221    m_dptr->m_minutes = arg;
00222    return *this;
00223 }
00225 CIMDateTime&
00226 CIMDateTime::setSeconds(UInt8 arg)
00227 {
00228    m_dptr->m_seconds = arg;
00229    return *this;
00230 }
00232 CIMDateTime&
00233 CIMDateTime::setMicroSeconds(UInt32 arg)
00234 {
00235    m_dptr->m_microSeconds = arg;
00236    return *this;
00237 }
00239 CIMDateTime&
00240 CIMDateTime::setUtc(Int16 arg)
00241 {
00242    m_dptr->m_utc = arg;
00243    return *this;
00244 }
00246 bool
00247 CIMDateTime::equal(const CIMDateTime& arg) const
00248 {
00249    return (
00250       m_dptr->m_year == arg.m_dptr->m_year &&
00251       m_dptr->m_month == arg.m_dptr->m_month &&
00252       m_dptr->m_days == arg.m_dptr->m_days &&
00253       m_dptr->m_hours == arg.m_dptr->m_hours &&
00254       m_dptr->m_minutes == arg.m_dptr->m_minutes &&
00255       m_dptr->m_seconds == arg.m_dptr->m_seconds &&
00256       m_dptr->m_microSeconds == arg.m_dptr->m_microSeconds &&
00257       m_dptr->m_utc == arg.m_dptr->m_utc &&
00258       m_dptr->m_isInterval == arg.m_dptr->m_isInterval);
00259    
00260 }
00262 void
00263 CIMDateTime::readObject(istream &istrm)
00264 {
00265    DateTimeData dtdata;
00266 
00267    BinarySerialization::read(istrm, dtdata.m_year);
00268    BinarySerialization::read(istrm, dtdata.m_month);
00269    BinarySerialization::read(istrm, dtdata.m_days);
00270    BinarySerialization::read(istrm, dtdata.m_hours);
00271    BinarySerialization::read(istrm, dtdata.m_minutes);
00272    BinarySerialization::read(istrm, dtdata.m_seconds);
00273    BinarySerialization::read(istrm, dtdata.m_microSeconds);
00274    BinarySerialization::read(istrm, dtdata.m_utc);
00275    BinarySerialization::read(istrm, dtdata.m_isInterval);
00276 
00277    if (!m_dptr)
00278    {
00279       m_dptr = new DateTimeData;
00280    }
00281    *m_dptr = dtdata;
00282 }
00284 void
00285 CIMDateTime::writeObject(ostream &ostrm) const
00286 {
00287    BinarySerialization::write(ostrm, m_dptr->m_year);
00288    BinarySerialization::write(ostrm, m_dptr->m_month);
00289    BinarySerialization::write(ostrm, m_dptr->m_days);
00290    BinarySerialization::write(ostrm, m_dptr->m_hours);
00291    BinarySerialization::write(ostrm, m_dptr->m_minutes);
00292    BinarySerialization::write(ostrm, m_dptr->m_seconds);
00293    BinarySerialization::write(ostrm, m_dptr->m_microSeconds);
00294    BinarySerialization::write(ostrm, m_dptr->m_utc);
00295    BinarySerialization::write(ostrm, m_dptr->m_isInterval);
00296 
00297 }
00299 String
00300 CIMDateTime::toString() const
00301 {
00302    char bfr[30];
00303    if (isInterval())
00304    {
00305       
00306       ::sprintf(bfr, "%08u%02u%02u%02u.%06u:000", m_dptr->m_days,
00307          m_dptr->m_hours, m_dptr->m_minutes, m_dptr->m_seconds,
00308          m_dptr->m_microSeconds);
00309    }
00310    else
00311    {
00312       
00313       ::sprintf(bfr, "%04u%02u%02u%02u%02u%02u.%06u%+04d", m_dptr->m_year,
00314          m_dptr->m_month, m_dptr->m_days, m_dptr->m_hours, m_dptr->m_minutes,
00315          m_dptr->m_seconds, m_dptr->m_microSeconds, m_dptr->m_utc);
00316    }
00317    return String(bfr);
00318 }
00320 DateTime
00321 CIMDateTime::toDateTime() const
00322 {
00323    return DateTime(toString());
00324 }
00326 static void
00327 fillDateTimeData(CIMDateTime::DateTimeData& data, const char* str)
00328 {
00329    if (str == NULL || *str == '\0')
00330    {
00331       return;
00332    }
00333    char bfr[35];
00334    ::strncpy(bfr, str, sizeof(bfr));
00335    bfr[34] = '\0';
00336    if (bfr[21] == ':')  
00337    {
00338       
00339       data.m_isInterval = 1;
00340       bfr[21] = 0;
00341       data.m_microSeconds = atoi(&bfr[15]);
00342       bfr[14] = 0;
00343       data.m_seconds = atoi(&bfr[12]);
00344       bfr[12] = 0;
00345       data.m_minutes = atoi(&bfr[10]);
00346       bfr[10] = 0;
00347       data.m_hours = atoi(&bfr[8]);
00348       bfr[8] = 0;
00349       data.m_days = atoi(bfr);
00350    }
00351    else if (bfr[21] == '+' || bfr[21] == '-')
00352    {
00353       
00354       data.m_isInterval = 0;
00355       data.m_utc = atoi(&bfr[21]);
00356       bfr[21] = 0;
00357       data.m_microSeconds = atoi(&bfr[15]);
00358       bfr[14] = 0;
00359       data.m_seconds = atoi(&bfr[12]);
00360       bfr[12] = 0;
00361       data.m_minutes = atoi(&bfr[10]);
00362       bfr[10] = 0;
00363       data.m_hours = atoi(&bfr[8]);
00364       bfr[8] = 0;
00365       data.m_days = atoi(&bfr[6]);
00366       bfr[6] = 0;
00367       data.m_month = atoi(&bfr[4]);
00368       bfr[4] = 0;
00369       data.m_year = atoi(bfr);
00370    }
00371    else
00372    {
00373       OW_THROW_ERR(CIMDateTimeException, "Invalid format for date time", CIMDateTime::E_INVALID_DATE_TIME_FORMAT);
00374    }
00375 }
00377 ostream&
00378 operator<< (ostream& ostr, const CIMDateTime& arg)
00379 {
00380    ostr << arg.toString();
00381    return ostr;
00382 }
00383 
00385 UInt16
00386 CIMDateTime::getYear() const {  return m_dptr->m_year; }
00388 UInt8
00389 CIMDateTime::getMonth() const {  return m_dptr->m_month; }
00391 UInt32
00392 CIMDateTime::getDays() const {  return m_dptr->m_days; }
00394 UInt32
00395 CIMDateTime::getDay() const {  return m_dptr->m_days; }
00397 UInt8
00398 CIMDateTime::getHours() const {  return m_dptr->m_hours; }
00400 UInt8
00401 CIMDateTime::getMinutes() const {  return m_dptr->m_minutes; }
00403 UInt8
00404 CIMDateTime::getSeconds() const {  return m_dptr->m_seconds; }
00406 UInt32
00407 CIMDateTime::getMicroSeconds() const {  return m_dptr->m_microSeconds; }
00409 Int16
00410 CIMDateTime::getUtc() const {  return m_dptr->m_utc; }
00412 bool
00413 CIMDateTime::isInterval() const {  return m_dptr->m_isInterval != 0;}
00415 void
00416 CIMDateTime::setInterval(bool val) { m_dptr->m_isInterval = val; }
00417 
00419 bool operator==(const CIMDateTime& x, const CIMDateTime& y)
00420 {
00421    return x.equal(y);
00422 }
00424 namespace
00425 {
00426 
00427    
00428    inline bool isLeap(UInt16 year)
00429    {
00430       return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
00431    }
00432 
00433    
00434    const unsigned short int monthYearDay[2][13] =
00435    {
00436       
00437       { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
00438       
00439       { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
00440    };
00441 
00442    
00443    
00444    
00445    Int64 getMagnitude(const CIMDateTime& dt)
00446    {
00447       OW_ASSERT(!dt.isInterval());
00448 
00449       
00450       if (dt.getMonth() > 12)
00451       {
00452          return 0; 
00453       }
00454 
00455       const int EPOCH_YEAR = 1970;
00456 
00457       int dayOfYear = monthYearDay[isLeap(dt.getYear())][dt.getMonth() - 1] + dt.getDay() - 1;
00458       int days = 366 * (dt.getYear() - EPOCH_YEAR) + dayOfYear; 
00459       return dt.getSeconds()
00460          + 60 * (dt.getMinutes() + dt.getUtc())
00461          + 3600 * static_cast<Int64>(dt.getHours() + 24 * days);
00462    }
00463 }
00465 bool operator<(const CIMDateTime& x, const CIMDateTime& y)
00466 {
00467    
00468    if (x.isInterval() ^ y.isInterval())
00469    {
00470       
00471       return x.isInterval();
00472    }
00473    else
00474    {
00475       if (x.isInterval())
00476       {
00477          
00478          return StrictWeakOrdering(
00479             x.getDays(), y.getDays(),
00480             x.getHours(), y.getHours(),
00481             x.getMinutes(), y.getMinutes(),
00482             x.getSeconds(), y.getSeconds(),
00483             x.getMicroSeconds(), y.getMicroSeconds());
00484       }
00485       else
00486       {
00487          
00488          return StrictWeakOrdering(
00489             getMagnitude(x), getMagnitude(y),
00490             x.getMicroSeconds(), y.getMicroSeconds());
00491       }
00492    }
00493 
00494 }
00495 
00497 bool operator!=(const CIMDateTime& x, const CIMDateTime& y)
00498 {
00499    return !(x == y);
00500 }
00501 
00503 bool operator>(const CIMDateTime& x, const CIMDateTime& y)
00504 {
00505    return y < x;
00506 }
00507 
00509 bool operator<=(const CIMDateTime& x, const CIMDateTime& y)
00510 {
00511    return !(y < x);
00512 }
00513 
00515 bool operator>=(const CIMDateTime& x, const CIMDateTime& y)
00516 {
00517    return !(x < y);
00518 }
00519 
00520 } 
00521