[alt.sources.d] Looking for a tool to make UNIX-Time

jfh@rpp386.cactus.org (John F. Haugh II) (11/26/90)

In article <1948@necisa.ho.necisa.oz> boyd@necisa.ho.necisa.oz (Boyd Roberts) writes:
>Here's a mktime() sort of thing based on calling localtime(3) and
>binary chopping on a guessed UNIX time long.  Ok?

gack!  you can compute it directly without looping.  if you don't
care about daylight savings time corrections you can get it without
ever having to call localtime.

this is what i use in "chage" to compute "days since the epoch".  don't
forget to multiply by (3600*24) to get seconds.  i've not completely
debugged this fragment - it is part of the next version of that command.

-- slice and dice as needed ... --
/*
 * Copyright 1990, John F. Haugh II
 * All rights reserved.
 *
 * Use, duplication, and disclosure prohibited without
 * the express written permission of the author.
 */

#include <sys/types.h>
#include <time.h>

/*
 * days and juldays are used to compute the number of days in the
 * current month, and the cummulative number of days in the preceding
 * months.  they are declared so that january is 1, not 0.
 */

static	short	days[13] = { 0,
	31,	28,	31,	30,	31,	30,	/* JAN - JUN */
	31,	31,	30,	31,	30,	31 };	/* JUL - DEC */

static	short	juldays[13] = { 0,
	0,	31,	59,	90,	120,	151,	/* JAN - JUN */
	181,	212,	243,	273,	304,	334 };	/* JUL - DEC */

/*
 * strtoday - compute the number of days since 1970.
 *
 * the total number of days prior to the current date is
 * computed.  january 1, 1970 is used as the origin with
 * it having a day number of 0.  the gmtime() routine is
 * used to prevent confusion regarding time zones.
 */

long
strtoday (str)
char	*str;
{
	int	month;
	int	day;
	int	year;
	long	total;

	/*
	 * start by separating the month, day and year.  this is
	 * a chauvanistic program - it only takes date input in
	 * the standard USA format.
	 */

	if (sscanf (str, "%d/%d/%d", &month, &day, &year) != 3)
		return -1;

	/*
	 * the month, day of the month, and year are checked for
	 * correctness and the year adjusted so it falls between
	 * 1970 and 2069.
	 */

	if (month < 1 || month > 12)
		return -1;

	if (day < 1)
		return -1;

	if ((month != 2 || (year % 4) != 0) && day > days[month])
		return -1;
	else if (day > 29)
		return -1;

	if (year < 0)
		return -1;
	else if (year < 70)
		year += 2000;
	else if (year < 99)
		year += 1900;

	if (year < 1970 || year > 2069)
		return -1;

	/*
	 * the total number of days is the total number of days in all
	 * the whole years, plus the number of leap days, plus the
	 * number of days in the whole months preceding, plus the number
	 * of days so far in the month.
	 */

	total = ((year - 1970) * 365) + (((year + 1) - 1970) / 4);
	total += juldays[month] + (month > 2 && (year % 4) == 0 ? 1:0);
	total += day - 1;

	return total;
}
-- 
John F. Haugh II                             UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832                           Domain: jfh@rpp386.cactus.org
"SCCS, the source motel!  Programs check in and never check out!"
		-- Ken Thompson

boyd@necisa.ho.necisa.oz (Boyd Roberts) (11/28/90)

In article <18748@rpp386.cactus.org> jfh@rpp386.cactus.org (John F. Haugh II) writes:
>
>gack!  you can compute it directly without looping.  if you don't
>care about daylight savings time corrections you can get it without
>ever having to call localtime.
>

Yeah, just what the guy wanted.  Bugger correctness -- I mean you wouldn't
want to write code that was actually _correct_, would you now?

``As long as you don't care that it works'' -- a truly fine philosophy.


Boyd Roberts			boyd@necisa.ho.necisa.oz.au

``When the going gets wierd, the weird turn pro...''

xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan) (11/28/90)

boyd@necisa.ho.necisa.oz (Boyd Roberts) writes in alt.sources.d:
> jfh@rpp386.cactus.org (John F. Haugh II) writes:

>>gack!  you can compute it directly without looping.  if you don't
>>care about daylight savings time corrections you can get it without
>>ever having to call localtime.


>Yeah, just what the guy wanted.  Bugger correctness -- I mean you wouldn't
>want to write code that was actually _correct_, would you now?

>``As long as you don't care that it works'' -- a truly fine philosophy.


Yep, that's our John Haugh.  Any wonder, with coding habits like that,
that he needs and is promoting the return of comp.unix.wizards, so he
can have an audience unskilled enough to think of him as a real programmer?

The scary thing is that he earns his living as a coding consultant, when
he's not busy libeling people on the net or making a fool of himself all
over the place.

Kent, the man from xanth.
<xanthian@Zorch.SF-Bay.ORG> <xanthian@well.sf.ca.us>

jfh@rpp386.cactus.org (John F. Haugh II) (11/28/90)

In article <1949@necisa.ho.necisa.oz> boyd@necisa.ho.necisa.oz (Boyd Roberts) writes:
>In article <18748@rpp386.cactus.org> jfh@rpp386.cactus.org (John F. Haugh II) writes:
>>gack!  you can compute it directly without looping.  if you don't
>>care about daylight savings time corrections you can get it without
>>ever having to call localtime.
>
>Yeah, just what the guy wanted.  Bugger correctness -- I mean you wouldn't
>want to write code that was actually _correct_, would you now?

Your algorithm makes 31 calls to localtime because it has to figure out
(2 ^ 31) possible dates by binary decomposition.  Let's pretend for a
moment that my algorithm takes as much time as one call to localtime()
to get the initial guess.  Now the code gets within 1 day of the correct
time, which is 86,400 seconds.  It would take ceil(Log2(86,400)) = 17
calls to localtime to resolve the hard way, or ceil(Log2(24)) = 5 if
you do it cleverly.  Adding in the fudge factor means taking a bad guess
saves you about 40%, and being cleverer saves you about 80%, or roughly
5 times as fast.

>``As long as you don't care that it works'' -- a truly fine philosophy.

Hey, you can always take the guess my algorithm produces and plug it
into your little binary guess thingy.  Of course, you don't actually
need to completely figure it out, just figure if daylight savings time
came or went that day.

It is rumored that a major vendor once had a FORTRAN integer square
root routine which was coded as (modulo syntax errors and such)

	INTEGER FUNCTION SQRT (N)
	DO 100 I = 1,65535
	IF I * I .GT. N RETURN I - 1
100	CONTINUE
	RETURN 0

Hey - it also worked.  It just took a little longer.
-- 
John F. Haugh II                             UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832                           Domain: jfh@rpp386.cactus.org
"SCCS, the source motel!  Programs check in and never check out!"
		-- Ken Thompson

Sm@cerberus.bhpese.oz.au (Scott Merrilees) (11/29/90)

In article <18748@rpp386.cactus.org> jfh@rpp386.cactus.org (John F. Haugh II) writes:
>gack!  you can compute it directly without looping.  if you don't
>care about daylight savings time corrections you can get it without
>ever having to call localtime.

But then you have to know all the garbage about when daylight savings
time cuts in/out, leap years etc.  This solution is simple, has a
few guesses, and will work anywhere without telling it extra stuff.
It may not be terribly efficient, but probably won't be called that
often.  I like both it, and the side step to think of doing it that
way.

Sm
-- 
Scott Merrilees, BHP Information Technology, Newcastle, Australia
Internet: Sm@bhpese.oz.au                    Phone: +61 49 402132

jfh@rpp386.cactus.org (John F. Haugh II) (11/30/90)

In article <1990Nov29.040427.15103@cerberus.bhpese.oz.au> Sm@cerberus.bhpese.oz.au (Scott Merrilees) writes:
>But then you have to know all the garbage about when daylight savings
>time cuts in/out, leap years etc.  This solution is simple, has a
>few guesses, and will work anywhere without telling it extra stuff.
>It may not be terribly efficient, but probably won't be called that
>often.  I like both it, and the side step to think of doing it that
>way.

I'm really sorry that you and Gregory have decided to attack my
suggestion without trying to do anything with it.

The code correctly gets within 48 hours of the day you want,
regardless of leap years, time zones, daylight savings time,
etc.  All that is left is figuring out how many hours off
the guess was.  That is very trivial and only requires one
or two calls to localtime to get.  It is very easy to figure
out the difference between two very close dates, so the hours
fall out very quickly.  Extending to support hours, minutes
and seconds is painless.

Sure, the original posted solution is "correct", but then
so would be starting at 0 and counting up by ones.  Binary
approximation is a very old technique.  It is not new or
clever.  It is a lazy solution to a really simple problem.
Clever would have been binary approximation using whole
hours or days, both of which would have been an improvement
and would have shown some thought.

As for not being called all that often, what if the application
is something like "expire" which must deal with textual dates
in article headers?  Still think it won't be called that often?
-- 
John F. Haugh II                             UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832                           Domain: jfh@rpp386.cactus.org
"SCCS, the source motel!  Programs check in and never check out!"
		-- Ken Thompson

jfh@rpp386.cactus.org (John F. Haugh II) (11/30/90)

In article <1990Nov28.065101.13081@zorch.SF-Bay.ORG> xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan) writes:
>Yep, that's our John Haugh.  Any wonder, with coding habits like that,
>that he needs and is promoting the return of comp.unix.wizards, so he
>can have an audience unskilled enough to think of him as a real programmer?

Oh great, K*nt Paul Dolan.  Official net.mental-case.  K*nt, haven't
you had enough?  =I= admit my code has bugs.  Can you make the
same claims?  I don't know - frankly I never see code with your
name on it.

Okay, since K*nt cares so much, let's see what kind of interesting
bugs there might be in the program which Boyd Roberts posted the
other day.  The advantage to admitting you have bugs in your code
is that when some idiot like me comes along and points them out
you get to say "Gee, Thanks" instead of eating crow because you
pretended to write bug free code or pretending the problem isn't
really a bug.

Let's suppose for a moment that you are running your program in
the central time zone.  Let's suppose for a moment that you are
running it on October 28th around 1:51 am.  Let's suppose for a
moment that you are running it for every second of that fateful
minute.

What you will see is that 10/28/90 01:51:44 returns 657,096,704
seconds and that 10/28/90 01:51:45 returns 657,100,305, which is
hardly one second more.  It is, in fact 3601 seconds more, which
means that according to Boyd Roberts daylight savings time starts
at 1:51:45, and not 1:00 or 2:00 or whatever.

You have to understand the algorithm to understand the source of
the error.  The first time is 0x272A8000.  When the next second
rolls around, it just so happens that 0x272A8001 =doesn't= get
picked because there are =two= 1:51:45's and Boyd picks the
second one because 0x272AC000 is too large, and so is every
choice all the way to 0x272A8800, by which time he has already
skipped over (in counting order, that is) 0x272A8001.  Once his
algorithm decides that 0x272A8800 is too small, he is forced to
pick the second occurance of that time by setting more of the
bits off to the right.

>The scary thing is that he earns his living as a coding consultant, when
>he's not busy libeling people on the net or making a fool of himself all
>over the place.

No, K*nt, I make my living as a programmer.  Unlike you who makes
his living dodging the child support payments you are supposed to
be paying to your ex-wife, or pretending to be mentally ill.  You
may be mentally ill, for all I know, but I've never seen anyone
as "disabled" as you are "able" to produce so much crap.
-- 
John F. Haugh II                             UUCP: ...!cs.utexas.edu!rpp386!jfh
Ma Bell: (512) 832-8832                           Domain: jfh@rpp386.cactus.org
"SCCS, the source motel!  Programs check in and never check out!"
		-- Ken Thompson

boyd@necisa.ho.necisa.oz (Boyd Roberts) (12/03/90)

In article <18761@rpp386.cactus.org> jfh@rpp386.cactus.org (John F. Haugh II) writes:
>
>As for not being called all that often, what if the application
>is something like "expire" which must deal with textual dates
>in article headers?  Still think it won't be called that often?

That's a different problem.  You'd compare the _components_ of a pieced
together `struct tm', not the 32 bit UNIX time.  That would be stupid.


Boyd Roberts			boyd@necisa.ho.necisa.oz.au

``When the going gets wierd, the weird turn pro...''