# [ntp:questions] Re: Jonathan Buzzard's radioclkd and FreeBSD

Terje Mathisen terje.mathisen at hda.hydro.com
Mon Nov 10 12:23:54 UTC 2003

```Wolfgang S. Rupprecht wrote:
> Unix really needs a lightweight UTC_tm to seconds_since_the_epoch
> routine.  Documenting and using it is the best way to get it into the

I'm afraid that it is missing simply because it was deemed to be too
trivial to deserve library inclusion. :-(

The only real problem in that direction is the leap handling, the rest
is just a couple of multiplications and a month-table lookup.

Probably about 20+ cycles.

Here's the hardest part, going from YMD to day number. Subtract the day
number of the epoch, multiply by 86400 and add the number of seconds in
the current day:

t = ymd2days((unsigned) tm->tm_year + 1900, (unsigned) tm->tm_mon + 1,
(unsigned) tm->tm_day);

t -= STARTDATE_OFFSET;

t += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;

Here's the function:

/* These operations are valid for any date after 1600-03-01,
according to the modern calendar
*/
#define STARTYEAR 1600
#define MASKSHIFT (8 * sizeof(int) - 1) /* 31 on a 32-bit machine */

/* Table to simplify conversion between mm-dd and day_in_year */
static daysToMonth[13] = {-1,30,60,91,121,152,183,213,244,274,305,336,366};

unsigned ymd2days(unsigned y, unsigned m, unsigned d)
{
unsigned days, y100;
int mask = (int) (m -= 3);
mask >>= MASKSHIFT;		/* mask is -1 if jan or feb */
m += (mask & 12);		/* Make believe the year starts in March */
y -= STARTYEAR;
y100 = y / 100;			/* Centuries for leap year calc */
days = y * 365 + (y >> 2) - y100 + (y100 >> 2);
days += (unsigned) daysToMonth[m] + d;

return days;
}

Terje
--
- <Terje.Mathisen at hda.hydro.com>
"almost all programming can be viewed as an exercise in caching"

```