[comp.lang.c] Date functionality

fpb@ittc.wec.com (Frank P. Bresz) (07/28/90)

Hello,
	I am looking for an algorithm to give me the day of the week when
handed the current date.  I can't use any builtin routines from any OS
(this is targeted for a real brain-damaged machine).  Any Help appreciated.

					Frank P. Bresz }*{
					ITTC Network Administrator
+--------------------+
|fbresz@ittc.wec.com |
|uunet!ittc!fbresz   |
|(412)733-6749       |
|Fax: (412)733-6444  |
+--------------------+

steve@taumet.com (Stephen Clamage) (07/29/90)

fpb@ittc.wec.com (Frank P. Bresz) writes:

>	I am looking for an algorithm to give me the day of the week when
>handed the current date.  I can't use any builtin routines from any OS
>(this is targeted for a real brain-damaged machine).

Here is an algorithm known as Zeller's congruence.

The day of the week (0 = Sunday) is given by
  W = ((26*M - 2) / 10 + D + Y + Y/4 + C/4 - 2*C) % 7
  where
	C is the century
	Y is the last two digits of the year
	D is the day of the month
	M is a special month number, where Jan and Feb are taken as
	  month 11 and 12 of the previous year
  and each division is truncating division, and cannot be combined.
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com

buckland@cheddar.ucs.ubc.ca (Tony Buckland) (07/31/90)

In article <171@ittc.wec.com> fbresz@ittc.wec.com writes:
>Hello,
>	I am looking for an algorithm to give me the day of the week when
>handed the current date.  I can't use any builtin routines from any OS
>(this is targeted for a real brain-damaged machine).  Any Help appreciated.
 
  Answering this question was my first post, a few months ago.
  Let's see if I can get it right this time.  The statement function
  following will work:

   DOW(ID,IM,IC,IY)=MOD((26*IM-2)/10+ID+IY+IY/4+IC/4-2*IC,7)
 
  where ID is the day of the month, IM is two less than the month
  from March on (March is 1, ..., December is 10) or 11 for January
  or 12 for February, IC is the century and IY is the year.  The
  value of DOW is minus one for Saturday, 0 for Sunday, ..., 5
  for Friday.  At least, it is if I read the program comments
  correctly this time.  It won't work before 1753.

stead@beno.CSS.GOV (Richard Stead) (08/02/90)

In article <8931@ubc-cs.UUCP>, buckland@cheddar.ucs.ubc.ca (Tony Buckland) writes:
>   Let's see if I can get it right this time.  The statement function
>   following will work:
> 
>    DOW(ID,IM,IC,IY)=MOD((26*IM-2)/10+ID+IY+IY/4+IC/4-2*IC,7)

Ouch, smells like FORTRASH.  Isn't this comp.lang.c?  Steve Clamage
already posted the C version of this (Zeller's congruence).  If you
want a function, #define it.

--Richard Stead
stead@seismo.css.gov

engbert@cs.vu.nl (Engbert Gerrit IJff) (08/09/90)

In article <357@taumet.com>,
	steve@taumet.com (Stephen Clamage) writes:
) fpb@ittc.wec.com (Frank P. Bresz) writes:
) 
) >	I am looking for an algorithm to give me the day of the week when
) >handed the current date.  I can't use any builtin routines from any OS
) >(this is targeted for a real brain-damaged machine).
) 
) Here is an algorithm known as Zeller's congruence.
) 
) The day of the week (0 = Sunday) is given by
)   W = ((26*M - 2) / 10 + D + Y + Y/4 + C/4 - 2*C) % 7
)   where
) 	C is the century
) 	Y is the last two digits of the year
) 	D is the day of the month
) 	M is a special month number, where Jan and Feb are taken as
) 	  month 11 and 12 of the previous year
)   and each division is truncating division, and cannot be combined.
) -- 
) 
) Steve Clamage, TauMetric Corp, steve@taumet.com

That works fine, but beware: if you take Jan and Feb as month
11 and 12 of the previous year, you have to take Y the previous year
as well, and C the previous century, if necessary.

At least that is what I found, when implementing the algorithm.
Good luck.

Bert.

engbert@cs.vu.nl (Engbert Gerrit IJff) (08/09/90)

In article <357@taumet.com>,
	steve@taumet.com (Stephen Clamage) writes:
) fpb@ittc.wec.com (Frank P. Bresz) writes:
) 
) >	I am looking for an algorithm to give me the day of the week when
) >handed the current date.  I can't use any builtin routines from any OS
) >(this is targeted for a real brain-damaged machine).
) 
) Here is an algorithm known as Zeller's congruence.
) 
) The day of the week (0 = Sunday) is given by
)   W = ((26*M - 2) / 10 + D + Y + Y/4 + C/4 - 2*C) % 7
)   where
) 	C is the century
) 	Y is the last two digits of the year
) 	D is the day of the month
) 	M is a special month number, where Jan and Feb are taken as
) 	  month 11 and 12 of the previous year
)   and each division is truncating division, and cannot be combined.
) -- 
) 
) Steve Clamage, TauMetric Corp, steve@taumet.com

Another point, I forgot to mention in my previous followup,
is that the number on which you do the % operation may be
negative, and so may be the result. Using the result as an index
to a table of day names then may cause a program crash.
Instead, use    W = ((...expression...) % 7 + 7) % 7


Bert IJff.

raab@novavax.UUCP (Moshe Raab) (08/11/90)

In article <8931@ubc-cs.UUCP> news@cs.ubc.ca writes:
>>Hello,
>>       I am looking for an algorithm to give me the day of the week when
>>handed the current date.  I can't use any builtin routines from any OS
>>(this is targeted for a real brain-damaged machine).  Any Help appreciated.
 
>  Answering this question was my first post, a few months ago.
>  Let's see if I can get it right this time.  The statement function
>  following will work:
>
>   DOW(ID,IM,IC,IY)=MOD((26*IM-2)/10+ID+IY+IY/4+IC/4-2*IC,7)
 
> where ID is the day of the month, IM is two less than the month
> from March on (March is 1, ..., December is 10) or 11 for January
>  or 12 for February, IC is the century and IY is the year.  The
>  value of DOW is minus one for Saturday, 0 for Sunday, ..., 5
>  for Friday.  At least, it is if I read the program comments
>  correctly this time.  It won't work before 1753.
 
this function will not work for the month of jan & feb unless you also
decrease the year, as the following code seg shows:
 
int dow(int id,int im,int ic,int iy)
{
/*
ID is the day of the month,
IM is two less than the month from March on (March is 1, ..., December is 10)
    or 11 for January or 12 for February,
IC is the century
IY is the year.
*/
  if (im > 2) im -= 2;
  else
  {
    im += 10;
    if (!iy)
    {
      ic--;
      iy = 99;
    }
    else iy--;
  }
  return ((26*im-2)/10+id+iy+iy/4+ic/4-2*ic) % 7;
}

steve@taumet.com (Stephen Clamage) (08/12/90)

It has been pointed out that there was a potential error in my
(and others') posting of Zeller's Congruence as follows:

The day of the week (0 = Sunday) is given by
  W = ((26*M - 2) / 10 + D + Y + Y/4 + C/4 - 2*C) % 7
  where
	C is the century
	Y is the last two digits of the year
	D is the day of the month
	M is a special month number, where Jan and Feb are taken as
	  month 11 and 12 of the previous year
  and each division is truncating division, and cannot be combined.

The algorithm uses the modulo operator '%' which is not the same
as the '%' operator in C, which is instead a remainder operator.
The result in C of the '%' operator on a negative value is
implemenation-dependent, even in ANSI C.  So we must ensure that
we do not apply '%' to a negative number.

The properties of modulo arithmetic are such that we may apply it
individually to each term of a sum.  To guarantee that our sum
is positive, we can find (2*C)%7, which is subtracted instead of 2*C,
and add an additional 7 before the final %7.

  W = ((26*M - 2) / 10 + D + Y + Y/4 + C/4 - (2*C)%7 + 7) % 7

As has also been noted:
1.  The year 1752 had a funny calendar, so use only for year >= 1753.
    (September had 11 days removed because the calendar had fallen
    that far out of sync with the true seasons.)
2.  Jan and Feb are treated as in the previous year, so in this case
    subtract 1 from the year.  Compute the century after computing
    the year. (For Mar - Dec, just subtract 2 from the month.)
-- 

Steve Clamage, TauMetric Corp, steve@taumet.com