Fix up leap second manipulations

This commit is contained in:
Laurence Withers 2007-07-24 11:45:21 +00:00
parent 35c4455bc2
commit a46057ef49
3 changed files with 71 additions and 15 deletions

View File

@ -57,7 +57,7 @@ static int _leap_elapsed_day(int sday, int eday)
if(eday <= leap_second_days[epos]) break;
}
return spos - epos;
return epos - spos;
}

View File

@ -40,14 +40,52 @@ int iso8601_eq(const struct iso8601_date* d1, const struct iso8601_date* d2)
void iso8601_add_elapsed(struct iso8601_date* date, const struct iso8601_elapsed* per)
{
/* TODO */
div_t qr;
int leapcorrect;
/* work out number to advance `day' by */
qr = div(per->sec, 86400);
leapcorrect = _leap_elapsed_day(date->day, date->day + qr.quot);
date->day += qr.quot;
date->sec += qr.rem - leapcorrect;
if(date->sec < 0) {
--date->day;
date->sec += iso8601_seconds_leap(date);
}
date->nsec += per->nsec;
if(date->nsec > BILLION) {
++date->sec;
date->nsec -= BILLION;
}
}
void iso8601_subtract_elapsed(struct iso8601_date* date, const struct iso8601_elapsed* per)
{
/* TODO */
div_t qr;
int leapcorrect;
/* work out number to advance `day' by */
qr = div(per->sec, 86400);
leapcorrect = _leap_elapsed_day(date->day - qr.quot, date->day);
date->day -= qr.quot;
date->sec -= qr.rem - leapcorrect;
date->nsec -= per->nsec;
if(date->nsec < 0) {
--date->sec;
date->nsec += BILLION;
}
if(date->sec < 0) {
--date->day;
date->sec += iso8601_seconds_leap(date);
}
if(date->sec >= iso8601_seconds_leap(date)) {
date->sec -= iso8601_seconds_leap(date);
++date->day;
}
}

View File

@ -30,6 +30,7 @@ int leap_diff(const char* s1, const char* s2, int* diff)
int regression1(void)
{
struct iso8601_date d;
struct iso8601_elapsed elapsed;
char s1[30], s2[30], s3[30];
int ret = 0, oday;
@ -39,11 +40,13 @@ int regression1(void)
d.nsec = 0;
iso8601_print(s1, sizeof(s1), &d, 0);
iso8601_add_seconds(&d, 86400);
elapsed.sec = 86400;
elapsed.nsec = 0;
iso8601_add_elapsed(&d, &elapsed);
iso8601_print(s2, sizeof(s2), &d, 0);
ret |= (d.day != oday) | (d.sec != 86400);
iso8601_add_seconds(&d, 86400);
iso8601_add_elapsed(&d, &elapsed);
iso8601_print(s3, sizeof(s3), &d, 0);
ret |= (d.day != (oday + 1)) | (d.sec != 86399);
@ -58,6 +61,7 @@ int regression2(void)
{
struct iso8601_date d;
char s1[30], s2[30], s3[30];
struct iso8601_elapsed elapsed;
int ret = 0, oday;
iso8601_from_cal(&d, 2005, 12, 31);
@ -66,11 +70,13 @@ int regression2(void)
d.nsec = 0;
iso8601_print(s1, sizeof(s1), &d, 0);
iso8601_add_seconds(&d, 86400);
elapsed.sec = 86400;
elapsed.nsec = 0;
iso8601_add_elapsed(&d, &elapsed);
iso8601_print(s2, sizeof(s2), &d, 0);
ret |= (d.day != (oday + 1)) | (d.sec != 86398);
iso8601_add_seconds(&d, 86400);
iso8601_add_elapsed(&d, &elapsed);
iso8601_print(s3, sizeof(s3), &d, 0);
ret |= (d.day != (oday + 2)) | (d.sec != 86398);
@ -85,6 +91,7 @@ int regression3(void)
{
struct iso8601_date d;
char s1[30], s2[30], s3[30];
struct iso8601_elapsed elapsed;
int ret = 0, oday;
iso8601_from_cal(&d, 2005, 12, 31);
@ -93,11 +100,13 @@ int regression3(void)
d.nsec = 0;
iso8601_print(s1, sizeof(s1), &d, 0);
iso8601_add_seconds(&d, 86400);
elapsed.sec = 86400;
elapsed.nsec = 0;
iso8601_add_elapsed(&d, &elapsed);
iso8601_print(s2, sizeof(s2), &d, 0);
ret |= (d.day != (oday + 1)) | (d.sec != 86399);
iso8601_add_seconds(&d, 86400);
iso8601_add_elapsed(&d, &elapsed);
iso8601_print(s3, sizeof(s3), &d, 0);
ret |= (d.day != (oday + 2)) | (d.sec != 86399);
@ -112,6 +121,7 @@ int regression4(void)
{
struct iso8601_date d;
char s1[30], s2[30], s3[30];
struct iso8601_elapsed elapsed;
int ret = 0, oday;
iso8601_from_cal(&d, 2006, 1, 1);
@ -120,11 +130,13 @@ int regression4(void)
d.nsec = 0;
iso8601_print(s1, sizeof(s1), &d, 0);
iso8601_add_seconds(&d, -86400);
elapsed.sec = 86400;
elapsed.nsec = 0;
iso8601_subtract_elapsed(&d, &elapsed);
iso8601_print(s2, sizeof(s2), &d, 0);
ret |= (d.day != (oday - 1)) | (d.sec != 86400);
iso8601_add_seconds(&d, -86400);
iso8601_subtract_elapsed(&d, &elapsed);
iso8601_print(s3, sizeof(s3), &d, 0);
ret |= (d.day != (oday - 1)) | (d.sec != 0);
@ -139,6 +151,7 @@ int regression5(void)
{
struct iso8601_date d;
char s1[30], s2[30], s3[30];
struct iso8601_elapsed elapsed;
int ret = 0, oday;
iso8601_from_cal(&d, 2006, 1, 2);
@ -147,11 +160,13 @@ int regression5(void)
d.nsec = 0;
iso8601_print(s1, sizeof(s1), &d, 0);
iso8601_add_seconds(&d, -86400);
elapsed.sec = 86400;
elapsed.nsec = 0;
iso8601_subtract_elapsed(&d, &elapsed);
iso8601_print(s2, sizeof(s2), &d, 0);
ret |= (d.day != (oday - 1)) | (d.sec != 86398);
iso8601_add_seconds(&d, -86400);
iso8601_subtract_elapsed(&d, &elapsed);
iso8601_print(s3, sizeof(s3), &d, 0);
ret |= (d.day != (oday - 2)) | (d.sec != 86399);
@ -166,6 +181,7 @@ int regression6(void)
{
struct iso8601_date d;
char s1[30], s2[30], s3[30];
struct iso8601_elapsed elapsed;
int ret = 0, oday;
iso8601_from_cal(&d, 2006, 1, 2);
@ -174,11 +190,13 @@ int regression6(void)
d.nsec = 0;
iso8601_print(s1, sizeof(s1), &d, 0);
iso8601_add_seconds(&d, -86400);
elapsed.sec = 86400;
elapsed.nsec = 0;
iso8601_subtract_elapsed(&d, &elapsed);
iso8601_print(s2, sizeof(s2), &d, 0);
ret |= (d.day != (oday - 1)) | (d.sec != 86399);
iso8601_add_seconds(&d, -86400);
iso8601_subtract_elapsed(&d, &elapsed);
iso8601_print(s3, sizeof(s3), &d, 0);
ret |= (d.day != (oday - 2)) | (d.sec != 86400);