From 0457e423609c6f55d3c841ab6ed8033c6ebb7ad1 Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Sun, 12 Feb 2006 14:13:04 +0000 Subject: [PATCH] Added unit tests for datetimeUtils + renamed functions. --- SConstruct | 1 + src/dateTime.cpp | 24 +++--- src/utility/datetimeUtils.cpp | 31 ++++--- tests/utility/datetimeUtilsTest.cpp | 128 ++++++++++++++++++++++++++++ vmime/utility/datetimeUtils.hpp | 12 +-- 5 files changed, 168 insertions(+), 28 deletions(-) create mode 100644 tests/utility/datetimeUtilsTest.cpp 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 + 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 +// +// 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. *