1 /* $NetBSD: ntp_calendar.c,v 1.10 2018/04/07 00:19:52 christos Exp $ */ 2 3 /* 4 * ntp_calendar.c - calendar and helper functions 5 * 6 * Written by Juergen Perlinger (perlinger@ntp.org) for the NTP project. 7 * The contents of 'html/copyright.html' apply. 8 * 9 * -------------------------------------------------------------------- 10 * Some notes on the implementation: 11 * 12 * Calendar algorithms thrive on the division operation, which is one of 13 * the slowest numerical operations in any CPU. What saves us here from 14 * abysmal performance is the fact that all divisions are divisions by 15 * constant numbers, and most compilers can do this by a multiplication 16 * operation. But this might not work when using the div/ldiv/lldiv 17 * function family, because many compilers are not able to do inline 18 * expansion of the code with following optimisation for the 19 * constant-divider case. 20 * 21 * Also div/ldiv/lldiv are defined in terms of int/long/longlong, which 22 * are inherently target dependent. Nothing that could not be cured with 23 * autoconf, but still a mess... 24 * 25 * Furthermore, we need floor division in many places. C either leaves 26 * the division behaviour undefined (< C99) or demands truncation to 27 * zero (>= C99), so additional steps are required to make sure the 28 * algorithms work. The {l,ll}div function family is requested to 29 * truncate towards zero, which is also the wrong direction for our 30 * purpose. 31 * 32 * For all this, all divisions by constant are coded manually, even when 33 * there is a joined div/mod operation: The optimiser should sort that 34 * out, if possible. Most of the calculations are done with unsigned 35 * types, explicitely using two's complement arithmetics where 36 * necessary. This minimises the dependecies to compiler and target, 37 * while still giving reasonable to good performance. 38 * 39 * The implementation uses a few tricks that exploit properties of the 40 * two's complement: Floor division on negative dividents can be 41 * executed by using the one's complement of the divident. One's 42 * complement can be easily created using XOR and a mask. 43 * 44 * Finally, check for overflow conditions is minimal. There are only two 45 * calculation steps in the whole calendar that suffer from an internal 46 * overflow, and these conditions are checked: errno is set to EDOM and 47 * the results are clamped/saturated in this case. All other functions 48 * do not suffer from internal overflow and simply return the result 49 * truncated to 32 bits. 50 * 51 * This is a sacrifice made for execution speed. Since a 32-bit day 52 * counter covers +/- 5,879,610 years and the clamp limits the effective 53 * range to +/-2.9 million years, this should not pose a problem here. 54 * 55 */ 56 57 #include <config.h> 58 #include <sys/types.h> 59 60 #include "ntp_types.h" 61 #include "ntp_calendar.h" 62 #include "ntp_stdlib.h" 63 #include "ntp_fp.h" 64 #include "ntp_unixtime.h" 65 66 /* For now, let's take the conservative approach: if the target property 67 * macros are not defined, check a few well-known compiler/architecture 68 * settings. Default is to assume that the representation of signed 69 * integers is unknown and shift-arithmetic-right is not available. 70 */ 71 #ifndef TARGET_HAS_2CPL 72 # if defined(__GNUC__) 73 # if defined(__i386__) || defined(__x86_64__) || defined(__arm__) 74 # define TARGET_HAS_2CPL 1 75 # else 76 # define TARGET_HAS_2CPL 0 77 # endif 78 # elif defined(_MSC_VER) 79 # if defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM) 80 # define TARGET_HAS_2CPL 1 81 # else 82 # define TARGET_HAS_2CPL 0 83 # endif 84 # else 85 # define TARGET_HAS_2CPL 0 86 # endif 87 #endif 88 89 #ifndef TARGET_HAS_SAR 90 # define TARGET_HAS_SAR 0 91 #endif 92 93 /* 94 *--------------------------------------------------------------------- 95 * replacing the 'time()' function 96 *--------------------------------------------------------------------- 97 */ 98 99 static systime_func_ptr systime_func = &time; 100 static inline time_t now(void); 101 102 103 systime_func_ptr 104 ntpcal_set_timefunc( 105 systime_func_ptr nfunc 106 ) 107 { 108 systime_func_ptr res; 109 110 res = systime_func; 111 if (NULL == nfunc) 112 nfunc = &time; 113 systime_func = nfunc; 114 115 return res; 116 } 117 118 119 static inline time_t 120 now(void) 121 { 122 return (*systime_func)(NULL); 123 } 124 125 /* 126 *--------------------------------------------------------------------- 127 * Get sign extension mask and unsigned 2cpl rep for a signed integer 128 *--------------------------------------------------------------------- 129 */ 130 131 static inline uint32_t 132 int32_sflag( 133 const int32_t v) 134 { 135 # if TARGET_HAS_2CPL && TARGET_HAS_SAR && SIZEOF_INT >= 4 136 137 /* Let's assume that shift is the fastest way to get the sign 138 * extension of of a signed integer. This might not always be 139 * true, though -- On 8bit CPUs or machines without barrel 140 * shifter this will kill the performance. So we make sure 141 * we do this only if 'int' has at least 4 bytes. 142 */ 143 return (uint32_t)(v >> 31); 144 145 # else 146 147 /* This should be a rather generic approach for getting a sign 148 * extension mask... 149 */ 150 return UINT32_C(0) - (uint32_t)(v < 0); 151 152 # endif 153 } 154 155 static inline uint32_t 156 int32_to_uint32_2cpl( 157 const int32_t v) 158 { 159 uint32_t vu; 160 161 # if TARGET_HAS_2CPL 162 163 /* Just copy through the 32 bits from the signed value if we're 164 * on a two's complement target. 165 */ 166 vu = (uint32_t)v; 167 168 # else 169 170 /* Convert from signed int to unsigned int two's complement. Do 171 * not make any assumptions about the representation of signed 172 * integers, but make sure signed integer overflow cannot happen 173 * here. A compiler on a two's complement target *might* find 174 * out that this is just a complicated cast (as above), but your 175 * mileage might vary. 176 */ 177 if (v < 0) 178 vu = ~(uint32_t)(-(v + 1)); 179 else 180 vu = (uint32_t)v; 181 182 # endif 183 184 return vu; 185 } 186 187 static inline int32_t 188 uint32_2cpl_to_int32( 189 const uint32_t vu) 190 { 191 int32_t v; 192 193 # if TARGET_HAS_2CPL 194 195 /* Just copy through the 32 bits from the unsigned value if 196 * we're on a two's complement target. 197 */ 198 v = (int32_t)vu; 199 200 # else 201 202 /* Convert to signed integer, making sure signed integer 203 * overflow cannot happen. Again, the optimiser might or might 204 * not find out that this is just a copy of 32 bits on a target 205 * with two's complement representation for signed integers. 206 */ 207 if (vu > INT32_MAX) 208 v = -(int32_t)(~vu) - 1; 209 else 210 v = (int32_t)vu; 211 212 # endif 213 214 return v; 215 } 216 217 /* Some of the calculations need to multiply the input by 4 before doing 218 * a division. This can cause overflow and strange results. Therefore we 219 * clamp / saturate the input operand. And since we do the calculations 220 * in unsigned int with an extra sign flag/mask, we only loose one bit 221 * of the input value range. 222 */ 223 static inline uint32_t 224 uint32_saturate( 225 uint32_t vu, 226 uint32_t mu) 227 { 228 static const uint32_t limit = UINT32_MAX/4u; 229 if ((mu ^ vu) > limit) { 230 vu = mu ^ limit; 231 errno = EDOM; 232 } 233 return vu; 234 } 235 236 /* 237 *--------------------------------------------------------------------- 238 * Convert between 'time_t' and 'vint64' 239 *--------------------------------------------------------------------- 240 */ 241 vint64 242 time_to_vint64( 243 const time_t * ptt 244 ) 245 { 246 vint64 res; 247 time_t tt; 248 249 tt = *ptt; 250 251 # if SIZEOF_TIME_T <= 4 252 253 res.D_s.hi = 0; 254 if (tt < 0) { 255 res.D_s.lo = (uint32_t)-tt; 256 M_NEG(res.D_s.hi, res.D_s.lo); 257 } else { 258 res.D_s.lo = (uint32_t)tt; 259 } 260 261 # elif defined(HAVE_INT64) 262 263 res.q_s = tt; 264 265 # else 266 /* 267 * shifting negative signed quantities is compiler-dependent, so 268 * we better avoid it and do it all manually. And shifting more 269 * than the width of a quantity is undefined. Also a don't do! 270 */ 271 if (tt < 0) { 272 tt = -tt; 273 res.D_s.lo = (uint32_t)tt; 274 res.D_s.hi = (uint32_t)(tt >> 32); 275 M_NEG(res.D_s.hi, res.D_s.lo); 276 } else { 277 res.D_s.lo = (uint32_t)tt; 278 res.D_s.hi = (uint32_t)(tt >> 32); 279 } 280 281 # endif 282 283 return res; 284 } 285 286 287 time_t 288 vint64_to_time( 289 const vint64 *tv 290 ) 291 { 292 time_t res; 293 294 # if SIZEOF_TIME_T <= 4 295 296 res = (time_t)tv->D_s.lo; 297 298 # elif defined(HAVE_INT64) 299 300 res = (time_t)tv->q_s; 301 302 # else 303 304 res = ((time_t)tv->d_s.hi << 32) | tv->D_s.lo; 305 306 # endif 307 308 return res; 309 } 310 311 /* 312 *--------------------------------------------------------------------- 313 * Get the build date & time 314 *--------------------------------------------------------------------- 315 */ 316 int 317 ntpcal_get_build_date( 318 struct calendar * jd 319 ) 320 { 321 /* The C standard tells us the format of '__DATE__': 322 * 323 * __DATE__ The date of translation of the preprocessing 324 * translation unit: a character string literal of the form "Mmm 325 * dd yyyy", where the names of the months are the same as those 326 * generated by the asctime function, and the first character of 327 * dd is a space character if the value is less than 10. If the 328 * date of translation is not available, an 329 * implementation-defined valid date shall be supplied. 330 * 331 * __TIME__ The time of translation of the preprocessing 332 * translation unit: a character string literal of the form 333 * "hh:mm:ss" as in the time generated by the asctime 334 * function. If the time of translation is not available, an 335 * implementation-defined valid time shall be supplied. 336 * 337 * Note that MSVC declares DATE and TIME to be in the local time 338 * zone, while neither the C standard nor the GCC docs make any 339 * statement about this. As a result, we may be +/-12hrs off 340 * UTC. But for practical purposes, this should not be a 341 * problem. 342 * 343 */ 344 # ifdef MKREPRO_DATE 345 static const char build[] = MKREPRO_TIME "/" MKREPRO_DATE; 346 # else 347 static const char build[] = __TIME__ "/" __DATE__; 348 # endif 349 static const char mlist[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; 350 351 char monstr[4]; 352 const char * cp; 353 unsigned short hour, minute, second, day, year; 354 /* Note: The above quantities are used for sscanf 'hu' format, 355 * so using 'uint16_t' is contra-indicated! 356 */ 357 358 # ifdef DEBUG 359 static int ignore = 0; 360 # endif 361 362 ZERO(*jd); 363 jd->year = 1970; 364 jd->month = 1; 365 jd->monthday = 1; 366 367 # ifdef DEBUG 368 /* check environment if build date should be ignored */ 369 if (0 == ignore) { 370 const char * envstr; 371 envstr = getenv("NTPD_IGNORE_BUILD_DATE"); 372 ignore = 1 + (envstr && (!*envstr || !strcasecmp(envstr, "yes"))); 373 } 374 if (ignore > 1) 375 return FALSE; 376 # endif 377 378 if (6 == sscanf(build, "%hu:%hu:%hu/%3s %hu %hu", 379 &hour, &minute, &second, monstr, &day, &year)) { 380 cp = strstr(mlist, monstr); 381 if (NULL != cp) { 382 jd->year = year; 383 jd->month = (uint8_t)((cp - mlist) / 3 + 1); 384 jd->monthday = (uint8_t)day; 385 jd->hour = (uint8_t)hour; 386 jd->minute = (uint8_t)minute; 387 jd->second = (uint8_t)second; 388 389 return TRUE; 390 } 391 } 392 393 return FALSE; 394 } 395 396 397 /* 398 *--------------------------------------------------------------------- 399 * basic calendar stuff 400 *--------------------------------------------------------------------- 401 */ 402 403 /* month table for a year starting with March,1st */ 404 static const uint16_t shift_month_table[13] = { 405 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337, 366 406 }; 407 408 /* month tables for years starting with January,1st; regular & leap */ 409 static const uint16_t real_month_table[2][13] = { 410 /* -*- table for regular years -*- */ 411 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, 412 /* -*- table for leap years -*- */ 413 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } 414 }; 415 416 /* 417 * Some notes on the terminology: 418 * 419 * We use the proleptic Gregorian calendar, which is the Gregorian 420 * calendar extended in both directions ad infinitum. This totally 421 * disregards the fact that this calendar was invented in 1582, and 422 * was adopted at various dates over the world; sometimes even after 423 * the start of the NTP epoch. 424 * 425 * Normally date parts are given as current cycles, while time parts 426 * are given as elapsed cycles: 427 * 428 * 1970-01-01/03:04:05 means 'IN the 1970st. year, IN the first month, 429 * ON the first day, with 3hrs, 4minutes and 5 seconds elapsed. 430 * 431 * The basic calculations for this calendar implementation deal with 432 * ELAPSED date units, which is the number of full years, full months 433 * and full days before a date: 1970-01-01 would be (1969, 0, 0) in 434 * that notation. 435 * 436 * To ease the numeric computations, month and day values outside the 437 * normal range are acceptable: 2001-03-00 will be treated as the day 438 * before 2001-03-01, 2000-13-32 will give the same result as 439 * 2001-02-01 and so on. 440 * 441 * 'rd' or 'RD' is used as an abbreviation for the latin 'rata die' 442 * (day number). This is the number of days elapsed since 0000-12-31 443 * in the proleptic Gregorian calendar. The begin of the Christian Era 444 * (0001-01-01) is RD(1). 445 */ 446 447 /* 448 * ==================================================================== 449 * 450 * General algorithmic stuff 451 * 452 * ==================================================================== 453 */ 454 455 /* 456 *--------------------------------------------------------------------- 457 * Do a periodic extension of 'value' around 'pivot' with a period of 458 * 'cycle'. 459 * 460 * The result 'res' is a number that holds to the following properties: 461 * 462 * 1) res MOD cycle == value MOD cycle 463 * 2) pivot <= res < pivot + cycle 464 * (replace </<= with >/>= for negative cycles) 465 * 466 * where 'MOD' denotes the modulo operator for FLOOR DIVISION, which 467 * is not the same as the '%' operator in C: C requires division to be 468 * a truncated division, where remainder and dividend have the same 469 * sign if the remainder is not zero, whereas floor division requires 470 * divider and modulus to have the same sign for a non-zero modulus. 471 * 472 * This function has some useful applications: 473 * 474 * + let Y be a calendar year and V a truncated 2-digit year: then 475 * periodic_extend(Y-50, V, 100) 476 * is the closest expansion of the truncated year with respect to 477 * the full year, that is a 4-digit year with a difference of less 478 * than 50 years to the year Y. ("century unfolding") 479 * 480 * + let T be a UN*X time stamp and V be seconds-of-day: then 481 * perodic_extend(T-43200, V, 86400) 482 * is a time stamp that has the same seconds-of-day as the input 483 * value, with an absolute difference to T of <= 12hrs. ("day 484 * unfolding") 485 * 486 * + Wherever you have a truncated periodic value and a non-truncated 487 * base value and you want to match them somehow... 488 * 489 * Basically, the function delivers 'pivot + (value - pivot) % cycle', 490 * but the implementation takes some pains to avoid internal signed 491 * integer overflows in the '(value - pivot) % cycle' part and adheres 492 * to the floor division convention. 493 * 494 * If 64bit scalars where available on all intended platforms, writing a 495 * version that uses 64 bit ops would be easy; writing a general 496 * division routine for 64bit ops on a platform that can only do 497 * 32/16bit divisions and is still performant is a bit more 498 * difficult. Since most usecases can be coded in a way that does only 499 * require the 32-bit version a 64bit version is NOT provided here. 500 *--------------------------------------------------------------------- 501 */ 502 int32_t 503 ntpcal_periodic_extend( 504 int32_t pivot, 505 int32_t value, 506 int32_t cycle 507 ) 508 { 509 uint32_t diff; 510 char cpl = 0; /* modulo complement flag */ 511 char neg = 0; /* sign change flag */ 512 513 /* make the cycle positive and adjust the flags */ 514 if (cycle < 0) { 515 cycle = - cycle; 516 neg ^= 1; 517 cpl ^= 1; 518 } 519 /* guard against div by zero or one */ 520 if (cycle > 1) { 521 /* 522 * Get absolute difference as unsigned quantity and 523 * the complement flag. This is done by always 524 * subtracting the smaller value from the bigger 525 * one. 526 */ 527 if (value >= pivot) { 528 diff = int32_to_uint32_2cpl(value) 529 - int32_to_uint32_2cpl(pivot); 530 } else { 531 diff = int32_to_uint32_2cpl(pivot) 532 - int32_to_uint32_2cpl(value); 533 cpl ^= 1; 534 } 535 diff %= (uint32_t)cycle; 536 if (diff) { 537 if (cpl) 538 diff = (uint32_t)cycle - diff; 539 if (neg) 540 diff = ~diff + 1; 541 pivot += uint32_2cpl_to_int32(diff); 542 } 543 } 544 return pivot; 545 } 546 547 /*--------------------------------------------------------------------- 548 * Note to the casual reader 549 * 550 * In the next two functions you will find (or would have found...) 551 * the expression 552 * 553 * res.Q_s -= 0x80000000; 554 * 555 * There was some ruckus about a possible programming error due to 556 * integer overflow and sign propagation. 557 * 558 * This assumption is based on a lack of understanding of the C 559 * standard. (Though this is admittedly not one of the most 'natural' 560 * aspects of the 'C' language and easily to get wrong.) 561 * 562 * see 563 * http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf 564 * "ISO/IEC 9899:201x Committee Draft — April 12, 2011" 565 * 6.4.4.1 Integer constants, clause 5 566 * 567 * why there is no sign extension/overflow problem here. 568 * 569 * But to ease the minds of the doubtful, I added back the 'u' qualifiers 570 * that somehow got lost over the last years. 571 */ 572 573 574 /* 575 *--------------------------------------------------------------------- 576 * Convert a timestamp in NTP scale to a 64bit seconds value in the UN*X 577 * scale with proper epoch unfolding around a given pivot or the current 578 * system time. This function happily accepts negative pivot values as 579 * timestamps befor 1970-01-01, so be aware of possible trouble on 580 * platforms with 32bit 'time_t'! 581 * 582 * This is also a periodic extension, but since the cycle is 2^32 and 583 * the shift is 2^31, we can do some *very* fast math without explicit 584 * divisions. 585 *--------------------------------------------------------------------- 586 */ 587 vint64 588 ntpcal_ntp_to_time( 589 uint32_t ntp, 590 const time_t * pivot 591 ) 592 { 593 vint64 res; 594 595 # if defined(HAVE_INT64) 596 597 res.q_s = (pivot != NULL) 598 ? *pivot 599 : now(); 600 res.Q_s -= 0x80000000u; /* unshift of half range */ 601 ntp -= (uint32_t)JAN_1970; /* warp into UN*X domain */ 602 ntp -= res.D_s.lo; /* cycle difference */ 603 res.Q_s += (uint64_t)ntp; /* get expanded time */ 604 605 # else /* no 64bit scalars */ 606 607 time_t tmp; 608 609 tmp = (pivot != NULL) 610 ? *pivot 611 : now(); 612 res = time_to_vint64(&tmp); 613 M_SUB(res.D_s.hi, res.D_s.lo, 0, 0x80000000u); 614 ntp -= (uint32_t)JAN_1970; /* warp into UN*X domain */ 615 ntp -= res.D_s.lo; /* cycle difference */ 616 M_ADD(res.D_s.hi, res.D_s.lo, 0, ntp); 617 618 # endif /* no 64bit scalars */ 619 620 return res; 621 } 622 623 /* 624 *--------------------------------------------------------------------- 625 * Convert a timestamp in NTP scale to a 64bit seconds value in the NTP 626 * scale with proper epoch unfolding around a given pivot or the current 627 * system time. 628 * 629 * Note: The pivot must be given in the UN*X time domain! 630 * 631 * This is also a periodic extension, but since the cycle is 2^32 and 632 * the shift is 2^31, we can do some *very* fast math without explicit 633 * divisions. 634 *--------------------------------------------------------------------- 635 */ 636 vint64 637 ntpcal_ntp_to_ntp( 638 uint32_t ntp, 639 const time_t *pivot 640 ) 641 { 642 vint64 res; 643 644 # if defined(HAVE_INT64) 645 646 res.q_s = (pivot) 647 ? *pivot 648 : now(); 649 res.Q_s -= 0x80000000u; /* unshift of half range */ 650 res.Q_s += (uint32_t)JAN_1970; /* warp into NTP domain */ 651 ntp -= res.D_s.lo; /* cycle difference */ 652 res.Q_s += (uint64_t)ntp; /* get expanded time */ 653 654 # else /* no 64bit scalars */ 655 656 time_t tmp; 657 658 tmp = (pivot) 659 ? *pivot 660 : now(); 661 res = time_to_vint64(&tmp); 662 M_SUB(res.D_s.hi, res.D_s.lo, 0, 0x80000000u); 663 M_ADD(res.D_s.hi, res.D_s.lo, 0, (uint32_t)JAN_1970);/*into NTP */ 664 ntp -= res.D_s.lo; /* cycle difference */ 665 M_ADD(res.D_s.hi, res.D_s.lo, 0, ntp); 666 667 # endif /* no 64bit scalars */ 668 669 return res; 670 } 671 672 673 /* 674 * ==================================================================== 675 * 676 * Splitting values to composite entities 677 * 678 * ==================================================================== 679 */ 680 681 /* 682 *--------------------------------------------------------------------- 683 * Split a 64bit seconds value into elapsed days in 'res.hi' and 684 * elapsed seconds since midnight in 'res.lo' using explicit floor 685 * division. This function happily accepts negative time values as 686 * timestamps before the respective epoch start. 687 *--------------------------------------------------------------------- 688 */ 689 ntpcal_split 690 ntpcal_daysplit( 691 const vint64 *ts 692 ) 693 { 694 ntpcal_split res; 695 uint32_t Q; 696 697 # if defined(HAVE_INT64) 698 699 /* Manual floor division by SECSPERDAY. This uses the one's 700 * complement trick, too, but without an extra flag value: The 701 * flag would be 64bit, and that's a bit of overkill on a 32bit 702 * target that has to use a register pair for a 64bit number. 703 */ 704 if (ts->q_s < 0) 705 Q = ~(uint32_t)(~ts->Q_s / SECSPERDAY); 706 else 707 Q = (uint32_t)(ts->Q_s / SECSPERDAY); 708 709 # else 710 711 uint32_t ah, al, sflag, A; 712 713 /* get operand into ah/al (either ts or ts' one's complement, 714 * for later floor division) 715 */ 716 sflag = int32_sflag(ts->d_s.hi); 717 ah = sflag ^ ts->D_s.hi; 718 al = sflag ^ ts->D_s.lo; 719 720 /* Since 86400 == 128*675 we can drop the least 7 bits and 721 * divide by 675 instead of 86400. Then the maximum remainder 722 * after each devision step is 674, and we need 10 bits for 723 * that. So in the next step we can shift in 22 bits from the 724 * numerator. 725 * 726 * Therefore we load the accu with the top 13 bits (51..63) in 727 * the first shot. We don't have to remember the quotient -- it 728 * would be shifted out anyway. 729 */ 730 A = ah >> 19; 731 if (A >= 675) 732 A = (A % 675u); 733 734 /* Now assemble the remainder with bits 29..50 from the 735 * numerator and divide. This creates the upper ten bits of the 736 * quotient. (Well, the top 22 bits of a 44bit result. But that 737 * will be truncated to 32 bits anyway.) 738 */ 739 A = (A << 19) | (ah & 0x0007FFFFu); 740 A = (A << 3) | (al >> 29); 741 Q = A / 675u; 742 A = A % 675u; 743 744 /* Now assemble the remainder with bits 7..28 from the numerator 745 * and do a final division step. 746 */ 747 A = (A << 22) | ((al >> 7) & 0x003FFFFFu); 748 Q = (Q << 22) | (A / 675u); 749 750 /* The last 7 bits get simply dropped, as they have no affect on 751 * the quotient when dividing by 86400. 752 */ 753 754 /* apply sign correction and calculate the true floor 755 * remainder. 756 */ 757 Q ^= sflag; 758 759 # endif 760 761 res.hi = uint32_2cpl_to_int32(Q); 762 res.lo = ts->D_s.lo - Q * SECSPERDAY; 763 764 return res; 765 } 766 767 /* 768 *--------------------------------------------------------------------- 769 * Split a 32bit seconds value into h/m/s and excessive days. This 770 * function happily accepts negative time values as timestamps before 771 * midnight. 772 *--------------------------------------------------------------------- 773 */ 774 static int32_t 775 priv_timesplit( 776 int32_t split[3], 777 int32_t ts 778 ) 779 { 780 /* Do 3 chained floor divisions by positive constants, using the 781 * one's complement trick and factoring out the intermediate XOR 782 * ops to reduce the number of operations. 783 */ 784 uint32_t us, um, uh, ud, sflag; 785 786 sflag = int32_sflag(ts); 787 us = int32_to_uint32_2cpl(ts); 788 789 um = (sflag ^ us) / SECSPERMIN; 790 uh = um / MINSPERHR; 791 ud = uh / HRSPERDAY; 792 793 um ^= sflag; 794 uh ^= sflag; 795 ud ^= sflag; 796 797 split[0] = (int32_t)(uh - ud * HRSPERDAY ); 798 split[1] = (int32_t)(um - uh * MINSPERHR ); 799 split[2] = (int32_t)(us - um * SECSPERMIN); 800 801 return uint32_2cpl_to_int32(ud); 802 } 803 804 /* 805 *--------------------------------------------------------------------- 806 * Given the number of elapsed days in the calendar era, split this 807 * number into the number of elapsed years in 'res.hi' and the number 808 * of elapsed days of that year in 'res.lo'. 809 * 810 * if 'isleapyear' is not NULL, it will receive an integer that is 0 for 811 * regular years and a non-zero value for leap years. 812 *--------------------------------------------------------------------- 813 */ 814 ntpcal_split 815 ntpcal_split_eradays( 816 int32_t days, 817 int *isleapyear 818 ) 819 { 820 /* Use the fast cyclesplit algorithm here, to calculate the 821 * centuries and years in a century with one division each. This 822 * reduces the number of division operations to two, but is 823 * susceptible to internal range overflow. We make sure the 824 * input operands are in the safe range; this still gives us 825 * approx +/-2.9 million years. 826 */ 827 ntpcal_split res; 828 int32_t n100, n001; /* calendar year cycles */ 829 uint32_t uday, Q, sflag; 830 831 /* split off centuries first */ 832 sflag = int32_sflag(days); 833 uday = uint32_saturate(int32_to_uint32_2cpl(days), sflag); 834 uday = (4u * uday) | 3u; 835 Q = sflag ^ ((sflag ^ uday) / GREGORIAN_CYCLE_DAYS); 836 uday = uday - Q * GREGORIAN_CYCLE_DAYS; 837 n100 = uint32_2cpl_to_int32(Q); 838 839 /* Split off years in century -- days >= 0 here, and we're far 840 * away from integer overflow trouble now. */ 841 uday |= 3; 842 n001 = uday / GREGORIAN_NORMAL_LEAP_CYCLE_DAYS; 843 uday = uday % GREGORIAN_NORMAL_LEAP_CYCLE_DAYS; 844 845 /* Assemble the year and day in year */ 846 res.hi = n100 * 100 + n001; 847 res.lo = uday / 4u; 848 849 /* Eventually set the leap year flag. Note: 0 <= n001 <= 99 and 850 * Q is still the two's complement representation of the 851 * centuries: The modulo 4 ops can be done with masking here. 852 * We also shift the year and the century by one, so the tests 853 * can be done against zero instead of 3. 854 */ 855 if (isleapyear) 856 *isleapyear = !((n001+1) & 3) 857 && ((n001 != 99) || !((Q+1) & 3)); 858 859 return res; 860 } 861 862 /* 863 *--------------------------------------------------------------------- 864 * Given a number of elapsed days in a year and a leap year indicator, 865 * split the number of elapsed days into the number of elapsed months in 866 * 'res.hi' and the number of elapsed days of that month in 'res.lo'. 867 * 868 * This function will fail and return {-1,-1} if the number of elapsed 869 * days is not in the valid range! 870 *--------------------------------------------------------------------- 871 */ 872 ntpcal_split 873 ntpcal_split_yeardays( 874 int32_t eyd, 875 int isleapyear 876 ) 877 { 878 ntpcal_split res; 879 const uint16_t *lt; /* month length table */ 880 881 /* check leap year flag and select proper table */ 882 lt = real_month_table[(isleapyear != 0)]; 883 if (0 <= eyd && eyd < lt[12]) { 884 /* get zero-based month by approximation & correction step */ 885 res.hi = eyd >> 5; /* approx month; might be 1 too low */ 886 if (lt[res.hi + 1] <= eyd) /* fixup approximative month value */ 887 res.hi += 1; 888 res.lo = eyd - lt[res.hi]; 889 } else { 890 res.lo = res.hi = -1; 891 } 892 893 return res; 894 } 895 896 /* 897 *--------------------------------------------------------------------- 898 * Convert a RD into the date part of a 'struct calendar'. 899 *--------------------------------------------------------------------- 900 */ 901 int 902 ntpcal_rd_to_date( 903 struct calendar *jd, 904 int32_t rd 905 ) 906 { 907 ntpcal_split split; 908 int leapy; 909 u_int ymask; 910 911 /* Get day-of-week first. Since rd is signed, the remainder can 912 * be in the range [-6..+6], but the assignment to an unsigned 913 * variable maps the negative values to positive values >=7. 914 * This makes the sign correction look strange, but adding 7 915 * causes the needed wrap-around into the desired value range of 916 * zero to six, both inclusive. 917 */ 918 jd->weekday = rd % DAYSPERWEEK; 919 if (jd->weekday >= DAYSPERWEEK) /* weekday is unsigned! */ 920 jd->weekday += DAYSPERWEEK; 921 922 split = ntpcal_split_eradays(rd - 1, &leapy); 923 /* Get year and day-of-year, with overflow check. If any of the 924 * upper 16 bits is set after shifting to unity-based years, we 925 * will have an overflow when converting to an unsigned 16bit 926 * year. Shifting to the right is OK here, since it does not 927 * matter if the shift is logic or arithmetic. 928 */ 929 split.hi += 1; 930 ymask = 0u - ((split.hi >> 16) == 0); 931 jd->year = (uint16_t)(split.hi & ymask); 932 jd->yearday = (uint16_t)split.lo + 1; 933 934 /* convert to month and mday */ 935 split = ntpcal_split_yeardays(split.lo, leapy); 936 jd->month = (uint8_t)split.hi + 1; 937 jd->monthday = (uint8_t)split.lo + 1; 938 939 return ymask ? leapy : -1; 940 } 941 942 /* 943 *--------------------------------------------------------------------- 944 * Convert a RD into the date part of a 'struct tm'. 945 *--------------------------------------------------------------------- 946 */ 947 int 948 ntpcal_rd_to_tm( 949 struct tm *utm, 950 int32_t rd 951 ) 952 { 953 ntpcal_split split; 954 int leapy; 955 956 /* get day-of-week first */ 957 utm->tm_wday = rd % DAYSPERWEEK; 958 if (utm->tm_wday < 0) 959 utm->tm_wday += DAYSPERWEEK; 960 961 /* get year and day-of-year */ 962 split = ntpcal_split_eradays(rd - 1, &leapy); 963 utm->tm_year = split.hi - 1899; 964 utm->tm_yday = split.lo; /* 0-based */ 965 966 /* convert to month and mday */ 967 split = ntpcal_split_yeardays(split.lo, leapy); 968 utm->tm_mon = split.hi; /* 0-based */ 969 utm->tm_mday = split.lo + 1; /* 1-based */ 970 971 return leapy; 972 } 973 974 /* 975 *--------------------------------------------------------------------- 976 * Take a value of seconds since midnight and split it into hhmmss in a 977 * 'struct calendar'. 978 *--------------------------------------------------------------------- 979 */ 980 int32_t 981 ntpcal_daysec_to_date( 982 struct calendar *jd, 983 int32_t sec 984 ) 985 { 986 int32_t days; 987 int ts[3]; 988 989 days = priv_timesplit(ts, sec); 990 jd->hour = (uint8_t)ts[0]; 991 jd->minute = (uint8_t)ts[1]; 992 jd->second = (uint8_t)ts[2]; 993 994 return days; 995 } 996 997 /* 998 *--------------------------------------------------------------------- 999 * Take a value of seconds since midnight and split it into hhmmss in a 1000 * 'struct tm'. 1001 *--------------------------------------------------------------------- 1002 */ 1003 int32_t 1004 ntpcal_daysec_to_tm( 1005 struct tm *utm, 1006 int32_t sec 1007 ) 1008 { 1009 int32_t days; 1010 int32_t ts[3]; 1011 1012 days = priv_timesplit(ts, sec); 1013 utm->tm_hour = ts[0]; 1014 utm->tm_min = ts[1]; 1015 utm->tm_sec = ts[2]; 1016 1017 return days; 1018 } 1019 1020 /* 1021 *--------------------------------------------------------------------- 1022 * take a split representation for day/second-of-day and day offset 1023 * and convert it to a 'struct calendar'. The seconds will be normalised 1024 * into the range of a day, and the day will be adjusted accordingly. 1025 * 1026 * returns >0 if the result is in a leap year, 0 if in a regular 1027 * year and <0 if the result did not fit into the calendar struct. 1028 *--------------------------------------------------------------------- 1029 */ 1030 int 1031 ntpcal_daysplit_to_date( 1032 struct calendar *jd, 1033 const ntpcal_split *ds, 1034 int32_t dof 1035 ) 1036 { 1037 dof += ntpcal_daysec_to_date(jd, ds->lo); 1038 return ntpcal_rd_to_date(jd, ds->hi + dof); 1039 } 1040 1041 /* 1042 *--------------------------------------------------------------------- 1043 * take a split representation for day/second-of-day and day offset 1044 * and convert it to a 'struct tm'. The seconds will be normalised 1045 * into the range of a day, and the day will be adjusted accordingly. 1046 * 1047 * returns 1 if the result is in a leap year and zero if in a regular 1048 * year. 1049 *--------------------------------------------------------------------- 1050 */ 1051 int 1052 ntpcal_daysplit_to_tm( 1053 struct tm *utm, 1054 const ntpcal_split *ds , 1055 int32_t dof 1056 ) 1057 { 1058 dof += ntpcal_daysec_to_tm(utm, ds->lo); 1059 1060 return ntpcal_rd_to_tm(utm, ds->hi + dof); 1061 } 1062 1063 /* 1064 *--------------------------------------------------------------------- 1065 * Take a UN*X time and convert to a calendar structure. 1066 *--------------------------------------------------------------------- 1067 */ 1068 int 1069 ntpcal_time_to_date( 1070 struct calendar *jd, 1071 const vint64 *ts 1072 ) 1073 { 1074 ntpcal_split ds; 1075 1076 ds = ntpcal_daysplit(ts); 1077 ds.hi += ntpcal_daysec_to_date(jd, ds.lo); 1078 ds.hi += DAY_UNIX_STARTS; 1079 1080 return ntpcal_rd_to_date(jd, ds.hi); 1081 } 1082 1083 1084 /* 1085 * ==================================================================== 1086 * 1087 * merging composite entities 1088 * 1089 * ==================================================================== 1090 */ 1091 1092 /* 1093 *--------------------------------------------------------------------- 1094 * Merge a number of days and a number of seconds into seconds, 1095 * expressed in 64 bits to avoid overflow. 1096 *--------------------------------------------------------------------- 1097 */ 1098 vint64 1099 ntpcal_dayjoin( 1100 int32_t days, 1101 int32_t secs 1102 ) 1103 { 1104 vint64 res; 1105 1106 # if defined(HAVE_INT64) 1107 1108 res.q_s = days; 1109 res.q_s *= SECSPERDAY; 1110 res.q_s += secs; 1111 1112 # else 1113 1114 uint32_t p1, p2; 1115 int isneg; 1116 1117 /* 1118 * res = days *86400 + secs, using manual 16/32 bit 1119 * multiplications and shifts. 1120 */ 1121 isneg = (days < 0); 1122 if (isneg) 1123 days = -days; 1124 1125 /* assemble days * 675 */ 1126 res.D_s.lo = (days & 0xFFFF) * 675u; 1127 res.D_s.hi = 0; 1128 p1 = (days >> 16) * 675u; 1129 p2 = p1 >> 16; 1130 p1 = p1 << 16; 1131 M_ADD(res.D_s.hi, res.D_s.lo, p2, p1); 1132 1133 /* mul by 128, using shift */ 1134 res.D_s.hi = (res.D_s.hi << 7) | (res.D_s.lo >> 25); 1135 res.D_s.lo = (res.D_s.lo << 7); 1136 1137 /* fix sign */ 1138 if (isneg) 1139 M_NEG(res.D_s.hi, res.D_s.lo); 1140 1141 /* properly add seconds */ 1142 p2 = 0; 1143 if (secs < 0) { 1144 p1 = (uint32_t)-secs; 1145 M_NEG(p2, p1); 1146 } else { 1147 p1 = (uint32_t)secs; 1148 } 1149 M_ADD(res.D_s.hi, res.D_s.lo, p2, p1); 1150 1151 # endif 1152 1153 return res; 1154 } 1155 1156 /* 1157 *--------------------------------------------------------------------- 1158 * get leap years since epoch in elapsed years 1159 *--------------------------------------------------------------------- 1160 */ 1161 int32_t 1162 ntpcal_leapyears_in_years( 1163 int32_t years 1164 ) 1165 { 1166 /* We use the in-out-in algorithm here, using the one's 1167 * complement division trick for negative numbers. The chained 1168 * division sequence by 4/25/4 gives the compiler the chance to 1169 * get away with only one true division and doing shifts otherwise. 1170 */ 1171 1172 uint32_t sflag, sum, uyear; 1173 1174 sflag = int32_sflag(years); 1175 uyear = int32_to_uint32_2cpl(years); 1176 uyear ^= sflag; 1177 1178 sum = (uyear /= 4u); /* 4yr rule --> IN */ 1179 sum -= (uyear /= 25u); /* 100yr rule --> OUT */ 1180 sum += (uyear /= 4u); /* 400yr rule --> IN */ 1181 1182 /* Thanks to the alternation of IN/OUT/IN we can do the sum 1183 * directly and have a single one's complement operation 1184 * here. (Only if the years are negative, of course.) Otherwise 1185 * the one's complement would have to be done when 1186 * adding/subtracting the terms. 1187 */ 1188 return uint32_2cpl_to_int32(sflag ^ sum); 1189 } 1190 1191 /* 1192 *--------------------------------------------------------------------- 1193 * Convert elapsed years in Era into elapsed days in Era. 1194 *--------------------------------------------------------------------- 1195 */ 1196 int32_t 1197 ntpcal_days_in_years( 1198 int32_t years 1199 ) 1200 { 1201 return years * DAYSPERYEAR + ntpcal_leapyears_in_years(years); 1202 } 1203 1204 /* 1205 *--------------------------------------------------------------------- 1206 * Convert a number of elapsed month in a year into elapsed days in year. 1207 * 1208 * The month will be normalized, and 'res.hi' will contain the 1209 * excessive years that must be considered when converting the years, 1210 * while 'res.lo' will contain the number of elapsed days since start 1211 * of the year. 1212 * 1213 * This code uses the shifted-month-approach to convert month to days, 1214 * because then there is no need to have explicit leap year 1215 * information. The slight disadvantage is that for most month values 1216 * the result is a negative value, and the year excess is one; the 1217 * conversion is then simply based on the start of the following year. 1218 *--------------------------------------------------------------------- 1219 */ 1220 ntpcal_split 1221 ntpcal_days_in_months( 1222 int32_t m 1223 ) 1224 { 1225 ntpcal_split res; 1226 1227 /* Add ten months and correct if needed. (It likely is...) */ 1228 res.lo = m + 10; 1229 res.hi = (res.lo >= 12); 1230 if (res.hi) 1231 res.lo -= 12; 1232 1233 /* if still out of range, normalise by floor division ... */ 1234 if (res.lo < 0 || res.lo >= 12) { 1235 uint32_t mu, Q, sflag; 1236 sflag = int32_sflag(res.lo); 1237 mu = int32_to_uint32_2cpl(res.lo); 1238 Q = sflag ^ ((sflag ^ mu) / 12u); 1239 res.hi += uint32_2cpl_to_int32(Q); 1240 res.lo = mu - Q * 12u; 1241 } 1242 1243 /* get cummulated days in year with unshift */ 1244 res.lo = shift_month_table[res.lo] - 306; 1245 1246 return res; 1247 } 1248 1249 /* 1250 *--------------------------------------------------------------------- 1251 * Convert ELAPSED years/months/days of gregorian calendar to elapsed 1252 * days in Gregorian epoch. 1253 * 1254 * If you want to convert years and days-of-year, just give a month of 1255 * zero. 1256 *--------------------------------------------------------------------- 1257 */ 1258 int32_t 1259 ntpcal_edate_to_eradays( 1260 int32_t years, 1261 int32_t mons, 1262 int32_t mdays 1263 ) 1264 { 1265 ntpcal_split tmp; 1266 int32_t res; 1267 1268 if (mons) { 1269 tmp = ntpcal_days_in_months(mons); 1270 res = ntpcal_days_in_years(years + tmp.hi) + tmp.lo; 1271 } else 1272 res = ntpcal_days_in_years(years); 1273 res += mdays; 1274 1275 return res; 1276 } 1277 1278 /* 1279 *--------------------------------------------------------------------- 1280 * Convert ELAPSED years/months/days of gregorian calendar to elapsed 1281 * days in year. 1282 * 1283 * Note: This will give the true difference to the start of the given 1284 * year, even if months & days are off-scale. 1285 *--------------------------------------------------------------------- 1286 */ 1287 int32_t 1288 ntpcal_edate_to_yeardays( 1289 int32_t years, 1290 int32_t mons, 1291 int32_t mdays 1292 ) 1293 { 1294 ntpcal_split tmp; 1295 1296 if (0 <= mons && mons < 12) { 1297 years += 1; 1298 mdays += real_month_table[is_leapyear(years)][mons]; 1299 } else { 1300 tmp = ntpcal_days_in_months(mons); 1301 mdays += tmp.lo 1302 + ntpcal_days_in_years(years + tmp.hi) 1303 - ntpcal_days_in_years(years); 1304 } 1305 1306 return mdays; 1307 } 1308 1309 /* 1310 *--------------------------------------------------------------------- 1311 * Convert elapsed days and the hour/minute/second information into 1312 * total seconds. 1313 * 1314 * If 'isvalid' is not NULL, do a range check on the time specification 1315 * and tell if the time input is in the normal range, permitting for a 1316 * single leapsecond. 1317 *--------------------------------------------------------------------- 1318 */ 1319 int32_t 1320 ntpcal_etime_to_seconds( 1321 int32_t hours, 1322 int32_t minutes, 1323 int32_t seconds 1324 ) 1325 { 1326 int32_t res; 1327 1328 res = (hours * MINSPERHR + minutes) * SECSPERMIN + seconds; 1329 1330 return res; 1331 } 1332 1333 /* 1334 *--------------------------------------------------------------------- 1335 * Convert the date part of a 'struct tm' (that is, year, month, 1336 * day-of-month) into the RD of that day. 1337 *--------------------------------------------------------------------- 1338 */ 1339 int32_t 1340 ntpcal_tm_to_rd( 1341 const struct tm *utm 1342 ) 1343 { 1344 return ntpcal_edate_to_eradays(utm->tm_year + 1899, 1345 utm->tm_mon, 1346 utm->tm_mday - 1) + 1; 1347 } 1348 1349 /* 1350 *--------------------------------------------------------------------- 1351 * Convert the date part of a 'struct calendar' (that is, year, month, 1352 * day-of-month) into the RD of that day. 1353 *--------------------------------------------------------------------- 1354 */ 1355 int32_t 1356 ntpcal_date_to_rd( 1357 const struct calendar *jd 1358 ) 1359 { 1360 return ntpcal_edate_to_eradays((int32_t)jd->year - 1, 1361 (int32_t)jd->month - 1, 1362 (int32_t)jd->monthday - 1) + 1; 1363 } 1364 1365 /* 1366 *--------------------------------------------------------------------- 1367 * convert a year number to rata die of year start 1368 *--------------------------------------------------------------------- 1369 */ 1370 int32_t 1371 ntpcal_year_to_ystart( 1372 int32_t year 1373 ) 1374 { 1375 return ntpcal_days_in_years(year - 1) + 1; 1376 } 1377 1378 /* 1379 *--------------------------------------------------------------------- 1380 * For a given RD, get the RD of the associated year start, 1381 * that is, the RD of the last January,1st on or before that day. 1382 *--------------------------------------------------------------------- 1383 */ 1384 int32_t 1385 ntpcal_rd_to_ystart( 1386 int32_t rd 1387 ) 1388 { 1389 /* 1390 * Rather simple exercise: split the day number into elapsed 1391 * years and elapsed days, then remove the elapsed days from the 1392 * input value. Nice'n sweet... 1393 */ 1394 return rd - ntpcal_split_eradays(rd - 1, NULL).lo; 1395 } 1396 1397 /* 1398 *--------------------------------------------------------------------- 1399 * For a given RD, get the RD of the associated month start. 1400 *--------------------------------------------------------------------- 1401 */ 1402 int32_t 1403 ntpcal_rd_to_mstart( 1404 int32_t rd 1405 ) 1406 { 1407 ntpcal_split split; 1408 int leaps; 1409 1410 split = ntpcal_split_eradays(rd - 1, &leaps); 1411 split = ntpcal_split_yeardays(split.lo, leaps); 1412 1413 return rd - split.lo; 1414 } 1415 1416 /* 1417 *--------------------------------------------------------------------- 1418 * take a 'struct calendar' and get the seconds-of-day from it. 1419 *--------------------------------------------------------------------- 1420 */ 1421 int32_t 1422 ntpcal_date_to_daysec( 1423 const struct calendar *jd 1424 ) 1425 { 1426 return ntpcal_etime_to_seconds(jd->hour, jd->minute, 1427 jd->second); 1428 } 1429 1430 /* 1431 *--------------------------------------------------------------------- 1432 * take a 'struct tm' and get the seconds-of-day from it. 1433 *--------------------------------------------------------------------- 1434 */ 1435 int32_t 1436 ntpcal_tm_to_daysec( 1437 const struct tm *utm 1438 ) 1439 { 1440 return ntpcal_etime_to_seconds(utm->tm_hour, utm->tm_min, 1441 utm->tm_sec); 1442 } 1443 1444 /* 1445 *--------------------------------------------------------------------- 1446 * take a 'struct calendar' and convert it to a 'time_t' 1447 *--------------------------------------------------------------------- 1448 */ 1449 time_t 1450 ntpcal_date_to_time( 1451 const struct calendar *jd 1452 ) 1453 { 1454 vint64 join; 1455 int32_t days, secs; 1456 1457 days = ntpcal_date_to_rd(jd) - DAY_UNIX_STARTS; 1458 secs = ntpcal_date_to_daysec(jd); 1459 join = ntpcal_dayjoin(days, secs); 1460 1461 return vint64_to_time(&join); 1462 } 1463 1464 1465 /* 1466 * ==================================================================== 1467 * 1468 * extended and unchecked variants of caljulian/caltontp 1469 * 1470 * ==================================================================== 1471 */ 1472 int 1473 ntpcal_ntp64_to_date( 1474 struct calendar *jd, 1475 const vint64 *ntp 1476 ) 1477 { 1478 ntpcal_split ds; 1479 1480 ds = ntpcal_daysplit(ntp); 1481 ds.hi += ntpcal_daysec_to_date(jd, ds.lo); 1482 1483 return ntpcal_rd_to_date(jd, ds.hi + DAY_NTP_STARTS); 1484 } 1485 1486 int 1487 ntpcal_ntp_to_date( 1488 struct calendar *jd, 1489 uint32_t ntp, 1490 const time_t *piv 1491 ) 1492 { 1493 vint64 ntp64; 1494 1495 /* 1496 * Unfold ntp time around current time into NTP domain. Split 1497 * into days and seconds, shift days into CE domain and 1498 * process the parts. 1499 */ 1500 ntp64 = ntpcal_ntp_to_ntp(ntp, piv); 1501 return ntpcal_ntp64_to_date(jd, &ntp64); 1502 } 1503 1504 1505 vint64 1506 ntpcal_date_to_ntp64( 1507 const struct calendar *jd 1508 ) 1509 { 1510 /* 1511 * Convert date to NTP. Ignore yearday, use d/m/y only. 1512 */ 1513 return ntpcal_dayjoin(ntpcal_date_to_rd(jd) - DAY_NTP_STARTS, 1514 ntpcal_date_to_daysec(jd)); 1515 } 1516 1517 1518 uint32_t 1519 ntpcal_date_to_ntp( 1520 const struct calendar *jd 1521 ) 1522 { 1523 /* 1524 * Get lower half of 64-bit NTP timestamp from date/time. 1525 */ 1526 return ntpcal_date_to_ntp64(jd).d_s.lo; 1527 } 1528 1529 1530 1531 /* 1532 * ==================================================================== 1533 * 1534 * day-of-week calculations 1535 * 1536 * ==================================================================== 1537 */ 1538 /* 1539 * Given a RataDie and a day-of-week, calculate a RDN that is reater-than, 1540 * greater-or equal, closest, less-or-equal or less-than the given RDN 1541 * and denotes the given day-of-week 1542 */ 1543 int32_t 1544 ntpcal_weekday_gt( 1545 int32_t rdn, 1546 int32_t dow 1547 ) 1548 { 1549 return ntpcal_periodic_extend(rdn+1, dow, 7); 1550 } 1551 1552 int32_t 1553 ntpcal_weekday_ge( 1554 int32_t rdn, 1555 int32_t dow 1556 ) 1557 { 1558 return ntpcal_periodic_extend(rdn, dow, 7); 1559 } 1560 1561 int32_t 1562 ntpcal_weekday_close( 1563 int32_t rdn, 1564 int32_t dow 1565 ) 1566 { 1567 return ntpcal_periodic_extend(rdn-3, dow, 7); 1568 } 1569 1570 int32_t 1571 ntpcal_weekday_le( 1572 int32_t rdn, 1573 int32_t dow 1574 ) 1575 { 1576 return ntpcal_periodic_extend(rdn, dow, -7); 1577 } 1578 1579 int32_t 1580 ntpcal_weekday_lt( 1581 int32_t rdn, 1582 int32_t dow 1583 ) 1584 { 1585 return ntpcal_periodic_extend(rdn-1, dow, -7); 1586 } 1587 1588 /* 1589 * ==================================================================== 1590 * 1591 * ISO week-calendar conversions 1592 * 1593 * The ISO8601 calendar defines a calendar of years, weeks and weekdays. 1594 * It is related to the Gregorian calendar, and a ISO year starts at the 1595 * Monday closest to Jan,1st of the corresponding Gregorian year. A ISO 1596 * calendar year has always 52 or 53 weeks, and like the Grogrian 1597 * calendar the ISO8601 calendar repeats itself every 400 years, or 1598 * 146097 days, or 20871 weeks. 1599 * 1600 * While it is possible to write ISO calendar functions based on the 1601 * Gregorian calendar functions, the following implementation takes a 1602 * different approach, based directly on years and weeks. 1603 * 1604 * Analysis of the tabulated data shows that it is not possible to 1605 * interpolate from years to weeks over a full 400 year range; cyclic 1606 * shifts over 400 years do not provide a solution here. But it *is* 1607 * possible to interpolate over every single century of the 400-year 1608 * cycle. (The centennial leap year rule seems to be the culprit here.) 1609 * 1610 * It can be shown that a conversion from years to weeks can be done 1611 * using a linear transformation of the form 1612 * 1613 * w = floor( y * a + b ) 1614 * 1615 * where the slope a must hold to 1616 * 1617 * 52.1780821918 <= a < 52.1791044776 1618 * 1619 * and b must be chosen according to the selected slope and the number 1620 * of the century in a 400-year period. 1621 * 1622 * The inverse calculation can also be done in this way. Careful scaling 1623 * provides an unlimited set of integer coefficients a,k,b that enable 1624 * us to write the calulation in the form 1625 * 1626 * w = (y * a + b ) / k 1627 * y = (w * a' + b') / k' 1628 * 1629 * In this implementation the values of k and k' are chosen to be 1630 * smallest possible powers of two, so the division can be implemented 1631 * as shifts if the optimiser chooses to do so. 1632 * 1633 * ==================================================================== 1634 */ 1635 1636 /* 1637 * Given a number of elapsed (ISO-)years since the begin of the 1638 * christian era, return the number of elapsed weeks corresponding to 1639 * the number of years. 1640 */ 1641 int32_t 1642 isocal_weeks_in_years( 1643 int32_t years 1644 ) 1645 { 1646 /* 1647 * use: w = (y * 53431 + b[c]) / 1024 as interpolation 1648 */ 1649 static const uint16_t bctab[4] = { 157, 449, 597, 889 }; 1650 1651 int32_t cs, cw; 1652 uint32_t cc, ci, yu, sflag; 1653 1654 sflag = int32_sflag(years); 1655 yu = int32_to_uint32_2cpl(years); 1656 1657 /* split off centuries, using floor division */ 1658 cc = sflag ^ ((sflag ^ yu) / 100u); 1659 yu -= cc * 100u; 1660 1661 /* calculate century cycles shift and cycle index: 1662 * Assuming a century is 5217 weeks, we have to add a cycle 1663 * shift that is 3 for every 4 centuries, because 3 of the four 1664 * centuries have 5218 weeks. So '(cc*3 + 1) / 4' is the actual 1665 * correction, and the second century is the defective one. 1666 * 1667 * Needs floor division by 4, which is done with masking and 1668 * shifting. 1669 */ 1670 ci = cc * 3u + 1; 1671 cs = uint32_2cpl_to_int32(sflag ^ ((sflag ^ ci) / 4u)); 1672 ci = ci % 4u; 1673 1674 /* Get weeks in century. Can use plain division here as all ops 1675 * are >= 0, and let the compiler sort out the possible 1676 * optimisations. 1677 */ 1678 cw = (yu * 53431u + bctab[ci]) / 1024u; 1679 1680 return uint32_2cpl_to_int32(cc) * 5217 + cs + cw; 1681 } 1682 1683 /* 1684 * Given a number of elapsed weeks since the begin of the christian 1685 * era, split this number into the number of elapsed years in res.hi 1686 * and the excessive number of weeks in res.lo. (That is, res.lo is 1687 * the number of elapsed weeks in the remaining partial year.) 1688 */ 1689 ntpcal_split 1690 isocal_split_eraweeks( 1691 int32_t weeks 1692 ) 1693 { 1694 /* 1695 * use: y = (w * 157 + b[c]) / 8192 as interpolation 1696 */ 1697 1698 static const uint16_t bctab[4] = { 85, 130, 17, 62 }; 1699 1700 ntpcal_split res; 1701 int32_t cc, ci; 1702 uint32_t sw, cy, Q, sflag; 1703 1704 /* Use two fast cycle-split divisions here. This is again 1705 * susceptible to internal overflow, so we check the range. This 1706 * still permits more than +/-20 million years, so this is 1707 * likely a pure academical problem. 1708 * 1709 * We want to execute '(weeks * 4 + 2) /% 20871' under floor 1710 * division rules in the first step. 1711 */ 1712 sflag = int32_sflag(weeks); 1713 sw = uint32_saturate(int32_to_uint32_2cpl(weeks), sflag); 1714 sw = 4u * sw + 2; 1715 Q = sflag ^ ((sflag ^ sw) / GREGORIAN_CYCLE_WEEKS); 1716 sw -= Q * GREGORIAN_CYCLE_WEEKS; 1717 ci = Q % 4u; 1718 cc = uint32_2cpl_to_int32(Q); 1719 1720 /* Split off years; sw >= 0 here! The scaled weeks in the years 1721 * are scaled up by 157 afterwards. 1722 */ 1723 sw = (sw / 4u) * 157u + bctab[ci]; 1724 cy = sw / 8192u; /* ws >> 13 , let the compiler sort it out */ 1725 sw = sw % 8192u; /* ws & 8191, let the compiler sort it out */ 1726 1727 /* assemble elapsed years and downscale the elapsed weeks in 1728 * the year. 1729 */ 1730 res.hi = 100*cc + cy; 1731 res.lo = sw / 157u; 1732 1733 return res; 1734 } 1735 1736 /* 1737 * Given a second in the NTP time scale and a pivot, expand the NTP 1738 * time stamp around the pivot and convert into an ISO calendar time 1739 * stamp. 1740 */ 1741 int 1742 isocal_ntp64_to_date( 1743 struct isodate *id, 1744 const vint64 *ntp 1745 ) 1746 { 1747 ntpcal_split ds; 1748 int32_t ts[3]; 1749 uint32_t uw, ud, sflag; 1750 1751 /* 1752 * Split NTP time into days and seconds, shift days into CE 1753 * domain and process the parts. 1754 */ 1755 ds = ntpcal_daysplit(ntp); 1756 1757 /* split time part */ 1758 ds.hi += priv_timesplit(ts, ds.lo); 1759 id->hour = (uint8_t)ts[0]; 1760 id->minute = (uint8_t)ts[1]; 1761 id->second = (uint8_t)ts[2]; 1762 1763 /* split days into days and weeks, using floor division in unsigned */ 1764 ds.hi += DAY_NTP_STARTS - 1; /* shift from NTP to RDN */ 1765 sflag = int32_sflag(ds.hi); 1766 ud = int32_to_uint32_2cpl(ds.hi); 1767 uw = sflag ^ ((sflag ^ ud) / DAYSPERWEEK); 1768 ud -= uw * DAYSPERWEEK; 1769 ds.hi = uint32_2cpl_to_int32(uw); 1770 ds.lo = ud; 1771 1772 id->weekday = (uint8_t)ds.lo + 1; /* weekday result */ 1773 1774 /* get year and week in year */ 1775 ds = isocal_split_eraweeks(ds.hi); /* elapsed years&week*/ 1776 id->year = (uint16_t)ds.hi + 1; /* shift to current */ 1777 id->week = (uint8_t )ds.lo + 1; 1778 1779 return (ds.hi >= 0 && ds.hi < 0x0000FFFF); 1780 } 1781 1782 int 1783 isocal_ntp_to_date( 1784 struct isodate *id, 1785 uint32_t ntp, 1786 const time_t *piv 1787 ) 1788 { 1789 vint64 ntp64; 1790 1791 /* 1792 * Unfold ntp time around current time into NTP domain, then 1793 * convert the full time stamp. 1794 */ 1795 ntp64 = ntpcal_ntp_to_ntp(ntp, piv); 1796 return isocal_ntp64_to_date(id, &ntp64); 1797 } 1798 1799 /* 1800 * Convert a ISO date spec into a second in the NTP time scale, 1801 * properly truncated to 32 bit. 1802 */ 1803 vint64 1804 isocal_date_to_ntp64( 1805 const struct isodate *id 1806 ) 1807 { 1808 int32_t weeks, days, secs; 1809 1810 weeks = isocal_weeks_in_years((int32_t)id->year - 1) 1811 + (int32_t)id->week - 1; 1812 days = weeks * 7 + (int32_t)id->weekday; 1813 /* days is RDN of ISO date now */ 1814 secs = ntpcal_etime_to_seconds(id->hour, id->minute, id->second); 1815 1816 return ntpcal_dayjoin(days - DAY_NTP_STARTS, secs); 1817 } 1818 1819 uint32_t 1820 isocal_date_to_ntp( 1821 const struct isodate *id 1822 ) 1823 { 1824 /* 1825 * Get lower half of 64-bit NTP timestamp from date/time. 1826 */ 1827 return isocal_date_to_ntp64(id).d_s.lo; 1828 } 1829 1830 /* 1831 * ==================================================================== 1832 * 'basedate' support functions 1833 * ==================================================================== 1834 */ 1835 1836 static int32_t s_baseday = NTP_TO_UNIX_DAYS; 1837 1838 int32_t 1839 basedate_eval_buildstamp(void) 1840 { 1841 struct calendar jd; 1842 int32_t ed; 1843 1844 if (!ntpcal_get_build_date(&jd)) 1845 return NTP_TO_UNIX_DAYS; 1846 1847 /* The time zone of the build stamp is unspecified; we remove 1848 * one day to provide a certain slack. And in case somebody 1849 * fiddled with the system clock, we make sure we do not go 1850 * before the UNIX epoch (1970-01-01). It's probably not possible 1851 * to do this to the clock on most systems, but there are other 1852 * ways to tweak the build stamp. 1853 */ 1854 jd.monthday -= 1; 1855 ed = ntpcal_date_to_rd(&jd) - DAY_NTP_STARTS; 1856 return (ed < NTP_TO_UNIX_DAYS) ? NTP_TO_UNIX_DAYS : ed; 1857 } 1858 1859 int32_t 1860 basedate_eval_string( 1861 const char * str 1862 ) 1863 { 1864 u_short y,m,d; 1865 u_long ned; 1866 int rc, nc; 1867 size_t sl; 1868 1869 sl = strlen(str); 1870 rc = sscanf(str, "%4hu-%2hu-%2hu%n", &y, &m, &d, &nc); 1871 if (rc == 3 && (size_t)nc == sl) { 1872 if (m >= 1 && m <= 12 && d >= 1 && d <= 31) 1873 return ntpcal_edate_to_eradays(y-1, m-1, d) 1874 - DAY_NTP_STARTS; 1875 goto buildstamp; 1876 } 1877 1878 rc = sscanf(str, "%lu%n", &ned, &nc); 1879 if (rc == 1 && (size_t)nc == sl) { 1880 if (ned <= INT32_MAX) 1881 return (int32_t)ned; 1882 goto buildstamp; 1883 } 1884 1885 buildstamp: 1886 msyslog(LOG_WARNING, 1887 "basedate string \"%s\" invalid, build date substituted!", 1888 str); 1889 return basedate_eval_buildstamp(); 1890 } 1891 1892 uint32_t 1893 basedate_get_day(void) 1894 { 1895 return s_baseday; 1896 } 1897 1898 int32_t 1899 basedate_set_day( 1900 int32_t day 1901 ) 1902 { 1903 struct calendar jd; 1904 int32_t retv; 1905 1906 if (day < NTP_TO_UNIX_DAYS) { 1907 msyslog(LOG_WARNING, 1908 "baseday_set_day: invalid day (%lu), UNIX epoch substituted", 1909 (unsigned long)day); 1910 day = NTP_TO_UNIX_DAYS; 1911 } 1912 retv = s_baseday; 1913 s_baseday = day; 1914 ntpcal_rd_to_date(&jd, day + DAY_NTP_STARTS); 1915 msyslog(LOG_INFO, "basedate set to %04hu-%02hu-%02hu", 1916 jd.year, (u_short)jd.month, (u_short)jd.monthday); 1917 return retv; 1918 } 1919 1920 time_t 1921 basedate_get_eracenter(void) 1922 { 1923 time_t retv; 1924 retv = (time_t)(s_baseday - NTP_TO_UNIX_DAYS); 1925 retv *= SECSPERDAY; 1926 retv += (UINT32_C(1) << 31); 1927 return retv; 1928 } 1929 1930 time_t 1931 basedate_get_erabase(void) 1932 { 1933 time_t retv; 1934 retv = (time_t)(s_baseday - NTP_TO_UNIX_DAYS); 1935 retv *= SECSPERDAY; 1936 return retv; 1937 } 1938 1939 /* -*-EOF-*- */ 1940