aboutsummaryrefslogtreecommitdiff
path: root/vmime-master/src/vmime/dateTime.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'vmime-master/src/vmime/dateTime.cpp')
-rw-r--r--vmime-master/src/vmime/dateTime.cpp925
1 files changed, 925 insertions, 0 deletions
diff --git a/vmime-master/src/vmime/dateTime.cpp b/vmime-master/src/vmime/dateTime.cpp
new file mode 100644
index 0000000..fd44303
--- /dev/null
+++ b/vmime-master/src/vmime/dateTime.cpp
@@ -0,0 +1,925 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002 Vincent Richard <vincent@vmime.org>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 3 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#include <iomanip>
+
+#include "vmime/config.hpp"
+#include "vmime/dateTime.hpp"
+#include "vmime/platform.hpp"
+#include "vmime/parserHelpers.hpp"
+
+#include "vmime/utility/datetimeUtils.hpp"
+
+
+namespace vmime {
+
+/*
+
+ RFC #822:
+ 5. DATE AND TIME SPECIFICATION
+
+date-time = [ day "," ] date time ; dd mm yy
+ ; hh:mm:ss zzz
+day = "Mon" / "Tue" / "Wed" / "Thu" /
+ "Fri" / "Sat" / "Sun"
+
+date = 1*2DIGIT month 2DIGIT ; day month year
+ ; e.g. 20 Jun 82
+month = "Jan" / "Feb" / "Mar" / "Apr" /
+ "May" / "Jun" / "Jul" / "Aug" /
+ "Sep" / "Oct" / "Nov" / "Dec"
+
+time = hour zone ; ANSI and Military
+
+hour = 2DIGIT ":" 2DIGIT [":" 2DIGIT] ; 00:00:00 - 23:59:59
+
+zone = "UT" / "GMT" ; Universal Time
+ ; North American : UT
+ / "EST" / "EDT" ; Eastern: - 5/ - 4
+ / "CST" / "CDT" ; Central: - 6/ - 5
+ / "MST" / "MDT" ; Mountain: - 7/ - 6
+ / "PST" / "PDT" ; Pacific: - 8/ - 7
+ / 1ALPHA ; Military: Z = UT;
+ ; A:-1; (J not used)
+ ; M:-12; N:+1; Y:+12
+ / ( ("+" / "-") 4DIGIT ) ; Local differential
+ ; hours+min. (HHMM)
+*/
+
+
+void datetime::parseImpl(
+ const parsingContext& /* ctx */,
+ const string& buffer,
+ const size_t position,
+ const size_t end,
+ size_t* newPosition
+) {
+
+ const char* const pend = buffer.data() + end;
+ const char* p = buffer.data() + position;
+
+ // Parse the date and time value
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ if (p < pend) {
+
+ if (parserHelpers::isAlpha(*p)) {
+
+ // Ignore week day
+ while (p < pend && parserHelpers::isAlpha(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ if (p < pend && *p == ',') ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+
+ bool dayParsed = false;
+
+ if (parserHelpers::isAlpha(*p)) {
+
+ // Ill-formed date/time, this may be the month,
+ // so we skip day parsing (will be done later)
+
+ } else {
+
+ while (p < pend && !parserHelpers::isDigit(*p)) ++p;
+
+ if (p < pend && parserHelpers::isDigit(*p)) {
+
+ // Month day
+ int day = 0;
+
+ do {
+ day = day * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ m_day = (day >= 1 && day <= 31) ? day : 1;
+
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ } else {
+
+ m_day = 1;
+
+ // Skip everything to the next field
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+
+ dayParsed = true;
+ }
+
+ if (p < pend && parserHelpers::isAlpha(*p)) {
+
+ // Month
+ char_t month[4] = { 0 };
+ int monthLength = 0;
+
+ do {
+ month[monthLength++] = *p;
+ ++p;
+ } while (monthLength < 3 && p < pend && parserHelpers::isAlpha(*p));
+
+ while (p < pend && parserHelpers::isAlpha(*p)) ++p;
+
+ switch (month[0]) {
+
+ case 'a':
+ case 'A': {
+
+ if (month[1] == 'u' || month[1] == 'U')
+ m_month = AUGUST;
+ else
+ m_month = APRIL; // by default
+
+ break;
+ }
+ case 'd':
+ case 'D': {
+
+ m_month = DECEMBER;
+ break;
+ }
+ case 'f':
+ case 'F': {
+
+ m_month = FEBRUARY;
+ break;
+ }
+ case 'j':
+ case 'J': {
+
+ if (month[1] == 'u' || month[1] == 'U') {
+
+ if (month[2] == 'l' || month[2] == 'L') {
+ m_month = JULY;
+ } else { // if (month[2] == 'n' || month[2] == 'N')
+ m_month = JUNE;
+ }
+
+ } else {
+
+ m_month = JANUARY; // by default
+ }
+
+ break;
+ }
+ case 'm':
+ case 'M': {
+
+ if ((month[1] == 'a' || month[1] == 'A') &&
+ (month[2] == 'y' || month[2] == 'Y')) {
+
+ m_month = MAY;
+
+ } else {
+
+ m_month = MARCH; // by default
+ }
+
+ break;
+ }
+ case 'n':
+ case 'N': {
+
+ m_month = NOVEMBER;
+ break;
+ }
+ case 'o':
+ case 'O': {
+
+ m_month = OCTOBER;
+ break;
+ }
+ case 's':
+ case 'S': {
+
+ m_month = SEPTEMBER;
+ break;
+ }
+ default: {
+
+ m_month = JANUARY; // by default
+ break;
+ }
+ }
+
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ } else {
+
+ m_month = JANUARY;
+
+ if (parserHelpers::isDigit(*p)) {
+
+ // Here, we expected a month, but it maybe
+ // a ill-formed date, so try to parse a year
+ // (we don't skip anything).
+
+ } else {
+
+ // Skip everything to the next field
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+ }
+
+ if (!dayParsed && p < pend && parserHelpers::isDigit(*p)) {
+
+ // Month day
+ int day = 0;
+
+ do {
+ day = day * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ m_day = (day >= 1 && day <= 31) ? day : 1;
+
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+
+ if (p < pend && parserHelpers::isDigit(*p)) {
+
+ // Check for ill-formed date/time and try to recover
+ if (p + 2 < pend && *(p + 2) == ':') {
+
+ // Skip year (default to current), and advance
+ // to time parsing
+ m_year = now().getYear();
+
+ } else {
+
+ // Year
+ int year = 0;
+
+ do {
+ year = year * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ if (year < 70) m_year = year + 2000;
+ else if (year < 1000) m_year = year + 1900;
+ else m_year = year;
+
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+
+ } else {
+
+ m_year = 1970;
+
+ // Skip everything to the next field
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+
+ if (p < pend && parserHelpers::isDigit(*p)) {
+
+ // Hour
+ int hour = 0;
+
+ do {
+ hour = hour * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ m_hour = (hour >= 0 && hour <= 23) ? hour : 0;
+
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ if (p < pend && *p == ':') {
+
+ ++p;
+
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ if (p < pend && parserHelpers::isDigit(*p)) {
+
+ // Minute
+ int minute = 0;
+
+ do {
+ minute = minute * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ m_minute = (minute >= 0 && minute <= 59) ? minute : 0;
+
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ if (p < pend && *p == ':') {
+
+ ++p;
+
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ if (p < pend && parserHelpers::isDigit(*p)) {
+
+ // Second
+ int second = 0;
+
+ do {
+ second = second * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ m_second = (second >= 0 && second <= 59) ? second : 0;
+
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+
+ } else {
+
+ m_second = 0;
+ }
+
+ } else {
+
+ m_second = 0;
+ }
+
+ } else {
+
+ m_minute = 0;
+ }
+
+ } else {
+
+ m_minute = 0;
+ }
+
+ } else {
+
+ m_hour = 0;
+
+ // Skip everything to the next field
+ while (p < pend && !parserHelpers::isSpace(*p)) ++p;
+ while (p < pend && parserHelpers::isSpace(*p)) ++p;
+ }
+
+ if (p + 1 < pend && (*p == '+' || *p == '-') && parserHelpers::isDigit(*(p + 1))) {
+
+ const char_t sign = *p;
+ ++p;
+
+ // Zone offset (in hour/minutes)
+ int offset = 0;
+
+ do {
+ offset = offset * 10 + (*p - '0');
+ ++p;
+ } while (p < pend && parserHelpers::isDigit(*p));
+
+ const int hourOff = offset / 100;
+ const int minOff = offset % 100;
+
+ if (sign == '+') {
+ m_zone = hourOff * 60 + minOff;
+ } else {
+ m_zone = -(hourOff * 60 + minOff);
+ }
+
+ } else if (p < pend && isalpha(*p)) {
+
+ bool done = false;
+
+ // Zone offset (Time zone name)
+ char_t zone[4] = { 0 };
+ int zoneLength = 0;
+
+ do {
+ zone[zoneLength++] = *p;
+ ++p;
+ } while (zoneLength < 3 && p < pend);
+
+ switch (zone[0])
+ {
+ case 'c':
+ case 'C':
+ {
+ if (zoneLength >= 2)
+ {
+ if (zone[1] == 's' || zone[1] == 'S')
+ m_zone = CST;
+ else
+ m_zone = CDT;
+
+ done = true;
+ }
+
+ break;
+ }
+ case 'e':
+ case 'E':
+ {
+ if (zoneLength >= 2) {
+
+ if (zone[1] == 's' || zone[1] == 'S') {
+ m_zone = EST;
+ } else {
+ m_zone = EDT;
+ }
+
+ done = true;
+ }
+
+ break;
+ }
+ case 'm':
+ case 'M': {
+
+ if (zoneLength >= 2) {
+
+ if (zone[1] == 's' || zone[1] == 'S') {
+ m_zone = MST;
+ } else {
+ m_zone = MDT;
+ }
+
+ done = true;
+ }
+
+ break;
+ }
+ case 'p':
+ case 'P': {
+
+ if (zoneLength >= 2) {
+
+ if (zone[1] == 's' || zone[1] == 'S') {
+ m_zone = PST;
+ } else {
+ m_zone = PDT;
+ }
+
+ done = true;
+ }
+
+ break;
+ }
+ case 'g':
+ case 'G':
+ case 'u':
+ case 'U': {
+
+ if (zoneLength >= 2) {
+
+ m_zone = GMT; // = UTC
+ done = true;
+ }
+
+ break;
+ }
+
+ }
+
+ if (!done) {
+
+ const char_t z = zone[0];
+
+ // Military time zone
+ if (z != 'j' && z != 'J') {
+
+ typedef std::map <char_t, int> Map;
+ static const Map::value_type offsetMapInit[] = {
+
+ Map::value_type('a', -60),
+ Map::value_type('b', -120),
+ Map::value_type('c', -180),
+ Map::value_type('d', -240),
+ Map::value_type('e', -300),
+ Map::value_type('f', -360),
+ Map::value_type('g', -420),
+ Map::value_type('h', -480),
+ Map::value_type('i', -540),
+ Map::value_type('k', -600),
+ Map::value_type('l', -660),
+ Map::value_type('m', -720),
+
+ Map::value_type('n', 60),
+ Map::value_type('o', 120),
+ Map::value_type('p', 180),
+ Map::value_type('q', 240),
+ Map::value_type('r', 300),
+ Map::value_type('s', 360),
+ Map::value_type('t', 420),
+ Map::value_type('u', 480),
+ Map::value_type('v', 540),
+ Map::value_type('w', 600),
+ Map::value_type('x', 660),
+ Map::value_type('y', 720),
+
+ Map::value_type('z', 0),
+ };
+
+ static const Map offsetMap(
+ ::vmime::begin(offsetMapInit),
+ ::vmime::end(offsetMapInit)
+ );
+
+ Map::const_iterator pos =
+ offsetMap.find(parserHelpers::toLower(z));
+
+ if (pos != offsetMap.end()) {
+ m_zone = (*pos).second;
+ } else {
+ m_zone = GMT;
+ }
+
+ } else {
+
+ m_zone = GMT;
+ }
+ }
+
+ } else {
+
+ m_zone = 0;
+ }
+
+ } else {
+
+ m_year = 1970;
+ m_month = JANUARY;
+ m_day = 1;
+
+ m_hour = 0;
+ m_minute = 0;
+ m_second = 0;
+
+ m_zone = 0;
+ }
+
+ setParsedBounds(position, end);
+
+ if (newPosition) {
+ *newPosition = end;
+ }
+}
+
+
+void datetime::generateImpl(
+ const generationContext& /* ctx */,
+ utility::outputStream& os,
+ const size_t curLinePos,
+ size_t* newLinePos
+) const {
+
+ static const char* dayNames[] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+ };
+ static const char* monthNames[] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ };
+
+ const int z = ((m_zone < 0) ? -m_zone : m_zone);
+ const int zh = z / 60;
+ const int zm = z % 60;
+
+ std::ostringstream oss;
+ oss.imbue(std::locale::classic());
+
+ oss << dayNames[getWeekDay()] << ", "
+ << m_day << " " << monthNames[m_month - 1] << " " << m_year
+ << " " << std::setfill('0') << std::setw(2) << m_hour << ":"
+ << std::setfill('0') << std::setw(2) << m_minute << ":"
+ << std::setfill('0') << std::setw(2) << m_second
+ << " " << ((m_zone < 0) ? '-' : '+') << std::setfill('0') << std::setw(2) << zh
+ << std::setfill('0') << std::setw(2) << zm;
+
+ const string& str = oss.str();
+ os << str;
+
+ if (newLinePos) {
+ *newLinePos = curLinePos + str.length();
+ }
+}
+
+
+datetime::datetime()
+ : m_year(1970), m_month(1), m_day(1),
+ m_hour(0), m_minute(0), m_second(0), m_zone(0) {
+
+}
+
+
+datetime::datetime(const int year, const int month, const int day)
+ : m_year(year), m_month(month), m_day(day),
+ m_hour(0), m_minute(0), m_second(0), m_zone(0) {
+
+}
+
+
+datetime::datetime(
+ const int year,
+ const int month,
+ const int day,
+ const int hour,
+ const int minute,
+ const int second,
+ const int zone
+)
+ : m_year(year),
+ m_month(month),
+ m_day(day),
+ m_hour(hour),
+ m_minute(minute),
+ m_second(second),
+ m_zone(zone) {
+
+}
+
+
+datetime::datetime(const datetime& d)
+ : headerFieldValue(),
+ m_year(d.m_year),
+ m_month(d.m_month),
+ m_day(d.m_day),
+ m_hour(d.m_hour),
+ m_minute(d.m_minute),
+ m_second(d.m_second),
+ m_zone(d.m_zone) {
+
+}
+
+
+datetime::datetime(const time_t t, const int zone) {
+
+#if VMIME_HAVE_LOCALTIME_S
+
+ struct tm tms;
+
+ if (!gmtime_s(&tms, &t)) {
+ localtime_s(&tms, &t);
+ }
+
+#elif VMIME_HAVE_LOCALTIME_R
+ struct tm tms;
+
+ if (!gmtime_r(&t, &tms)) {
+ localtime_r(&t, &tms);
+ }
+
+#else
+
+ struct tm* gtm = gmtime(&t);
+ struct tm* ltm = localtime(&t);
+
+ struct tm tms;
+
+ if (gtm) {
+ tms = *gtm;
+ } else if (ltm) {
+ tms = *ltm;
+ }
+
+#endif
+
+ m_year = tms.tm_year + 1900;
+ m_month = tms.tm_mon + 1;
+ m_day = tms.tm_mday;
+ m_hour = tms.tm_hour;
+ m_minute = tms.tm_min;
+ m_second = tms.tm_sec;
+ m_zone = zone;
+}
+
+
+datetime::datetime(const string& date) {
+
+ parse(date);
+}
+
+
+datetime::~datetime() {
+
+}
+
+
+void datetime::copyFrom(const component& other) {
+
+ const datetime& d = dynamic_cast <const datetime&>(other);
+
+ m_year = d.m_year;
+ m_month = d.m_month;
+ m_day = d.m_day;
+ m_hour = d.m_hour;
+ m_minute = d.m_minute;
+ m_second = d.m_second;
+ m_zone = d.m_zone;
+}
+
+
+datetime& datetime::operator=(const datetime& other) {
+
+ copyFrom(other);
+ return *this;
+}
+
+
+datetime& datetime::operator=(const string& s) {
+
+ parse(s);
+ return *this;
+}
+
+
+void datetime::getTime(int& hour, int& minute, int& second, int& zone) const {
+
+ hour = m_hour;
+ minute = m_minute;
+ second = m_second;
+ zone = m_zone;
+}
+
+
+void datetime::getTime(int& hour, int& minute, int& second) const {
+
+ hour = m_hour;
+ minute = m_minute;
+ second = m_second;
+}
+
+
+void datetime::getDate(int& year, int& month, int& day) const {
+
+ year = m_year;
+ month = m_month;
+ day = m_day;
+}
+
+
+void datetime::setTime(
+ const int hour,
+ const int minute,
+ const int second,
+ const int zone
+) {
+
+ m_hour = hour;
+ m_minute = minute;
+ m_second = second;
+ m_zone = zone;
+}
+
+
+void datetime::setDate(
+ const int year,
+ const int month,
+ const int day
+) {
+
+ m_year = year;
+ m_month = month;
+ m_day = day;
+}
+
+
+const datetime datetime::now() {
+
+ return platform::getHandler()->getCurrentLocalTime();
+}
+
+
+shared_ptr <component> datetime::clone() const {
+
+ return make_shared <datetime>(*this);
+}
+
+
+const std::vector <shared_ptr <component> > datetime::getChildComponents() {
+
+ return std::vector <shared_ptr <component> >();
+}
+
+
+int datetime::getYear() const { return m_year; }
+int datetime::getMonth() const { return m_month; }
+int datetime::getDay() const { return m_day; }
+int datetime::getHour() const { return m_hour; }
+int datetime::getMinute() const { return m_minute; }
+int datetime::getSecond() const { return m_second; }
+int datetime::getZone() const { return m_zone; }
+int datetime::getWeekDay() const { return utility::datetimeUtils::getDayOfWeek(m_year, m_month, m_day); }
+int datetime::getWeek() const { return utility::datetimeUtils::getWeekOfYear(m_year, m_month, m_day); }
+
+void datetime::setYear(const int year) { m_year = year; }
+void datetime::setMonth(const int month) { m_month = std::min(std::max(month, 1), 12); }
+void datetime::setDay(const int day) { m_day = day; }
+void datetime::setHour(const int hour) { m_hour = hour; }
+void datetime::setMinute(const int minute) { m_minute = minute; }
+void datetime::setSecond(const int second) { m_second = second; }
+void datetime::setZone(const int zone) { m_zone = zone; }
+
+
+bool datetime::operator==(const datetime& other) const {
+
+ const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this);
+ const datetime ut2 = utility::datetimeUtils::toUniversalTime(other);
+
+ return ut1.m_year == ut2.m_year &&
+ ut1.m_month == ut2.m_month &&
+ ut1.m_day == ut2.m_day &&
+ ut1.m_hour == ut2.m_hour &&
+ ut1.m_minute == ut2.m_minute &&
+ ut1.m_second == ut2.m_second;
+}
+
+
+bool datetime::operator!=(const datetime& other) const {
+
+ const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this);
+ const datetime ut2 = utility::datetimeUtils::toUniversalTime(other);
+
+ return ut1.m_year != ut2.m_year ||
+ ut1.m_month != ut2.m_month ||
+ ut1.m_day != ut2.m_day ||
+ ut1.m_hour != ut2.m_hour ||
+ ut1.m_minute != ut2.m_minute ||
+ ut1.m_second != ut2.m_second;
+}
+
+
+bool datetime::operator<(const datetime& other) const {
+
+ const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this);
+ const datetime ut2 = utility::datetimeUtils::toUniversalTime(other);
+
+ return (ut1.m_year < ut2.m_year) ||
+ ((ut1.m_year == ut2.m_year) && ((ut1.m_month < ut2.m_month) ||
+ ((ut1.m_month == ut2.m_month) && ((ut1.m_day < ut2.m_day) ||
+ ((ut1.m_day == ut2.m_day) && ((ut1.m_hour < ut2.m_hour) ||
+ ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute < ut2.m_minute) ||
+ ((ut1.m_minute == ut2.m_minute) && ((ut1.m_second < ut2.m_second)))))))))));
+}
+
+
+bool datetime::operator<=(const datetime& other) const {
+
+ const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this);
+ const datetime ut2 = utility::datetimeUtils::toUniversalTime(other);
+
+ return (ut1.m_year < ut2.m_year) ||
+ ((ut1.m_year == ut2.m_year) && ((ut1.m_month < ut2.m_month) ||
+ ((ut1.m_month == ut2.m_month) && ((ut1.m_day < ut2.m_day) ||
+ ((ut1.m_day == ut2.m_day) && ((ut1.m_hour < ut2.m_hour) ||
+ ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute < ut2.m_minute) ||
+ ((ut1.m_minute == ut2.m_minute) && ((ut1.m_second <= ut2.m_second)))))))))));
+}
+
+
+bool datetime::operator>(const datetime& other) const {
+
+ const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this);
+ const datetime ut2 = utility::datetimeUtils::toUniversalTime(other);
+
+ return (ut1.m_year > ut2.m_year) ||
+ ((ut1.m_year == ut2.m_year) && ((ut1.m_month > ut2.m_month) ||
+ ((ut1.m_month == ut2.m_month) && ((ut1.m_day > ut2.m_day) ||
+ ((ut1.m_day == ut2.m_day) && ((ut1.m_hour > ut2.m_hour) ||
+ ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute > ut2.m_minute) ||
+ ((ut1.m_minute == ut2.m_minute) && (ut1.m_second > ut2.m_second))))))))));
+}
+
+
+bool datetime::operator>=(const datetime& other) const {
+
+ const datetime ut1 = utility::datetimeUtils::toUniversalTime(*this);
+ const datetime ut2 = utility::datetimeUtils::toUniversalTime(other);
+
+ return (ut1.m_year > ut2.m_year) ||
+ ((ut1.m_year == ut2.m_year) && ((ut1.m_month > ut2.m_month) ||
+ ((ut1.m_month == ut2.m_month) && ((ut1.m_day > ut2.m_day) ||
+ ((ut1.m_day == ut2.m_day) && ((ut1.m_hour > ut2.m_hour) ||
+ ((ut1.m_hour == ut2.m_hour) && ((ut1.m_minute > ut2.m_minute) ||
+ ((ut1.m_minute == ut2.m_minute) && (ut1.m_second >= ut2.m_second))))))))));
+}
+
+
+} // vmime