OW_CIMDateTime.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
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       // Interval format
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       // Date/Time format
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] == ':')  // Is this an interval
00337    {
00338       // ddddddddhhmmss.mmmmmm:000
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       // yyyymmddhhmmss.mmmmmmsutc
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    // Nonzero if YEAR is a leap year (every 4 years, except every 100th isn't, and every 400th is).
00428    inline bool isLeap(UInt16 year)
00429    {
00430       return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
00431    }
00432 
00433    // How many days come before each month (0-12).
00434    const unsigned short int monthYearDay[2][13] =
00435    {
00436       // Normal years.
00437       { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
00438       // Leap years.
00439       { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
00440    };
00441 
00442    // This doesn't return the exact number of seconds, since it assumes all previous years are 366 days long,
00443    // In essense we're introducing some empty space in the range of this function, but that's good enough to
00444    // use in comparing dates.
00445    Int64 getMagnitude(const CIMDateTime& dt)
00446    {
00447       OW_ASSERT(!dt.isInterval());
00448 
00449       // only check the month, we don't check the rest since it won't cause a crash...
00450       if (dt.getMonth() > 12)
00451       {
00452          return 0; // invalid month would cause an access violation.
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; // leap years are accounted for by 366 instead of 365.
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    // see if they both the same type (intervals or date/times) or are different types.
00468    if (x.isInterval() ^ y.isInterval())
00469    {
00470       // they're different.  We define an interval to be < a date/time
00471       return x.isInterval();
00472    }
00473    else
00474    {
00475       if (x.isInterval())
00476       {
00477          // both intervals
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          // they're both date/times
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 } // end namespace OW_NAMESPACE
00521 

Generated on Thu Feb 9 08:47:53 2006 for openwbem by  doxygen 1.4.6