aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/dateTime.cpp1
-rw-r--r--src/utility/datetimeUtils.cpp70
-rw-r--r--tests/utility/datetimeUtilsTest.cpp37
-rw-r--r--vmime/dateTime.hpp1
-rw-r--r--vmime/utility/datetimeUtils.hpp9
5 files changed, 118 insertions, 0 deletions
diff --git a/src/dateTime.cpp b/src/dateTime.cpp
index 1af0554e..f3ba2396 100644
--- a/src/dateTime.cpp
+++ b/src/dateTime.cpp
@@ -794,6 +794,7 @@ const int datetime::getMinute() const { return (m_minute); }
const int datetime::getSecond() const { return (m_second); }
const int datetime::getZone() const { return (m_zone); }
const int datetime::getWeekDay() const { return (utility::datetimeUtils::getDayOfWeek(m_year, m_month, m_day)); }
+const 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); }
diff --git a/src/utility/datetimeUtils.cpp b/src/utility/datetimeUtils.cpp
index 3bec7dbf..8606a275 100644
--- a/src/utility/datetimeUtils.cpp
+++ b/src/utility/datetimeUtils.cpp
@@ -252,5 +252,75 @@ const int datetimeUtils::getDayOfWeek(const int year, const int month, const int
}
+const int datetimeUtils::getWeekOfYear(const int year, const int month, const int day)
+{
+ // Algorithm from http://personal.ecu.edu/mccartyr/ISOwdALG.txt
+
+ const bool leapYear = ((year % 4) == 0 && (year % 100) != 0) || (year % 400) == 0;
+ const bool leapYear_1 = (((year - 1) % 4) == 0 && ((year - 1) % 100) != 0) || ((year - 1) % 400) == 0;
+
+ // 4. Find the DayOfYearNumber for Y M D
+ static const int DAY_OF_YEAR_NUMBER_MAP[12] =
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+
+ int DayOfYearNumber = day + DAY_OF_YEAR_NUMBER_MAP[month - 1];
+
+ if (leapYear && month > 2)
+ DayOfYearNumber += 1;
+
+ // 5. Find the Jan1Weekday for Y (Monday=1, Sunday=7)
+ const int YY = (year - 1) % 100;
+ const int C = (year - 1) - YY;
+ const int G = YY + YY / 4;
+ const int Jan1Weekday = 1 + (((((C / 100) % 4) * 5) + G) % 7);
+
+ // 6. Find the Weekday for Y M D
+ const int H = DayOfYearNumber + (Jan1Weekday - 1);
+ const int Weekday = 1 + ((H - 1) % 7);
+
+ // 7. Find if Y M D falls in YearNumber Y-1, WeekNumber 52 or 53
+ int YearNumber, WeekNumber;
+
+ if (DayOfYearNumber <= (8 - Jan1Weekday) && Jan1Weekday > 4)
+ {
+ YearNumber = year - 1;
+
+ if (Jan1Weekday == 5 || (Jan1Weekday == 6 && leapYear_1))
+ WeekNumber = 53;
+ else
+ WeekNumber = 52;
+ }
+ else
+ {
+ YearNumber = year;
+ }
+
+ // 8. Find if Y M D falls in YearNumber Y+1, WeekNumber 1
+ if (YearNumber == year)
+ {
+ const int I = (leapYear ? 366 : 365);
+
+ if ((I - DayOfYearNumber) < (4 - Weekday))
+ {
+ YearNumber = year + 1;
+ WeekNumber = 1;
+ }
+ }
+
+ // 9. Find if Y M D falls in YearNumber Y, WeekNumber 1 through 53
+ if (YearNumber == year)
+ {
+ const int J = DayOfYearNumber + (7 - Weekday) + (Jan1Weekday - 1);
+
+ WeekNumber = J / 7;
+
+ if (Jan1Weekday > 4)
+ WeekNumber -= 1;
+ }
+
+ return WeekNumber;
+}
+
+
} // utility
} // vmime
diff --git a/tests/utility/datetimeUtilsTest.cpp b/tests/utility/datetimeUtilsTest.cpp
index d018081f..3bb9e3ec 100644
--- a/tests/utility/datetimeUtilsTest.cpp
+++ b/tests/utility/datetimeUtilsTest.cpp
@@ -39,6 +39,8 @@ VMIME_TEST_SUITE_BEGIN
VMIME_TEST(testGetDaysInMonthLeapYear)
VMIME_TEST(testToUniversalTime)
VMIME_TEST(testToLocalTime)
+ VMIME_TEST(testGetDayOfWeek)
+ VMIME_TEST(testGetWeekOfYear)
VMIME_TEST_LIST_END
@@ -124,5 +126,40 @@ VMIME_TEST_SUITE_BEGIN
VASSERT_EQ("7", 120, local.getZone());
}
+ void testGetDayOfWeek()
+ {
+ VASSERT_EQ("1", vmime::datetime::WEDNESDAY, datetimeUtils::getDayOfWeek(1969, 12, 31));
+ VASSERT_EQ("2", vmime::datetime::FRIDAY, datetimeUtils::getDayOfWeek(1976, 4, 9));
+ VASSERT_EQ("3", vmime::datetime::TUESDAY, datetimeUtils::getDayOfWeek(1987, 6, 23));
+ VASSERT_EQ("4", vmime::datetime::SATURDAY, datetimeUtils::getDayOfWeek(1990, 1, 13));
+ VASSERT_EQ("5", vmime::datetime::MONDAY, datetimeUtils::getDayOfWeek(1999, 9, 20));
+ VASSERT_EQ("6", vmime::datetime::THURSDAY, datetimeUtils::getDayOfWeek(2003, 2, 27));
+ VASSERT_EQ("7", vmime::datetime::SATURDAY, datetimeUtils::getDayOfWeek(2005, 11, 19));
+ VASSERT_EQ("8", vmime::datetime::WEDNESDAY, datetimeUtils::getDayOfWeek(2012, 5, 16));
+ VASSERT_EQ("9", vmime::datetime::FRIDAY, datetimeUtils::getDayOfWeek(2027, 3, 12));
+ }
+
+ void testGetWeekOfYear()
+ {
+ VASSERT_EQ("1.1", 52, datetimeUtils::getWeekOfYear(2003, 12, 27));
+ VASSERT_EQ("1.2", 52, datetimeUtils::getWeekOfYear(2003, 12, 28));
+ VASSERT_EQ("1.3", 1, datetimeUtils::getWeekOfYear(2003, 12, 29));
+ VASSERT_EQ("1.4", 1, datetimeUtils::getWeekOfYear(2004, 1, 4));
+ VASSERT_EQ("1.5", 2, datetimeUtils::getWeekOfYear(2004, 1, 5));
+ VASSERT_EQ("1.6", 2, datetimeUtils::getWeekOfYear(2004, 1, 11));
+
+ VASSERT_EQ("2.1", 52, datetimeUtils::getWeekOfYear(2004, 12, 26));
+ VASSERT_EQ("2.2", 53, datetimeUtils::getWeekOfYear(2004, 12, 27));
+ VASSERT_EQ("2.3", 53, datetimeUtils::getWeekOfYear(2005, 1, 2));
+ VASSERT_EQ("2.4", 1, datetimeUtils::getWeekOfYear(2005, 1, 3));
+ VASSERT_EQ("2.5", 1, datetimeUtils::getWeekOfYear(2005, 1, 4));
+ VASSERT_EQ("2.6", 2, datetimeUtils::getWeekOfYear(2005, 1, 11));
+
+ VASSERT_EQ("3.1", 9, datetimeUtils::getWeekOfYear(2027, 3, 7));
+ VASSERT_EQ("3.2", 10, datetimeUtils::getWeekOfYear(2027, 3, 8));
+ VASSERT_EQ("3.3", 10, datetimeUtils::getWeekOfYear(2027, 3, 14));
+ VASSERT_EQ("3.4", 11, datetimeUtils::getWeekOfYear(2027, 3, 15));
+ }
+
VMIME_TEST_SUITE_END
diff --git a/vmime/dateTime.hpp b/vmime/dateTime.hpp
index b047a6a4..cdb7a980 100644
--- a/vmime/dateTime.hpp
+++ b/vmime/dateTime.hpp
@@ -200,6 +200,7 @@ public:
const int getSecond() const;
const int getZone() const;
const int getWeekDay() const;
+ const int getWeek() const;
void getTime(int& hour, int& minute, int& second, int& zone) const;
void getTime(int& hour, int& minute, int& second) const;
diff --git a/vmime/utility/datetimeUtils.hpp b/vmime/utility/datetimeUtils.hpp
index a20be877..a80cf09e 100644
--- a/vmime/utility/datetimeUtils.hpp
+++ b/vmime/utility/datetimeUtils.hpp
@@ -78,6 +78,15 @@ public:
* @return the day of the week, Sunday is 0, Monday is 1 (see datetime::DaysOfWeek enum)
*/
static const int getDayOfWeek(const int year, const int month, const int day);
+
+ /** Return the week number in the year (ISO 8601).
+ *
+ * @param year year in 4-digit format
+ * @param month month (1-12), January is 1, December is 12 (see datetime::Months enum)
+ * @param day month day (1-31)
+ * @return the week number (1 is the first week of the year)
+ */
+ static const int getWeekOfYear(const int year, const int month, const int day);
};