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