Annotation of embedaddon/ntp/libntp/caltontp.c, revision 1.1
1.1 ! misho 1: /*
! 2: * caltontp - convert a date to an NTP time
! 3: */
! 4: #include <sys/types.h>
! 5:
! 6: #include "ntp_types.h"
! 7: #include "ntp_calendar.h"
! 8: #include "ntp_stdlib.h"
! 9: #include "ntp_assert.h"
! 10:
! 11: /*
! 12: * Juergen Perlinger, 2008-11-12
! 13: * Add support for full calendar calculatios. If the day-of-year is provided
! 14: * (that is, not zero) it will be used instead of month and day-of-month;
! 15: * otherwise a full turn through the calendar calculations will be taken.
! 16: *
! 17: * I know that Harlan Stenn likes to see assertions in production code, and I
! 18: * agree there, but it would be a tricky thing here. The algorithm is quite
! 19: * capable of producing sensible answers even to seemingly weird inputs: the
! 20: * date <any year here>-03-00, the 0.th March of the year, will be automtically
! 21: * treated as the last day of February, no matter whether the year is a leap
! 22: * year or not. So adding constraints is merely for the benefit of the callers,
! 23: * because the only thing we can check for consistency is our input, produced
! 24: * by somebody else.
! 25: *
! 26: * BTW: A total roundtrip using 'caljulian' would be a quite shaky thing:
! 27: * Because of the truncation of the NTP time stamp to 32 bits and the epoch
! 28: * unfolding around the current time done by 'caljulian' the roundtrip does
! 29: * *not* necessarily reproduce the input, especially if the time spec is more
! 30: * than 68 years off from the current time...
! 31: */
! 32: u_long
! 33: caltontp(
! 34: const struct calendar *jt
! 35: )
! 36: {
! 37: ntp_u_int32_t days; /* full days in NTP epoch */
! 38: ntp_u_int32_t years; /* complete ACE years before date */
! 39: ntp_u_int32_t month; /* adjusted month for calendar */
! 40:
! 41: NTP_INSIST(jt != NULL);
! 42:
! 43: NTP_REQUIRE(jt->month <= 13); /* permit month 0..13! */
! 44: NTP_REQUIRE(jt->monthday <= 32);
! 45: NTP_REQUIRE(jt->yearday <= 366);
! 46: NTP_REQUIRE(jt->hour <= 24);
! 47: NTP_REQUIRE(jt->minute <= MINSPERHR);
! 48: NTP_REQUIRE(jt->second <= SECSPERMIN);
! 49:
! 50: /*
! 51: * First convert the date to fully elapsed days since NTP epoch. The
! 52: * expressions used here give us initially days since 0001-01-01, the
! 53: * beginning of the christian era in the proleptic gregorian calendar;
! 54: * they are rebased on-the-fly into days since beginning of the NTP
! 55: * epoch, 1900-01-01.
! 56: */
! 57: if (jt->yearday) {
! 58: /*
! 59: * Assume that the day-of-year contains a useable value and
! 60: * avoid all calculations involving month and day-of-month.
! 61: */
! 62: years = jt->year - 1;
! 63: days = years * DAYSPERYEAR /* days in previous years */
! 64: + years / 4 /* plus prior years's leap days */
! 65: - years / 100 /* minus leapless century years */
! 66: + years / 400 /* plus leapful Gregorian yrs */
! 67: + jt->yearday /* days this year */
! 68: - DAY_NTP_STARTS; /* rebase to NTP epoch */
! 69: } else {
! 70: /*
! 71: * The following code is according to the excellent book
! 72: * 'Calendrical Calculations' by Nachum Dershowitz and Edward
! 73: * Reingold. It does a full calendar evaluation, using one of
! 74: * the alternate algorithms: Shift to a hypothetical year
! 75: * starting on the previous march,1st; merge years, month and
! 76: * days; undo the the 9 month shift (which is 306 days). The
! 77: * advantage is that we do NOT need to now whether a year is a
! 78: * leap year or not, because the leap day is the LAST day of
! 79: * the year.
! 80: */
! 81: month = (ntp_u_int32_t)jt->month + 9;
! 82: years = jt->year - 1 + month / 12;
! 83: month %= 12;
! 84: days = years * DAYSPERYEAR /* days in previous years */
! 85: + years / 4 /* plus prior years's leap days */
! 86: - years / 100 /* minus leapless century years */
! 87: + years / 400 /* plus leapful Gregorian yrs */
! 88: + (month * 153 + 2) / 5 /* plus days before month */
! 89: + jt->monthday /* plus day-of-month */
! 90: - 306 /* minus 9 months */
! 91: - DAY_NTP_STARTS; /* rebase to NTP epoch */
! 92: }
! 93:
! 94: /*
! 95: * Do the obvious: Merge everything together, making sure integer
! 96: * promotion doesn't play dirty tricks on us; there is probably some
! 97: * redundancy in the casts, but this drives it home with force. All
! 98: * arithmetic is done modulo 2**32, because the result is truncated
! 99: * anyway.
! 100: */
! 101: return days * SECSPERDAY
! 102: + (ntp_u_int32_t)jt->hour * MINSPERHR*SECSPERMIN
! 103: + (ntp_u_int32_t)jt->minute * SECSPERMIN
! 104: + (ntp_u_int32_t)jt->second;
! 105: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>