Fix up leap second manipulations
This commit is contained in:
		
							parent
							
								
									35c4455bc2
								
							
						
					
					
						commit
						a46057ef49
					
				| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue