// use this call, only if the DateTime object has a timezone // ie tzAvailable() == true void DateTime::makeUTC() { if(!tzAvailable()) { throw DateTimeException("timezone information not available for the conversion"); } operator -= (_tz); _tz = TimeZone(0,0); }
// use this call, only if the DateTime object does not have a timezone // ie tzAvailable() == false void DateTime::makeUTC(TimeZone tz) { if(tzAvailable() && (_tz != tz) ) { ostringstream oss; oss << "DateTime object already has a timezone" << " which does not not match with supplied timezone"; throw DateTimeException(oss.str()); } operator -= (tz); _tz = TimeZone(0,0); }
time_t timegm2(struct tm *tm) { struct tm tm2, tm3; time_t t; tm2 = *tm; t = mktime(&tm2); tm3 = *localtime(&t); tm2 = *tm; tm2.tm_isdst = tm3.tm_isdst; t = mktime(&tm2); t -= TimeZone(t); return t; }
namespace XPlus { // // Timezones currently in use, could vary from +12:00 to -13:00. // It is, however, possible for this range to expand or contract in the // future, based on local laws. // const TimeZone DateTime::UTC_TZ = TimeZone(); //FIXME const TimeZone DateTime::UNKNOWN_TZ = TimeZone(24, 0); const int DateTime::UNSPECIFIED = -9999; //FIXME const int DateTime::INDETERMINATE = 2; // [0, ] const int DateTime::MIN_VALID_YEAR = 1; const int DateTime::MAX_VALID_YEAR = 99999; //FIXME // [1,12] const int DateTime::MIN_VALID_MONTH = 1; const int DateTime::MAX_VALID_MONTH = 12; // [1,31] const int DateTime::MIN_VALID_DAY = 1; const int DateTime::MAX_VALID_DAY = 31; // [0,24] const int DateTime::MIN_VALID_HOUR = 0 ; const int DateTime::MAX_VALID_HOUR = 24 ; // [0,59] const int DateTime::MIN_VALID_MINUTE = 0; const int DateTime::MAX_VALID_MINUTE = 59; // [0,60] const int DateTime::MIN_VALID_SECOND = 0; const int DateTime::MAX_VALID_SECOND = 60; // [0,14]:[0:60] const int DateTime::MAX_VALID_TZ_HOUR = 14; const std::string DateTime::ISO8601_FORMAT = "%Y-%m-%dT%H:%M:%s%z"; const std::string DateTime::XSD_DATE_FORMAT = "%Y-%m-%d%z"; const std::string DateTime::XSD_DAY_FORMAT = "%d%z"; const std::string DateTime::XSD_MONTH_FORMAT = "%m%z"; const std::string DateTime::XSD_MONTHDAY_FORMAT = "%m-%d%z"; const std::string DateTime::XSD_YEARMONTH_FORMAT = "%Y-%m%z"; const std::string DateTime::XSD_TIME_FORMAT = "%H:%M:%s%z"; const std::string DateTime::XSD_DURATION_FORMAT = "P%YY%mM%dDT%HH%MM%sS"; //PnYnMnDTnHnMnS DateTime::DateTime(int year, int month, int day, int hour, int minute, double second, TimeZone tz): _year (year), _month (month), _day (day), _hour (hour), _minute (minute), _second (second), _tz(tz) { if(!DateAlgo::isValidDateTime(year, month, day, hour, minute, second, tz)) { ostringstream oss; oss << "Invalid date:" << " year:" << year << " month:" << month << " day:" << day << " hour:" << hour << " minute:" << minute << " second:" << second; throw DateTimeException(oss.str()); } } DateTime& DateTime::assign_nochecks(int year, int month, int day, int hour, int minute, double second, TimeZone tz) { _year = year; _month = month; _day = day; _hour = hour; _minute = minute; _second = second; _tz = tz; return *this; } DateTime& DateTime::assign(int year, int month, int day, int hour, int minute, double second, TimeZone tz) { if(!DateAlgo::isValidDateTime(year, month, day, hour, minute, second, tz)) { ostringstream oss; oss << "Invalid date:" << " year:" << year << " month:" << month << " day:" << day << " hour:" << hour << " minute:" << minute << " second:" << second; throw DateTimeException(oss.str()); } _year = year; _month = month; _day = day; _hour = hour; _minute = minute; _second = second; _tz = tz; return *this; } DateTime::DateTime(const DateTime& dateTime): _year(dateTime._year), _month(dateTime._month), _day(dateTime._day), _hour(dateTime._hour), _minute(dateTime._minute), _second(dateTime._second), _tz(dateTime._tz) { } DateTime::~DateTime() { } DateTime& DateTime::operator = (const DateTime& dateTime) { if (&dateTime != this) { _year = dateTime._year; _month = dateTime._month; _day = dateTime._day; _hour = dateTime._hour; _minute = dateTime._minute; _second = dateTime._second; _tz = dateTime._tz; } return *this; } /* double DateTime::toSeconds() { return toSeconds(_year, _month, _day, _hour, _minute, _second); } */ // use this call, only if the DateTime object has a timezone // ie tzAvailable() == true void DateTime::makeUTC() { if(!tzAvailable()) { throw DateTimeException("timezone information not available for the conversion"); } operator -= (_tz); _tz = TimeZone(0,0); } // use this call, only if the DateTime object does not have a timezone // ie tzAvailable() == false void DateTime::makeUTC(TimeZone tz) { if(tzAvailable() && (_tz != tz) ) { ostringstream oss; oss << "DateTime object already has a timezone" << " which does not not match with supplied timezone"; throw DateTimeException(oss.str()); } operator -= (tz); _tz = TimeZone(0,0); } // this call will fail, if the DateTime is already local ie tzAvailable()==true void DateTime::makeLocal(TimeZone tz) { if(!isUTC()) { ostringstream oss; oss << "DateTime object is already local "; throw DateTimeException(oss.str()); } operator +=(tz); _tz = tz; } int DateTime::dayOfYear() const { int doy = 0; for (int month = 1; month < _month; ++month) doy += maximumDayInMonthFor(_year, month); doy += _day; return doy; } DateTime& DateTime::operator += (const Duration& d) { int e_year=0, e_month=0, e_day=0; int e_hour=0, e_minute=0; double e_second=0; TimeZone e_zone; datetime_plus_duration(*this, d, e_year, e_month, e_day, e_hour, e_minute, e_second, e_zone); this->assign(e_year, e_month, e_day, e_hour, e_minute, e_second, e_zone); return *this; } DateTime& DateTime::operator -= (const Duration& d) { return operator +=(-d); } bool DateTime::operator == (const DateTime& dt) const { int result = DateAlgo::cmp(*this, dt); if(result == INDETERMINATE) { throw DateTimeException("INDETERMINATE DateTime == comparison"); } return (result == 0); } bool DateTime::operator != (const DateTime& dt) const { return !operator==(dt); } bool DateTime::operator < (const DateTime& dt) const { int result = DateAlgo::cmp(*this, dt); if(result == INDETERMINATE) { throw DateTimeException("INDETERMINATE DateTime < comparison"); } return (result == -1); } bool DateTime::operator <= (const DateTime& dt) const { int result = DateAlgo::cmp(*this, dt); if(result == INDETERMINATE) { throw DateTimeException("INDETERMINATE DateTime <= comparison"); } return ((result == -1) || (result == 0)); } bool DateTime::operator > (const DateTime& dt) const { int result = DateAlgo::cmp(*this, dt); if(result == INDETERMINATE) { throw DateTimeException("INDETERMINATE DateTime > comparison"); } return (result == 1); } bool DateTime::operator >= (const DateTime& dt) const { int result = DateAlgo::cmp(*this, dt); if(result == INDETERMINATE) { throw DateTimeException("INDETERMINATE DateTime >= comparison"); } return ((result == 1) || (result == 0)); } } // namespace XPlus
int TimeZone::parse( char const *s, size_t s_len, TimeZone *tz ) { s = ascii::trim_space( s, &s_len ); char const *const end = s + s_len; if ( s == end ) // string was entirely whitespace return 1; // // Ibid: The lexical representation of a timezone is a string of the form: // (('+' | '-') hh ':' mm) | 'Z'. // if ( *s == 'Z' ) { if ( ++s != end ) return 1; *tz = TimeZone( 0 ); } else { if ( end - s != 6 ) // need exactly 6 characters return 1; bool negative = false; switch ( *s ) { case '-': negative = true; // no break; case '+': try { if ( !ascii::is_digit( *++s ) ) return 1; int hours = (int)ztd::aton<unsigned>( s, end, &s ); if ( end - s != 3 || *s != ':' || !ascii::is_digit( *++s ) ) return 1; int minutes = (int)ztd::aton<unsigned>( s, end, &s ); if ( s != end ) return 1; if ( negative ) { if ( hours ) hours = -hours; else minutes = -minutes; } *tz = TimeZone( hours, minutes ); } catch ( std::exception const& ) { // // IMHO, using error codes is terrible, especially when C++ supports // exceptions; but the original code returned error codes so we're // forced to return them as well (otherwise more chunks of code would // have to be rewritten to catch exceptions). Perhaps a future // clean-up will fix this. // // That aside, the original code didn't even use error code well in // that this function returned '1' for all errors rather than // something more sensible like returning different error codes for // "syntax error" vs "range error." // return 1; } break; default: return 1; } } return 0; }