aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--SConstruct1
-rw-r--r--src/dateTime.cpp24
-rw-r--r--src/utility/datetimeUtils.cpp31
-rw-r--r--tests/utility/datetimeUtilsTest.cpp128
-rw-r--r--vmime/utility/datetimeUtils.hpp12
5 files changed, 168 insertions, 28 deletions
diff --git a/SConstruct b/SConstruct
index 4b1894d2..49dccf04 100644
--- a/SConstruct
+++ b/SConstruct
@@ -348,6 +348,7 @@ libvmimetest_sources = [
'tests/parser/parameterTest.cpp',
'tests/parser/textTest.cpp',
# ============================== Utility =============================
+ 'tests/utility/datetimeUtilsTest.cpp',
'tests/utility/filteredStreamTest.cpp',
'tests/utility/stringProxyTest.cpp',
'tests/utility/stringUtilsTest.cpp',
diff --git a/src/dateTime.cpp b/src/dateTime.cpp
index 1e2c6a29..1af0554e 100644
--- a/src/dateTime.cpp
+++ b/src/dateTime.cpp
@@ -806,8 +806,8 @@ void datetime::setZone(const int zone) { m_zone = zone; }
const bool datetime::operator==(const datetime& other) const
{
- const datetime ut1 = utility::datetimeUtils::localTimeToUniversalTime(*this);
- const datetime ut2 = utility::datetimeUtils::localTimeToUniversalTime(other);
+ 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 &&
@@ -820,8 +820,8 @@ const bool datetime::operator==(const datetime& other) const
const bool datetime::operator!=(const datetime& other) const
{
- const datetime ut1 = utility::datetimeUtils::localTimeToUniversalTime(*this);
- const datetime ut2 = utility::datetimeUtils::localTimeToUniversalTime(other);
+ 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 ||
@@ -834,8 +834,8 @@ const bool datetime::operator!=(const datetime& other) const
const bool datetime::operator<(const datetime& other) const
{
- const datetime ut1 = utility::datetimeUtils::localTimeToUniversalTime(*this);
- const datetime ut2 = utility::datetimeUtils::localTimeToUniversalTime(other);
+ 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) ||
@@ -848,8 +848,8 @@ const bool datetime::operator<(const datetime& other) const
const bool datetime::operator<=(const datetime& other) const
{
- const datetime ut1 = utility::datetimeUtils::localTimeToUniversalTime(*this);
- const datetime ut2 = utility::datetimeUtils::localTimeToUniversalTime(other);
+ 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) ||
@@ -862,8 +862,8 @@ const bool datetime::operator<=(const datetime& other) const
const bool datetime::operator>(const datetime& other) const
{
- const datetime ut1 = utility::datetimeUtils::localTimeToUniversalTime(*this);
- const datetime ut2 = utility::datetimeUtils::localTimeToUniversalTime(other);
+ 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) ||
@@ -876,8 +876,8 @@ const bool datetime::operator>(const datetime& other) const
const bool datetime::operator>=(const datetime& other) const
{
- const datetime ut1 = utility::datetimeUtils::localTimeToUniversalTime(*this);
- const datetime ut2 = utility::datetimeUtils::localTimeToUniversalTime(other);
+ 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) ||
diff --git a/src/utility/datetimeUtils.cpp b/src/utility/datetimeUtils.cpp
index c990a2ac..3bec7dbf 100644
--- a/src/utility/datetimeUtils.cpp
+++ b/src/utility/datetimeUtils.cpp
@@ -19,6 +19,8 @@
#include "vmime/utility/datetimeUtils.hpp"
+#include <stdexcept>
+
namespace vmime {
namespace utility {
@@ -157,10 +159,10 @@ static inline void substractHoursAndMinutes(datetime& d, const int h, const int
#endif // VMIME_BUILDING_DOC
-const datetime datetimeUtils::localTimeToUniversalTime(const datetime& date)
+const datetime datetimeUtils::toUniversalTime(const datetime& date)
{
if (date.getZone() == datetime::GMT)
- return (date);
+ return date; // no conversion needed
datetime nd(date);
nd.setZone(datetime::GMT);
@@ -178,19 +180,20 @@ const datetime datetimeUtils::localTimeToUniversalTime(const datetime& date)
}
-const datetime datetimeUtils::universalTimeToLocalTime(const datetime& date, const int zone)
+const datetime datetimeUtils::toLocalTime(const datetime& date, const int zone)
{
- if (zone == 0)
- return (date);
+ datetime utcDate(date);
- datetime nd(date);
+ if (utcDate.getZone() != datetime::GMT)
+ utcDate = toUniversalTime(date); // convert to UT before
+
+ datetime nd(utcDate);
nd.setZone(zone);
- const int z = zone;
- const int h = (z < 0) ? (-z / 60) : (z / 60);
- const int m = (z < 0) ? (-z - h * 60) : (z - h * 60);
+ const int h = (zone < 0) ? (-zone / 60) : (zone / 60);
+ const int m = (zone < 0) ? (-zone - h * 60) : (zone - h * 60);
- if (z < 0) // GMT+hhmm: substract hours and minutes from date
+ if (zone < 0) // GMT+hhmm: substract hours and minutes from date
substractHoursAndMinutes(nd, h, m);
else // GMT-hhmm: add hours and minutes to date
addHoursAndMinutes(nd, h, m);
@@ -213,6 +216,9 @@ const int datetimeUtils::getDaysInMonth(const int year, const int month)
static const int daysInMonthLeapYear[12] =
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+ if (month < 1 || month > 12)
+ throw std::out_of_range("Invalid month number");
+
return (isLeapYear(year) ? daysInMonthLeapYear[month - 1] : daysInMonth[month - 1]);
}
@@ -222,6 +228,11 @@ const int datetimeUtils::getDayOfWeek(const int year, const int month, const int
int y = year;
int m = month;
+ if (month < 1 || month > 12)
+ throw std::out_of_range("Invalid month number");
+ else if (day < 1 || day > getDaysInMonth(year, month))
+ throw std::out_of_range("Invalid day number");
+
// From RFC-3339 - Appendix B. Day of the Week
// Adjust months so February is the last one
diff --git a/tests/utility/datetimeUtilsTest.cpp b/tests/utility/datetimeUtilsTest.cpp
new file mode 100644
index 00000000..d018081f
--- /dev/null
+++ b/tests/utility/datetimeUtilsTest.cpp
@@ -0,0 +1,128 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2006 Vincent Richard <[email protected]>
+//
+// 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 2 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 "tests/testUtils.hpp"
+
+#include "vmime/dateTime.hpp"
+#include "vmime/utility/datetimeUtils.hpp"
+
+
+#define VMIME_TEST_SUITE datetimeUtilsTest
+#define VMIME_TEST_SUITE_MODULE "Utility"
+
+
+VMIME_TEST_SUITE_BEGIN
+
+ VMIME_TEST_LIST_BEGIN
+ VMIME_TEST(testIsLeapYear)
+ VMIME_TEST(testGetDaysInMonth)
+ VMIME_TEST(testGetDaysInMonthLeapYear)
+ VMIME_TEST(testToUniversalTime)
+ VMIME_TEST(testToLocalTime)
+ VMIME_TEST_LIST_END
+
+
+ typedef vmime::utility::datetimeUtils datetimeUtils;
+
+
+ void testIsLeapYear()
+ {
+ VASSERT_EQ("1", false, datetimeUtils::isLeapYear(1999));
+ VASSERT_EQ("2", false, datetimeUtils::isLeapYear(1800));
+ VASSERT_EQ("3", false, datetimeUtils::isLeapYear(1900));
+ VASSERT_EQ("4", false, datetimeUtils::isLeapYear(2100));
+ VASSERT_EQ("5", false, datetimeUtils::isLeapYear(2200));
+
+ VASSERT_EQ("6", true, datetimeUtils::isLeapYear(1996));
+ VASSERT_EQ("7", true, datetimeUtils::isLeapYear(2000));
+ }
+
+ void testGetDaysInMonth()
+ {
+ VASSERT_EQ("1", 31, datetimeUtils::getDaysInMonth(2006, 1));
+ VASSERT_EQ("2", 28, datetimeUtils::getDaysInMonth(2006, 2));
+ VASSERT_EQ("3", 31, datetimeUtils::getDaysInMonth(2006, 3));
+ VASSERT_EQ("4", 30, datetimeUtils::getDaysInMonth(2006, 4));
+ VASSERT_EQ("5", 31, datetimeUtils::getDaysInMonth(2006, 5));
+ VASSERT_EQ("6", 30, datetimeUtils::getDaysInMonth(2006, 6));
+ VASSERT_EQ("7", 31, datetimeUtils::getDaysInMonth(2006, 7));
+ VASSERT_EQ("8", 31, datetimeUtils::getDaysInMonth(2006, 8));
+ VASSERT_EQ("9", 30, datetimeUtils::getDaysInMonth(2006, 9));
+ VASSERT_EQ("10", 31, datetimeUtils::getDaysInMonth(2006, 10));
+ VASSERT_EQ("11", 30, datetimeUtils::getDaysInMonth(2006, 11));
+ VASSERT_EQ("12", 31, datetimeUtils::getDaysInMonth(2006, 12));
+ }
+
+ void testGetDaysInMonthLeapYear()
+ {
+ VASSERT_EQ("1", 31, datetimeUtils::getDaysInMonth(2004, 1));
+ VASSERT_EQ("2", 29, datetimeUtils::getDaysInMonth(2004, 2));
+ VASSERT_EQ("3", 31, datetimeUtils::getDaysInMonth(2004, 3));
+ VASSERT_EQ("4", 30, datetimeUtils::getDaysInMonth(2004, 4));
+ VASSERT_EQ("5", 31, datetimeUtils::getDaysInMonth(2004, 5));
+ VASSERT_EQ("6", 30, datetimeUtils::getDaysInMonth(2004, 6));
+ VASSERT_EQ("7", 31, datetimeUtils::getDaysInMonth(2004, 7));
+ VASSERT_EQ("8", 31, datetimeUtils::getDaysInMonth(2004, 8));
+ VASSERT_EQ("9", 30, datetimeUtils::getDaysInMonth(2004, 9));
+ VASSERT_EQ("10", 31, datetimeUtils::getDaysInMonth(2004, 10));
+ VASSERT_EQ("11", 30, datetimeUtils::getDaysInMonth(2004, 11));
+ VASSERT_EQ("12", 31, datetimeUtils::getDaysInMonth(2004, 12));
+ }
+
+ void testToUniversalTime()
+ {
+ const vmime::datetime local
+ (2005, 12, 2, 12, 34, 56, -789);
+
+ const vmime::datetime gmt =
+ datetimeUtils::toUniversalTime(local);
+
+ // 789 is 13 hours, 9 minutes later
+ VASSERT_EQ("1", 2005, gmt.getYear());
+ VASSERT_EQ("2", 12, gmt.getMonth());
+ VASSERT_EQ("3", 3, gmt.getDay());
+ VASSERT_EQ("4", 1, gmt.getHour());
+ VASSERT_EQ("5", 43, gmt.getMinute());
+ VASSERT_EQ("6", 56, gmt.getSecond());
+ VASSERT_EQ("7", 0, gmt.getZone());
+ }
+
+ void testToLocalTime()
+ {
+ const vmime::datetime date
+ (2005, 12, 2, 12, 34, 56, -120); // GMT-2
+
+ const vmime::datetime local =
+ datetimeUtils::toLocalTime(date, 120); // GMT+2
+
+ VASSERT_EQ("1", 2005, local.getYear());
+ VASSERT_EQ("2", 12, local.getMonth());
+ VASSERT_EQ("3", 2, local.getDay());
+ VASSERT_EQ("4", 16, local.getHour());
+ VASSERT_EQ("5", 34, local.getMinute());
+ VASSERT_EQ("6", 56, local.getSecond());
+ VASSERT_EQ("7", 120, local.getZone());
+ }
+
+VMIME_TEST_SUITE_END
+
diff --git a/vmime/utility/datetimeUtils.hpp b/vmime/utility/datetimeUtils.hpp
index 710e965e..a20be877 100644
--- a/vmime/utility/datetimeUtils.hpp
+++ b/vmime/utility/datetimeUtils.hpp
@@ -55,20 +55,20 @@ public:
*/
static const int getDaysInMonth(const int year, const int month);
- /** Convert the specified local time and date to UT (GMT).
+ /** Convert the specified date/time to UT (GMT).
*
- * @param date local date/time
+ * @param date date/time to convert
* @return GMT date/time
*/
- static const datetime localTimeToUniversalTime(const datetime& date);
+ static const datetime toUniversalTime(const datetime& date);
- /** Convert the specified UT to local time and date.
+ /** Convert the specified date/time to the specified time zone.
*
- * @param date GMT date/time
+ * @param date date/time to convert
* @param zone local zone to convert to (see datetime::TimeZones enum)
* @return local time and date
*/
- static const datetime universalTimeToLocalTime(const datetime& date, const int zone);
+ static const datetime toLocalTime(const datetime& date, const int zone);
/** Return the day of the week from the specified date.
*