Reputation: 43
I am trying to get the ISO8601 week number with C. MinGW is installed on my PC. GCC version is 5.3.0. You can see my code below. strftime doesn't work for specifier "%V". But it works fine with the specifier "%W". But that's not what I want. I need the week number of year in ISO 8601 format.
I have tried my code with 2 different online C compilers and they both worked fine. I doubt that the compiler on my PC is not well configured. Can anyone tell me what am I doing wrong? Any help would be appreciated.
Here is my code:
#include <stdio.h>
#include <time.h>
#include <string.h>
int main ()
{
time_t timep;
struct tm * time_inf;
char buff [80];
time ( &timep );
time_inf = localtime ( &timep );
time_inf->tm_year = 2008 - 1900;
time_inf->tm_mon = 11;
time_inf->tm_mday = 31;
mktime ( time_inf );
strftime (buff, sizeof(buff), "%V", time_inf) ;
puts (buff); //prints nothing
printf("%d", strlen(buff)); //prints 0
return 0;
}
Upvotes: 2
Views: 1944
Reputation: 153498
to get the ISO8601 week number with C
When "%V"
with strftime()
is not available or problematic, code can directivity calculate the ISO 8601 week.
ISO 8601 weeks of the year begins on Mondays.
When one want to find the ISO 8601 week of the year, often the corresponding "year" is needed too.
The first week of the year, week #1, is the first week, starting on Monday, that has at least 4 days in January - or as code below uses, the first Thursday of the year is in week 1.
Is is possible that Dec 31 is in week 1 of the next year.
Is is possible that Jan 1 is in week 52/53 of the previous year.
#include <time.h>
// return 1 on failure, 0 on success
int tm_YearWeek(const struct tm *tmptr, int *year, int *week) {
// work with local copy
struct tm tm = *tmptr;
// fully populate the yday and wday fields.
if (mktime(&tm) == -1) {
return 1;
}
// Find day-of-the-week: 0 to 6.
// Week starts on Monday per ISO 8601
// 0 <= DayOfTheWeek <= 6, Monday, Tuesday ... Sunday
int DayOfTheWeek = (tm.tm_wday + (7 - 1)) % 7;
// Offset the month day to the Monday of the week.
tm.tm_mday -= DayOfTheWeek;
// Offset the month day to the mid-week (Thursday) of the week, 3 days later.
tm.tm_mday += 3;
// Re-evaluate tm_year and tm_yday (local time)
if (mktime(&tm) == -1) {
return 1;
}
*year = tm.tm_year + 1900;
// Convert yday to week of the year, stating with 1.
*week = tm.tm_yday / 7 + 1;
return 0;
}
Example
int main() {
struct tm tm = { 0 };
tm.tm_year = 2008 - 1900;
tm.tm_mon = 12 - 1;
tm.tm_mday = 31;
tm.tm_isdst = -1;
int y = 0, w = 0;
int err = tm_YearWeek(&tm, &y, &w);
printf("Err:%d Year:%d Week:%d %02d%02d\n", err, y, w, y%100, w);
return 0;
}
Output is week 1 of 2009 for Dec 31, 2008 or 0901. This is expected per the discussion above and may explain OP's unstated concern with OP's code.
Err:0 Year:2009 Week:1 0901
Upvotes: 2
Reputation: 8657
MinGW doesn't provide its own strftime
, but links in MSVCRT's definition, which doesn't provide %V
.
Either implement what you're missing yourself or use an alternate implementation, e.g. here's BSD's strftime.
Upvotes: 2