#include <ctime>
usingnamespace std;
//======================================================================
bool isLeap( int year )
{
if ( year % 4 == 0 )
{
if ( year % 100 == 0 && year % 400 != 0 ) returnfalse;
elsereturntrue;
}
returnfalse;
}
//======================================================================
void getYearAndWeek( tm TM, int &YYYY, int &WW ) // Reference: https://en.wikipedia.org/wiki/ISO_8601
{
YYYY = TM.tm_year + 1900;
int day = TM.tm_yday;
int Monday = day - ( TM.tm_wday + 6 ) % 7; // Monday this week: may be negative down to 1-6 = -5;
int MondayYear = 1 + ( Monday + 6 ) % 7; // First Monday of the year
int Monday01 = ( MondayYear > 4 ) ? MondayYear - 7 : MondayYear; // Monday of week 1: should lie between -2 and 4 inclusive
WW = 1 + ( Monday - Monday01 ) / 7; // Nominal week ... but see below
// In ISO-8601 there is no week 0 ... it will be week 52 or 53 of the previous year
if ( WW == 0 )
{
YYYY--;
WW = 52;
if ( MondayYear == 3 || MondayYear == 4 || ( isLeap( YYYY ) && MondayYear == 2 ) ) WW = 53;
}
// Similar issues at the end of the calendar year
if ( WW == 53)
{
int daysInYear = isLeap( YYYY ) ? 366 : 365;
if ( daysInYear - Monday < 3 )
{
YYYY++;
WW = 1;
}
}
}
//======================================================================
You would need %V, not %W, in strftime() for true ISO-8601 - http://www.cplusplus.com/reference/ctime/strftime/ . I'm glad to see that the FreeBSD implementation looks just as complicated for case 'V'.
EDITED: corrected the "Week 53" case: depends on the Monday of the current week, not day of the year. Coded from the Wikipedia article, so could still do with some checking ...