200 lines
4.5 KiB
C
200 lines
4.5 KiB
C
/* libiso8601/src/tests/calconv.c
|
|
*
|
|
* (c)2006, Laurence Withers, <l@lwithers.me.uk>.
|
|
* Released under the GNU GPLv2. See file COPYING or
|
|
* http://www.gnu.org/copyleft/gpl.html for details.
|
|
*/
|
|
|
|
#include "iso8601.h"
|
|
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
|
|
|
|
const int _days_in_month_common[] = {
|
|
31,
|
|
28,
|
|
31,
|
|
30,
|
|
31,
|
|
30,
|
|
31,
|
|
31,
|
|
30,
|
|
31,
|
|
30,
|
|
31
|
|
};
|
|
|
|
const int _days_in_month_leap[] = {
|
|
31,
|
|
29,
|
|
31,
|
|
30,
|
|
31,
|
|
30,
|
|
31,
|
|
31,
|
|
30,
|
|
31,
|
|
30,
|
|
31
|
|
};
|
|
|
|
|
|
int try_year(int year)
|
|
{
|
|
static int daycount = 0;
|
|
const int* mc;
|
|
int m, d, y2, m2, d2, ret = 0;
|
|
struct iso8601_date dt;
|
|
|
|
mc = iso8601_isleap(year) ? _days_in_month_leap : _days_in_month_common;
|
|
|
|
for(m = 0; m < 12; ++m) {
|
|
for(d = 0; d < mc[m]; ++d) {
|
|
if(iso8601_from_cal(&dt, year, m + 1, d + 1)) {
|
|
++ret;
|
|
printf("[cal2date ] %04d-%02d-%02d: %s (%d)\n",
|
|
year, m + 1, d + 1, strerror(errno), errno);
|
|
|
|
} else if(dt.day != daycount) {
|
|
++ret;
|
|
printf("[discontinuity] %04d-%02d-%02d: got day=%d, expected day=%d\n",
|
|
year, m + 1, d + 1, dt.day, daycount);
|
|
|
|
} else if(iso8601_to_cal(&y2, &m2, &d2, &dt), year != y2 || m + 1 != m2 || d + 1 != d2) {
|
|
++ret;
|
|
printf("[date2cal ] %04d-%02d-%02d ==> %04d-%02d-%02d (%d)\n",
|
|
year, m + 1, d + 1, y2, m2, d2, daycount);
|
|
|
|
}
|
|
|
|
++daycount;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
int try_neg_year(int year)
|
|
{
|
|
static int daycount = 365;
|
|
const int* mc;
|
|
int m, d, y2, m2, d2, ret = 0;
|
|
struct iso8601_date dt;
|
|
|
|
mc = iso8601_isleap(year) ? _days_in_month_leap : _days_in_month_common;
|
|
|
|
for(m = 11; m >= 0; --m) {
|
|
for(d = mc[m]; d; --d) {
|
|
if(iso8601_from_cal(&dt, year, m + 1, d)) {
|
|
++ret;
|
|
printf("[cal2date ] %04d-%02d-%02d: %s (%d)\n",
|
|
year, m + 1, d, strerror(errno), errno);
|
|
|
|
} else if(dt.day != daycount) {
|
|
++ret;
|
|
printf("[discontinuity] %04d-%02d-%02d: got day=%d, expected day=%d\n",
|
|
year, m + 1, d, dt.day, daycount);
|
|
|
|
} else if(iso8601_to_cal(&y2, &m2, &d2, &dt), year != y2 || m + 1 != m2 || d != d2) {
|
|
++ret;
|
|
printf("[date2cal ] %04d-%02d-%02d ==> %04d-%02d-%02d (%d)\n",
|
|
year, m + 1, d, y2, m2, d2, daycount);
|
|
|
|
}
|
|
|
|
--daycount;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
// stuff repeats on a 400-year cycle, so we really shouldn't need to worry too much about this
|
|
#define MAX_YEAR_COUNT 2400
|
|
|
|
|
|
|
|
int try_weeks(void)
|
|
{
|
|
// starting position
|
|
int weekcount = 52, weekday = 5, isoyear = -1;
|
|
int y, wk, wd, ret = 0;
|
|
struct iso8601_date dt, dt2;
|
|
|
|
for(dt.day = 0; dt.day < MAX_YEAR_COUNT * 366; ++dt.day) {
|
|
iso8601_to_week(&y, &wk, &wd, &dt);
|
|
if(wd == 1) {
|
|
if(weekday != 7) goto discont;
|
|
++weekcount;
|
|
if(wk == 1) {
|
|
if(weekcount != 53 && weekcount != 54) goto discont;
|
|
weekcount = 1;
|
|
++isoyear;
|
|
}
|
|
}
|
|
|
|
if(wk != weekcount || y != isoyear) goto discont;
|
|
weekday = wd;
|
|
|
|
iso8601_from_week(&dt2, isoyear, weekcount, weekday);
|
|
if(dt2.day != dt.day) {
|
|
printf("[weekmismatch ] %04d-W%02d-%d: should be %d, got %d\n",
|
|
isoyear, weekcount, weekday, dt.day, dt2.day);
|
|
if(++ret > 20) return ret;
|
|
}
|
|
|
|
continue;
|
|
|
|
discont:
|
|
printf("[weekdiscont ] %04d-W%02d-%d ==> %04d-W%02d-%d (%d)\n",
|
|
isoyear, weekcount, weekday, y, wk, wd, dt.day);
|
|
isoyear = y;
|
|
weekcount = wk;
|
|
weekday = wd;
|
|
if(++ret > 20) return ret;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char* argv[])
|
|
{
|
|
int ret = 0, year;
|
|
|
|
if(argc == 2 && !strcmp(argv[1], "--print-summary")) {
|
|
printf("Calendar date / day number conversion test.\n");
|
|
return 0;
|
|
}
|
|
|
|
for(year = 0; year <= MAX_YEAR_COUNT; ++year) {
|
|
ret += try_year(year);
|
|
if(ret > 20) return ret;
|
|
}
|
|
|
|
for(year = 0; year >= -MAX_YEAR_COUNT; --year) {
|
|
ret += try_neg_year(year);
|
|
if(ret > 20) return ret;
|
|
}
|
|
|
|
ret += try_weeks();
|
|
if(ret > 20) return ret;
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* options for text editors
|
|
kate: replace-trailing-space-save true; space-indent true; tab-width 4;
|
|
vim: expandtab:ts=4:sw=4
|
|
*/
|