By using difftime()
no need to assume Jan 1, 1970 epoch. difftime()
returns the difference in the 2 time stamps as a number of seconds (double
). The return value is independent of the number type and epoch used for time_t
.
Use mktime()
to convert YMD to time_t
.
Open question: timezone not mentioned in OP's post.
#include <stdio.h>
#include <time.h>
time_t TimeFromYMD(int year, int month, int day) {
struct tm tm = {0};
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
return mktime(&tm);
}
#define SECS_PER_WEEK (60L*60*24*7)
int GPSweek(int year, int month, int day) {
// See update below
double diff = difftime(TimeFromYMD(year, month, day), TimeFromYMD(1980, 1, 1)); // See update
return (int) (diff / SECS_PER_WEEK);
}
int main(void) {
printf("%d\n", GPSweek(2015, 11, 30));
return 0;
}
Output
1873
[edit 2022]
@Bianca offered the correction to use Jan 5, 1980 epoch. Reviewed against this and determine Jan 6, 1980 is correct which also matches this.
int GPSweek(int year, int month, int day) {
double diff = difftime(TimeFromYMD(year, month, day), TimeFromYMD(1980, 1, 6));
return (int) (diff / SECS_PER_WEEK);
}
Pedantic: Should a TZ setting include an area that has gained/lost a day due to switching across the International dateline, mktime()
may be problematic.
Week numbers before Jan 6, 1980 need additional code.