[comp.sources.misc] v06i037: Evaluate if a date is DST or not

allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (02/04/89)

Posting-number: Volume 6, Issue 37
Submitted-by: dg@lakart.UUCP (David Goodenough)
Archive-name: isdst

[Does this critter deal with DST ambiguities like the recent change?  ++bsa]

For a project I'm doing, I needed to know if a given date was Daylight
Savings or not. After searching long and hard, I dicovered that in the
United States at least, the changes are always the last Sunday of April
and October. The following algorithm will take a date in day, month,
year, century form, and tell if it is DST or not: it returns zero if
not DST, and 1 if the date is DST. Caveat: it assumes that the
changeover is at midnight: it doesn't understand about the time slip at
2AM. However as long as you aren't up at 2AM I don't predict this will
be a problem. As a freebie, it also includes a function that will
evaluate the day of the week for a given date. This function returns a
number between 0 and 6, where 0 means Sunday, 1 is Monday etc., and 6
is Saturday.
-- 
	dg@lakart.UUCP - David Goodenough		+---+
						IHS	| +-+-+
	....... !harvard!xait!lakart!dg			+-+-+ |
AKA:	dg%lakart.uucp@xait.xerox.com		  	  +---+

--- cut here --- cut here --- cut here --- cut here --- cut here ---
#! /bin/sh
# This file was wrapped with "dummyshar".  "sh" this file to extract.
# Contents:  isdst.c
echo extracting 'isdst.c'
if test -f 'isdst.c' -a -z "$1"; then echo Not overwriting 'isdst.c'; else
sed 's/^X//' << \EOF > 'isdst.c'
Xint isdst(day, month, year, cent)
Xint day, month, year, cent;
X {
X    if (month < 4 || month > 10)
X      return(0);	/* months 1 - 3, and 11, 12 are always not DST */
X    if (month > 4 && month < 10)
X      return(1);	/* months 5 - 9 are always DST */
X
X	/* see if there's a Sunday in the month after our day. */
X
X    while (++day <= ((month == 4) ? 30 : 31))
X      if (dayofweek(day, month, year, cent) == 0)
X	return(month == 10);	/* found one: that means we're before the
X				 * changeover, so 4 => not DST, 10 => DST */
X
X    return(month == 4);		/* failed, so we're after the changeover,
X				 * so 4 => DST, 10 => not DST */
X }
X
Xint dayofweek(day, month, year, cent)
Xint day, month, year, cent;
X {
X		/* This has it's roots in the Roman calendar, where the first
X		 * month was Mar, and Jan and Feb were months 11 and 12 of
X		 * the previous year */
X    if ((month = month - 2) < 1) /* back month by two, but check for wrap */
X     {
X	month = month + 12;	/* reset to end of last year */
X	if (year-- == 0)	/* reduce year number */
X	 {
X	    year = 99;		/* and adjust for century wrap if needed */
X	    cent--;
X	 }
X     }
X    return(((13 * month - 1) / 5 + day + year + year / 4 +
X						cent / 4 - 2 * cent) % 7);
X				/* I don't have a clue how this got dreamed
X				 * up, but it works. If memory serves I first
X				 * saw it in the British Science Museum, in
X				 * London, England */
X }
EOF
chars=`wc -c < 'isdst.c'`
if test $chars !=     1425; then echo 'isdst.c' is $chars characters, should be     1425 characters!; fi
fi
exit 0