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>