Week of year calculation.
This commit is contained in:
parent
6933fb8a30
commit
01ba897060
@ -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); }
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user