Day of the week algorithm

A

aarklon

Hi folks,

I found an algorithm for calculating the day of the week here:-

http://www.faqs.org/faqs/calendars/faq/part1/index.html

in the section titled 2.5 what day of the week was 2 august 1953

I checked the algorithm it is very correct.

1)I used zellers congruence which is described in C-FAQ,page no:356,
QNO: 20.31

for the following date 27th december 1985

i used the formula: h = (q + 26 *(m+1)/10 + k + k/4 + j/4 + 5 *j)%7
to get

h = (27 + 26 *(13) /10 +85 + 85/4 + 19/4 + 5 * 19) % 7 to get the
answer
as 0,which is wrong, as the correct answer is friday which
corresponds to 6

1) can any body point out where i have gone wrong

2)can any body explain the statement / give examples

and if January and February are taken as months 13 and 14 of the
previous year [affecting both J and K]; then h for the Gregorian
calendar is the remainder when the sum

which is given here http://c-faq.com/misc/zeller.html

3) on what grounds the values for the array t are set in the following
code by
Tomohiko Sakamoto:
int dayofweek(int y, int m, int d) /* 0 = Sunday */
{
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
y -= m < 3;
return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}
 
T

Tak-Shing Chan

Hi folks,

I found an algorithm for calculating the day of the week here:-

http://www.faqs.org/faqs/calendars/faq/part1/index.html

in the section titled 2.5 what day of the week was 2 august 1953

I checked the algorithm it is very correct.

1)I used zellers congruence which is described in C-FAQ,page no:356,
QNO: 20.31

for the following date 27th december 1985

i used the formula: h = (q + 26 *(m+1)/10 + k + k/4 + j/4 + 5 *j)%7
to get

h = (27 + 26 *(13) /10 +85 + 85/4 + 19/4 + 5 * 19) % 7 to get the
answer
as 0,which is wrong, as the correct answer is friday which
corresponds to 6

The above formula is equivalent to h = 6, indicating that
the C-FAQ is correct. If you got h = 0 instead, chances are that
you have forgotten to discard the remainders as per the C-FAQ.
1) can any body point out where i have gone wrong

2)can any body explain the statement / give examples

and if January and February are taken as months 13 and 14 of the
previous year [affecting both J and K]; then h for the Gregorian
calendar is the remainder when the sum

which is given here http://c-faq.com/misc/zeller.html

3) on what grounds the values for the array t are set in the following
code by
Tomohiko Sakamoto:
int dayofweek(int y, int m, int d) /* 0 = Sunday */
{
static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
y -= m < 3;
return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}

This is exactly the same algorithm used in the Calendar FAQ
you quoted above. Here ``y -= m < 3'' is just a shorthand for
``a = (14 - month) / 12, y = year - a'', and ``t[m-1]'' is just
a shorthand for ``m = month + 12*a - 2, ((31*m)/12)) % 7''.

Tak-Shing
 
F

Frederick Gotham

aarklon posted:
I found an algorithm for calculating the day of the week here:


Things to consider:

(1) The Gregorian calender came into effect in 1583.

(2) Dates prior to 1583 are of the Julian calender.

(3) Thursday October 4th 1582 was followed by Friday October 15th 1582. The
dates 5th through 14th didn't exist.
 
W

Walter Roberson

aarklon posted:
Things to consider:
(1) The Gregorian calender came into effect in 1583.

In the places where it came into effect.

(2) Dates prior to 1583 are of the Julian calender.

Unless they are in a different calendar system entirely, such as
the Jewish Calendar.

(3) Thursday October 4th 1582 was followed by Friday October 15th 1582. The
dates 5th through 14th didn't exist.

Sounds like you aren't Ukranian or Russian...
 
F

Flash Gordon

Frederick said:
aarklon posted:


Things to consider:

(1) The Gregorian calender came into effect in 1583.

(2) Dates prior to 1583 are of the Julian calender.

(3) Thursday October 4th 1582 was followed by Friday October 15th 1582. The
dates 5th through 14th didn't exist.

Further things to consider, different countries adopted the Gregorian
calendar at different times, so what you are saying is only true in some
places. Also the Gregorian calendar can be (and is) used for dates prior
to when it was adopted, and the same went for the Julian calendar.

All off topic for here.
 
R

Richard Heathfield

Walter Roberson said:
In the places where it came into effect.



Unless they are in a different calendar system entirely, such as
the Jewish Calendar.



Sounds like you aren't Ukranian or Russian...

....or British, Irish, or American. Our October 1582 was a normal October.
Our September 1752, however, was somewhat minimalist.

cal gets the period a bit confused. For a decent rendition of those
turbulent calendrical times, see
http://www.crowl.org/Lawrence/time/britgreg.html
 
A

aarklon

Flash said:
Further things to consider, different countries adopted the Gregorian
calendar at different times, so what you are saying is only true in some
places. Also the Gregorian calendar can be (and is) used for dates prior
to when it was adopted, and the same went for the Julian calendar.

All off topic for here.



Hi all,

this is what i got reply to my posting(via email) from stan milam

http://groups.google.co.in/group/co...994?lnk=gst&q=aarklon&rnum=1#4b39c1b032181994



Stan Milam
=============================================================
Charter Member of The Society for Mediocre Guitar Playing on
Expensive Instruments, Ltd.
=============================================================

/**********************************************************************/
/* File Id: dates.c.
*/
/* Author: Stan Milam.
*/
/* Date Written: 23 Sep. 93.
*/
/*
*/
/* (c) Copyright 2006 by Stan Milam.
*/
/* All rights reserved.
*/
/*
*/
/* The routines in this file allow powerful date manipulation.
*/
/* Many of the routines are fashioned after standard C library
*/
/* functions.
*/
/*
*/
/* The following is a list of function and their purpose:
*/
/* date() - Return the current date.
*/
/* date_to_string() - Builds canned date strings.
*/
/* localdate() - Build a date structure.
*/
/* mkdate() - Computes a date value from a date
*/
/* structure.
*/
/* strfdate() - Builds custom date strings.
*/
/* to_date() - Converts date strings into date values.
*/
/* to_char() - Same as date_to_string().
*/
/* compute_date() - Add/subtract years, months, weeks, days
*/
/* to a given date value.
*/
/* time_to_date() - Convert ANSI time value into a date
*/
/* value.
*/
/**********************************************************************/
/*
*/
/* Added some new functions. They are:
*/
/* first_day_of_month() - Computes the first date value of a
*/
/* month.
*/
/* last_day_of_month() - Computes a date value for the last
*/
/* day of a month.
*/
/* next_day_of_week() - Computes a future date value for a
*/
/* specific day of the week.
*/
/* last_day_of_week() - Computes a previous date value for
*/
/* a specific day of the week.
*/
/* get_day_of_week() - Compute integer value for day of the
*/
/* week.
*/
/* easter() - Compute date value for Easter in a
*/
/* given year.
*/
/*
*/
/**********************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "datetool.h"

#define MAXYEAR 9999
#define MAXDATE 3652059L /* 31-Dec-9999 */

/* $Revision: 1.3 $ */
extern char tb_copyright[];
static char *copyright = tb_copyright;

/**********************************************************************/
/* A table which contains an accumulation of days of all pre-
*/
/* ceeding months.
*/
/**********************************************************************/

static int month_accum_table[] = {
0, 31, 59, 90, 120, 151,
181, 212, 243, 273, 304, 334
};

/**********************************************************************/
/* Each element contains the normal number of days for each
*/
/* month.
*/
/**********************************************************************/

static int month_table[] = {
31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31
};

/**********************************************************************/
/* The full names of the weekdays.
*/
/**********************************************************************/

static char *full_weekday[] = {
"Sunday", "Monday", "Tuesday",
"Wednesday", "Thursday", "Friday", "Saturday"
};

/**********************************************************************/
/* The full names of the months.
*/
/**********************************************************************/

static char *full_month[] = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
};

/**********************************************************************/
/* Name:
*/
/* compare()
*/
/*
*/
/* Description:
*/
/* This function serves to compare two strings in a case in-
*/
/* sensitive manner. Also the length of the compare is con-
*/
/* trolled. Should work like Turbo C's strnicmp().
*/
/*
*/
/* Arguments:
*/
/* char *string1 - The first string to compare.
*/
/* char *string2 - The second string to compare.
*/
/* size_t len - The max length of the compare.
*/
/*
*/
/* Returns:
*/
/* 0 if both strings equal.
*/
/* -1 if first string less than second.
*/
/* 1 if first string greater than second.
*/
/*
*/
/**********************************************************************/

static int
compare( char *s1, char *s2, size_t len )
{
int rv;

while ( *s1 && *s2 && len ) {

if ( ( rv = toupper(*s1++) - toupper(*s2++) ) == 0 ) {
len--;
continue;
}

return rv < 0 ? -1 : 1;
}
return len == 0 ? 0 : *s1 ? 1 : -1;
}

/**********************************************************************/
/* Name:
*/
/* is_it_a_leap_year()
*/
/*
*/
/* Description:
*/
/* This function determines if a year is a leap year or not.
*/
/*
*/
/* Arguments:
*/
/* size_t year - The year to test.
*/
/*
*/
/* Returns:
*/
/* A logical value, TRUE or FALSE.
*/
/*
*/
/**********************************************************************/

static int
is_it_a_leap_year( size_t year )
{
return ( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 );
}

/**********************************************************************/
/* Name:
*/
/* years_to_days()
*/
/*
*/
/* Description:
*/
/* This function converts a Gregorian year into a long integer
*/
/* number representing the number of days elapsed since year 1
*/
/* day 1 of month 1.
*/
/*
*/
/* Arguments:
*/
/* An size_t value presumed to be the year to convert to days.
*/
/*
*/
/* Return Value:
*/
/* A value of date_t which should be the number of days from
*/
/* 01-Jan-0001 up to but not including the year argument.
*/
/*
*/
/**********************************************************************/

static date_t
years_to_days( size_t year )
{
date_t rv;

if (year > 0) year--;
rv = year * 365L + year / 4L - year / 100L + year / 400L;
return rv;
}

/**********************************************************************/
/* Name:
*/
/* months_to_days()
*/
/*
*/
/* Description:
*/
/* This function will convert the number of elapsed months into
*/
/* a long integer representing the number of elapsed days since
*/
/* the beginning of a year.
*/
/*
*/
/* Arguments:
*/
/* int month - The month to convert.
*/
/* int year - The year which the month occurs in. Used
*/
/* to add an extra day if a leap year.
*/
/*
*/
/* Returns:
*/
/* A long integer value representing the number of days elapsed
*/
/* since the beginning of the year.
*/
/*
*/
/**********************************************************************/

static date_t
months_to_days( int month, int leap_year )
{
date_t rv;

rv = month_accum_table[month - 1];
if ( month > 2 ) rv += leap_year;
return rv;
}

/**********************************************************************/
/* Name:
*/
/* days_to_months()
*/
/*
*/
/* Description:
*/
/* This function takes the number of elapsed days in a year and
*/
/* converts this number into the month and the day of the month
*/
/*
*/
/* Arguments:
*/
/* int *days - The number of elapsed days. The day of the
*/
/* month is returned in this variable.
*/
/* int years - The current year. Used to determine a leap yr.
*/
/*
*/
/* Returns: The month.
*/
/*
*/
/**********************************************************************/

static int
days_to_months( int *days, int leap_year )
{
int rv, month, save_month;

save_month = month_table[1];
month_table[1] += leap_year;
for ( month = 0 ;; month++ ) { /* Go find the month and day
*/
if ( *days > month_table[month] ) /* More days than in month?
*/
*days -= month_table[month]; /* Yes, subtract from days
*/
else {
rv = month; /* Found month, days left
over */
break; /* Get out of loop */
}
}
month_table[1] = save_month;
return rv; /* Return our month */
}

/**********************************************************************/
/* week_of_year()
*/
/*
*/
/* This function computes the week of the year for either of
*/
/* two cases: The week starts on a Sunday or a Monday.
*/
/*
*/
/* NOTE! This function was borrowed from P. J. Plauger's book
*/
/* "The Standard C Library".
*/
/*
*/
/**********************************************************************/

static int
week_of_year( int start, int wday, int yday )
{
wday = ( wday + 7 - start ) % 7;
return ( yday - wday + 12 ) / 7 - 1;
}

/**********************************************************************/
/* Name:
*/
/* get_four_digit_year().
*/
/*
*/
/* Description:
*/
/* When given a two digit year this function uses a floating year
*/
/* algorithim to determine a four digit year.
*/
/*
*/
/* Arguments:
*/
/* int two_digit_year - NUFF Said!
*/
/*
*/
/* Return Value:
*/
/* An integer type containing the four digit year.
*/
/*
*/
/**********************************************************************/

static int
get_four_digit_year( int two_digit_year )
{
time_t time_v;
struct tm *tm;
int thisyear, newyear, lowyear;

/******************************************************************/
/* Get the current four digit year from system using standard */
/* time functions. */
/******************************************************************/

time_v = time( NULL );
tm = localtime( &time_v );
thisyear = tm -> tm_year + 1900;

/******************************************************************/
/* The cutoff year is 50 years in the past. If the two digit */
/* year is less than the cutoff date add 100 to it. */
/******************************************************************/

lowyear = thisyear - 50;
newyear = (lowyear / 100 ) == (thisyear / 100 ) ? thisyear :
lowyear;
newyear = ( ( newyear / 100 ) * 100 ) + two_digit_year;
if ( newyear <= lowyear )
newyear += 100;

return newyear;
}

/**********************************************************************/
/* Name: get_day_of_week().
*/
/*
*/
/* Description:
*/
/* Given a value of type date_t will return an integer number
*/
/* indicating the day of the week with Sunday being represented
*/
/* by 0, Monday by 1 and so on.
*/
/*
*/
/* Arguments:
*/
/* date_t date_v - A date value from date(), mkdate(), to_date()
*/
/* or compute_date().
*/
/*
*/
/* Return Value:
*/
/* An integer value between 0 and 6 representing the day of the
*/
/* week with Sunday = 0.
*/
/*
*/
/**********************************************************************/

int
get_day_of_week( date_t date_v )
{
int rv = (int) (date_v % 7L);
return rv;
}

/**********************************************************************/
/* time_to_date()
*/
/*
*/
/* This function was initially intentioned to be called intern-
*/
/* ally, but I found use for it to called externally too, so it
*/
/* became part of the suite. It serves to convert time values
*/
/* obtained from time() into date values.
*/
/*
*/
/* Arguments:
*/
/* time_t tv - A time value obtained from the time() function
*/
/*
*/
/* Returns: A value of type date_t which respresents a date
*/
/* value.
*/
/*
*/
/**********************************************************************/

date_t
time_to_date( long tv )
{
date_t rv;
struct tm *tm;
int year, leap_year;

/******************************************************************/
/* Get a time structure to use for conversion process. */
/******************************************************************/

tm = localtime( (time_t *) &tv);

/******************************************************************/
/* Use values in the tm structure to convert the current */
/* date into a long integer value. */
/******************************************************************/

year = tm -> tm_year + 1900;
leap_year = is_it_a_leap_year(year);
rv = years_to_days( year );
rv += months_to_days(tm -> tm_mon + 1, leap_year );
rv += tm -> tm_mday;

return rv;
}

/**********************************************************************/
/* date()
*/
/*
*/
/* This function returns a long integer value which represents
*/
/* the current date as the number of days elapsed since day 1
*/
/* of month 1 of year 1.
*/
/*
*/
/* Arguements:
*/
/* date_t *arg - Pointer to a value of type date_t. Can be
*/
/* NULL.
*/
/*
*/
/* Returns: A value of date_t (long) which is the number of
*/
/* days elapsed.
*/
/*
*/
/**********************************************************************/

date_t
date( date_t *arg )
{
date_t rv;

/******************************************************************/
/* Use time_to_date() which uses the ANSI time() function */
/* to do the actual date conversion. */
/******************************************************************/

rv = time_to_date( time( NULL ) );

/******************************************************************/
/* If an argument is supplied put the value in it. */
/******************************************************************/

if ( arg != NULL ) *arg = rv;
return rv;
}

/**********************************************************************/
/* Name:
*/
/* mkdate()
*/
/*
*/
/* Description:
*/
/* This function is the complement to the mktime() function.
*/
/* It takes the value in the dt structure and converts them
*/
/* into a long integer value. We also do the basic edits of
*/
/* values to make sure we have reasonable data to work with.
*/
/*
*/
/* Arguments:
*/
/* struct dt *dt - A pointer to a structure of type dt which
*/
/* the following information is required:
*/
/*
*/
/* dt_year
*/
/* dt_yday (can substitue month and day)
*/
/* dt_month (if dt_mday not used.)
*/
/* dt_mday (if dt_yday not used.)
*/
/*
*/
/* Return Value:
*/
/* An integer value of type date_t or (date_t) -1 if
*/
/* an error occurs.
*/
/*
*/
/**********************************************************************/

date_t
mkdate( struct dt *dt )
{
date_t rv;
int max_day;
int year, month, day_of_month, day_of_year, leap_year;

/******************************************************************/
/* Get values from the structure into local variables. */
/******************************************************************/

year = dt -> dt_year;
month = dt -> dt_month;
day_of_month = dt -> dt_mday;
day_of_year = dt -> dt_yday;

/******************************************************************/
/* Convert the year into a sequential number, but check for */
/* errors first. */
/******************************************************************/

if ( year < 1 || year > MAXYEAR ) return ( (date_t) -1);

rv = years_to_days(year);
leap_year = is_it_a_leap_year(year);

/******************************************************************/
/* Try to use the month and day of month first to get the */
/* number of days elpased since the beginning of the year. */
/* Use the day of the year if we do not have the above. */
/* Check everything along the way. */
/******************************************************************/

if (month >= 0 && month < 12) {
if ( day_of_month > 0 ) {
rv += months_to_days( month + 1, leap_year );
max_day = month_table[month];
if ( month == 1 ) max_day += leap_year;
if ( day_of_month <= max_day ) rv += day_of_month;
else rv = (date_t) -1;
}
else if ( day_of_year >= 0 ) {
max_day = leap_year ? 365 : 364;
if ( day_of_year <= max_day ) rv += day_of_year + 1;
else rv = (date_t) -1;
}
else rv = (date_t) -1;
}
else rv = (date_t) -1;
return rv;
}

/**********************************************************************/
/* Name:
*/
/* localdate()
*/
/*
*/
/* Description:
*/
/* This function is the inverse of the mkdate() function. It
*/
/* will take the number of elapsed days since Jan 1, 0001 and
*/
/* convert into the dt structure.
*/
/*
*/
/* Arguments:
*/
/* date_t *arg - A pointer to the number of elpased days.
*/
/*
*/
/* Return Value:
*/
/* A pointer to type struct dt. This is the address of
*/
/* an internal structure so the return value must be copied be-
*/
/* fore making the next call.
*/
/*
*/
/**********************************************************************/

struct dt *
localdate( date_t *arg ) {

date_t day;
size_t year;
static struct dt dt;
int yday, mday, leapyear, month, wday;

/******************************************************************/
/* Make sure we are in range. Upper limit is 31-Dec-9999. */
/******************************************************************/

day = *arg;
if ( day < (date_t) 1L || day > (date_t) MAXDATE ) return NULL;

/******************************************************************/
/* 146097 is years_to_days(400). */
/******************************************************************/

year = (size_t) ( (day * 400L) / 146097L );
while ( years_to_days( year + 1 ) < day ) year++;

/******************************************************************/
/* Compute the remaining values from what we know already. */
/******************************************************************/

leapyear = is_it_a_leap_year(year);
mday = (int) (day - years_to_days( year )); yday = mday - 1;
month = days_to_months( &mday, leapyear);
wday = get_day_of_week( day );

/******************************************************************/
/* Assign to our internal structure. */
/******************************************************************/

dt.dt_year = year;
dt.dt_mday = mday;
dt.dt_yday = yday;
dt.dt_wday = wday;
dt.dt_month= month;
dt.dt_leap_year = leapyear;
return &dt;
}

/**********************************************************************/
/* Name:
*/
/* strfdate()
*/
/*
*/
/* Synopsis:
*/
/* #include "datetool.h"
*/
/* size_t strfdate(char *b, size_t size, char *f, struct dt *);
*/
/*
*/
/* Description:
*/
/* This is the main function in the file. It uses format char-
*/
/* acters to format the date any way we want it in a supplied
*/
/* memory address.
*/
/*
*/
/* Arguments:
*/
/* char *buffer - Memory address where we place the formatted
*/
/* date.
*/
/* size_t size - Max size of the buffer. We do not exceed.
*/
/* char *format - The format string. Characters preceeded
*/
/* by the % character are taken to be format
*/
/* specifiers. The format specifiers are:
*/
/*
*/
/* %a - Format abbreviated weekday name.
*/
/* %A - Full weekday name.
*/
/* %b - Format abbreviated month name.
*/
/* %B - Format full month name.
*/
/* %d - Format the day of the month (01-31).
*/
/* %j - The day of the year (001 - 366).
*/
/* %m - The month of the year (01 - 12).
*/
/* %U - The week of year (00 - 52, Sunday)
*/
/* %w - The day of week (0 - 6, Sunday = 0)
*/
/* %W - The week of year (00 - 52, Monday).
*/
/* %x - The date (MM/DD/CCYY).
*/
/* %y - Formats a two digit year.
*/
/* %Y - Formats the four digit year.
*/
/*
*/
/* struct dt *dt - A pointer to the dt structure populated
*/
/* with the localdate() function.
*/
/*
*/
/* Return Value:
*/
/* The length of the formatted string.
*/
/*
*/
/**********************************************************************/

size_t
strfdate( char *buffer, size_t size, char *format, struct dt *dt )
{
size_t len;
int start;
size_t rv = 0;
char wrkbuf[15];
char *src = format;
char *dest= buffer;

/******************************************************************/
/* Enter a loop copying characters from the format string */
/* into the buffer unless it is a format character. */
/******************************************************************/

while ( *src && size ) {
if ( *src != '%' ) {
*dest++ = *src++;
size--; rv++;
}
else {
len = 0;

/**********************************************************/
/* We have a format character so we handle it. */
/**********************************************************/

switch( *++src ) {

/******************************************************/
/* Just in case there is nothing following! */
/******************************************************/

case '\0' :
continue;

/******************************************************/
/* Format the abbreviated weekday name. */
/******************************************************/

case 'a' :
len = 3;
if ( len > size ) len = size;
strncpy(dest, full_weekday[dt -> dt_wday], len );
break;

/******************************************************/
/* Format the full name of the week. */
/******************************************************/

case 'A' :
len = strlen( full_weekday[dt -> dt_wday] );
if ( len > size ) len = size;
strncpy( dest, full_weekday[dt->dt_wday], len);
break;

/******************************************************/
/* Format the abbreviated name of the month. */
/******************************************************/

case 'b' :
len = 3;
if ( len > size ) len = size;
strncpy(dest, full_month[dt -> dt_month], len);
break;

/******************************************************/
/* Format the full name of the month. */
/******************************************************/

case 'B' :
len = strlen(full_month[dt -> dt_month]);
if ( len > size ) len = size;
strncpy(dest, full_month[dt -> dt_month], len);
break;

/******************************************************/
/* Format the day of the month. */
/******************************************************/

case 'd' :
len = sprintf(wrkbuf, "%02d", dt -> dt_mday);
if ( len > size ) len = size;
strncpy(dest, wrkbuf, len);
break;

/******************************************************/
/* Format the day of the month with a suffix. */
/******************************************************/

case 'e' :
len = sprintf(wrkbuf, "%d", dt -> dt_mday) + 2;
switch( dt -> dt_mday ) {
case 1:
case 21:
case 31:
strcat(wrkbuf, "st");
break;
case 2:
case 22:
strcat(wrkbuf, "nd");
break;
case 3:
case 23:
strcat(wrkbuf, "rd");
break;
default :
strcat(wrkbuf, "th");
break;
}
if ( len > size ) len = size;
strncpy(dest, wrkbuf, len);
break;


/******************************************************/
/* Format the day of the year (001 - 366). */
/******************************************************/

case 'j' :
len = sprintf(wrkbuf, "%03d", dt -> dt_yday + 1);
if ( len > size ) len = size;
strncpy(dest, wrkbuf, len);
break;

/******************************************************/
/* Format the month of the year (01 - 12). */
/******************************************************/

case 'm' :
len = sprintf(wrkbuf, "%02d", dt -> dt_month + 1);
if ( len > size ) len = size;
strncpy(dest, wrkbuf, len);
break;

/******************************************************/
/* Formats the week of the year. %U starts the */
/* week with Sunday, %W starts the week with a */
/* Monday. */
/******************************************************/

case 'U' :
case 'W' :
start = (*src == 'U') ? 1 : 0;
len = sprintf(wrkbuf, "%02d",
week_of_year(start, dt -> dt_wday,
dt->dt_yday));
if ( len > size ) len = size;
strncpy(dest, wrkbuf, len);
break;

/******************************************************/
/* Format the day of the week (1 - 6). */
/******************************************************/

case 'w' :
len = sprintf(wrkbuf, "%d", dt -> dt_wday);
if ( len > size ) len = size;
strncpy( dest, wrkbuf, len );
break;

/******************************************************/
/* Formats a traditional Gregorian date with */
/* single exception: The year is four digits. */
/******************************************************/

case 'x' :
len = sprintf(wrkbuf, "%02d/%02d/%04d",
dt -> dt_month + 1,
dt -> dt_mday,
dt -> dt_year);
if (len > size) len = size;
strncpy(dest, wrkbuf, len);
break;

/******************************************************/
/* Formats the year in at least four digits. */
/******************************************************/

case 'Y' :
len = sprintf(wrkbuf, "%04d", dt -> dt_year);
if ( len > size ) len = size;
strncpy(dest, wrkbuf, len);
break;

/******************************************************/
/* Format the year without the century. */
/******************************************************/

case 'y' :
len = sprintf(wrkbuf, "%02d", dt -> dt_year % 100);
if ( len > size ) len = size;
strncpy(dest, wrkbuf, len);
break;

/******************************************************/
/* User may want a % character in the output. */
/******************************************************/

case '%' :
len = 1;
if (len > size) len = size;
else *dest = '%';
break;

} /* Switch */

src += 1;
rv += len;
dest += len;
size -= len;
} /* while */
}
if ( size ) *dest = '\0';
return rv;
}

/**********************************************************************/
/* Name:
*/
/* to_date()
*/
/*
*/
/* Synopsis:
*/
/* #include "datetool.h"
*/
/* date_t to_date( char *date_string, int date_type.
*/
/*
*/
/* Description:
*/
/* This function serves to convert well known formatted date
*/
/* strings into a variable of type date_t.
*/
/*
*/
/* Arguments:
*/
/* char *string - String containing the formatted date.
*/
/* int type - An integer value informing us what kind of
*/
/* date string we are dealing with. Uses the
*/
/* manifest constants in date.h.
*/
/*
*/
/* Returns: A positive value of type date_t if the conversion
*/
/* was successful. A value of -1L if the conversion
*/
/* was not successful.
*/
/*
*/
/**********************************************************************/

date_t
to_date( char *string, int type )
{
date_t rv;
struct dt dt = { 0, 0, 0, 0, 0, 0 };
int len, i, mday, yday, month, year;
char wrkbuf[16], **months = full_month;

year = month = yday = mday = 0;
switch ( type ) {

case DDMMCCYY :
i = sscanf(string, "%2d%2d%4d", &mday, &month, &year);
if ( i != 3 ) return (date_t) -1L;
month--;
break;

case MMDDCCYY :
i = sscanf(string, "%2d%2d%4d", &month, &mday, &year);
if ( i != 3 ) return (date_t) -1L;
month--;
break;

case GREGDATE :
i = sscanf(string, "%d%*c%d%*c%d", &month, &mday, &year);
if ( i != 3 ) return (date_t) -1L;
month--;
break;

case ISODATE :
i = sscanf(string, "%d%*c%d%*c%d", &year, &month, &mday);
if ( i != 3 ) return (date_t) -1L;
month--;
break;

case MILDATE :
i = sscanf(string,"%d%*c%d%*c%d",&mday, &month, &year);
if ( i != 3) return (date_t) -1L;
month--;
break;

case SPELLDATE :
i = sscanf(string, "%d%*c%3c%*c%d", &mday, wrkbuf, &year);
if (i != 3) return (date_t) -1L;
for (month = 0, len = 3; month < 12; month++) {
if ( compare( wrkbuf, months[month], len ) == 0 )
break;
}
if ( month == 12 ) return (date_t) -1;
break;

case JULDATE :
len = strlen( string );
if ( len == 5 || len == 7 ) {
len -= 3;
sprintf(wrkbuf, "%%%dd%%%dd", len, 3);
i = sscanf(string, wrkbuf, &year, &yday);
if ( i != 2 ) return (date_t) -1L;
yday--;
}
else return (date_t) -1L;
break;

case SYSDATE :
len = strlen( string );
if ( len == 8 || len == 6 ) {
len -= 4;
sprintf(wrkbuf, "%%%dd%%%dd%%%dd", len, 2, 2);
i = sscanf(string, wrkbuf, &year, &month, &mday);
if ( i != 3 ) return (date_t) -1L;
month--;
}
else return ( date_t ) -1L;
break;

default :
return (date_t) -1L;

}

/******************************************************************/
/* If a two digit year is provided determine the four digit year. */
/******************************************************************/

if ( year < 100 )
year = get_four_digit_year( year );

/******************************************************************/
/* Setup and call mkdate() to get the sequential day number */
/******************************************************************/

dt.dt_year = year;
dt.dt_mday = mday;
dt.dt_yday = yday;
dt.dt_month= month;
rv = mkdate( &dt );
return rv;
}

/**********************************************************************/
/* Name:
*/
/* date_to_string()
*/
/*
*/
/* Synopsis:
*/
/* #include "datetool.h"
*/
/* char *date_to_string(char *dest, date_t dv, int date_type.
*/
/*
*/
/* Description:
*/
/* This function allows the programmer to quickly convert a
*/
/* date variable into a widely used string format. Therefore,
*/
/* this function is just a front end to strfdate().
*/
/*
*/
/* Arguments:
*/
/* char *buffer - Address of buffer to format the string in.
*/
/* date_t day - Sequential number of date.
*/
/* int type - A value which determines what format the
*/
/* string will be in.
*/
/*
*/
/* Returns: The address of the formatted string.
*/
/*
*/
/**********************************************************************/

char
*date_to_string(char *buffer, date_t day, int type)
{
int size;
struct dt *dt;
char wrkbuf[25], *format;

wrkbuf[0] = '\0';
size = sizeof(wrkbuf);

switch ( type ) {

case GREGDATE :
format = "%x";
break;

case MILDATE :
format = "%d/%m/%Y";
break;

case ISODATE :
format = "%Y-%m-%d";
break;

case SPELLDATE :
format = "%d-%b-%Y";
break;

case JULDATE :
format = "%Y%j";
break;

case SYSDATE :
format = "%Y%m%d";
break;

case DDMMCCYY :
format = "%d%m%Y";
break;

case MMDDCCYY :
format = "%m%d%Y";
break;

default :
format = NULL;
}

if ( format != NULL ) {
if (( dt = localdate( &day )) != NULL )
strfdate(wrkbuf, size, format, dt);
}
return (strcpy(buffer, wrkbuf));
}

/**********************************************************************/
/* to_char()
*/
/*
*/
/* This function is just a front end to date_to_string() as it
*/
/* seems to be more aptly named.
*/
/*
*/
/**********************************************************************/

char
*to_char(char *buffer, date_t day, int type)
{
return date_to_string(buffer, day, type);
}

/**********************************************************************/
/* next_day_of_week()
*/
/*
*/
/* This function, given a date value and given a day value
*/
/* (0 = Sunday..6 = Saturday) will compute a the next date
*/
/* value for that day.
*/
/*
*/
/* Arguments:
*/
/* date_t date_val - A date value.
*/
/* int day - An integer value (see defined values in
*/
/* dates.h) representing a day of the
*/
/* week where Sunday = 0 and Saturday = 6.
*/
/*
*/
/* Returns:
*/
/* A value of type date_t representing the next future date
*/
/* of the specfied day.
*/
/*
*/
/**********************************************************************/

date_t
next_day_of_week( date_t value, int day )
{
date_t rv;
struct dt *dt;

/******************************************************************/
/* See if we have a valid date value. */
/******************************************************************/

if ( (dt = localdate( &value )) == NULL )
rv = (date_t) -1L;
else if ( day < SUNDAY || day > SATURDAY )
rv = (date_t) -1L;
else {

/**************************************************************/
/* Compute how many days until the next specifed day of */
/* the week. Make sure we are within our limits too. */
/**************************************************************/

rv = (date_t) 7 - dt -> dt_wday + day;
if ( rv > (date_t) 7) rv -= (date_t) 7;
rv = rv + value;
if ( rv > MAXDATE ) rv = (date_t) -1L;
}
return rv;
}

/**********************************************************************/
/* previous_day_of_week()
*/
/*
*/
/* This function computes a previous date value of a day of the
*/
/* week
*/
/*
*/
/* Arguments:
*/
/* date_t value - A date value which is used as the starting
*/
/* point of the calculation.
*/
/* int day - A value representing the day of the week
*/
/* to be calculated. See values defined in
*/
/* dates.h
*/
/*
*/
/* Returns: A date value for the calculated date or (date_t)-1
*/
/* if an error occured.
*/
/*
*/
/**********************************************************************/

date_t
previous_day_of_week( date_t value, int day )
{
date_t rv;
struct dt *dt;

/******************************************************************/
/* Check for a valid date value. */
/******************************************************************/

if ((dt = localdate( &value )) == NULL)
rv = (date_t) -1L;
else if ( day < SUNDAY || day > SATURDAY )
rv = (date_t) -1L;
else {

/**************************************************************/
/* Compute the date value for previous specified day */
/* and do sanity check. */
/**************************************************************/

rv = (date_t) day - dt->dt_wday;
if ( rv >= (date_t) 0 ) rv -= (date_t) 7L;
rv += value;
if ( rv < (date_t) 1L ) rv = (date_t) -1L;
}
return rv;
}

/**********************************************************************/
/* last_day_of_month()
*/
/*
*/
/* This function, when given a date value will determine the
*/
/* last day of the month the date value falls in.
*/
/*
*/
/* Arguments:
*/
/* date_t value - A date value representing a day between
*/
/* 01-Jan-0001 and 31-Dec-9999.
*/
/*
*/
/* Returns:
*/
/* A date value as described above. (date_t) -1L is ret-
*/
/* urned if the argument was invalid.
*/
/*
*/
/**********************************************************************/

date_t
last_day_of_month( date_t value )
{

date_t rv;
struct dt *dt = localdate( &value );

/******************************************************************/
/* See if date value was valid. */
/******************************************************************/

if ( dt == NULL )
rv = (date_t) -1L;
else {

/**************************************************************/
/* Determine last day of the month, compute the diffe- */
/* rence and add to the date value. */
/**************************************************************/

rv = month_table[ dt -> dt_month ];
if ( dt -> dt_month == 1 ) rv += dt -> dt_leap_year;
rv = rv - dt -> dt_mday + value;
}
return rv;
}

/**********************************************************************/
/* first_day_of_month()
*/
/*
*/
/* This function, when given a date value, will determine the
*/
/* first day of the month for which the date value falls under.
*/
/*
*/
/* Arguments:
*/
/* date_t value - An integer date value.
*/
/*
*/
/* Returns:
*/
/* An integer date value representing the first day of the
*/
/* month which the argument is in.
*/
/*
*/
/**********************************************************************/

date_t
first_day_of_month( date_t value )
{
date_t rv;
struct dt *dt = localdate( &value );

rv = ( dt == NULL ) ? (date_t) -1L : (date_t) 1 - dt -> dt_mday +
value;
return rv;
}

/**********************************************************************/
/* compute_date()
*/
/*
*/
/* This function will take a date value as an argument and
*/
/* allow the programmer to add/subtract a combination of years
*/
/* months, weeks, and days to arrive at another date.
*/
/*
*/
/* Arguments:
*/
/* date_t value - The date value we are using as a base.
*/
/* int years - The number of years to add/subtract.
*/
/* int months- The number of months to add/subtract.
*/
/* int weeks - The number of weeks to add/subtract.
*/
/* int days - The number of days to add/subtract.
*/
/*
*/
/* Returns: A new date value for the calculated date.
*/
/*
*/
/**********************************************************************/

date_t
compute_date(date_t value, int years, int months, int weeks, int days)
{
date_t rv; /* Return value */
int ld1, ld2; /* Last days of months */
struct dt *wrk; /* A date structure */

wrk = localdate( &value ); /* Get a date structure */
if ( wrk == NULL ) return (date_t) -1L;

/******************************************************************/
/* Go ahead and compute the weeks and days. */
/******************************************************************/

rv = (weeks * 7) + days;

/******************************************************************/
/* Now compute the months. We may have to adjust the years */
/* value. */
/******************************************************************/

if ( months ) {
if ( abs(months) > 11 ) {
years += months / 12;
months = months % 12;
}

/**************************************************************/
/* Now compute the target month and handle wrap-around. */
/**************************************************************/

months += wrk -> dt_month;
if ( months < 0 ) {
months += 12;
years += -1;
}
else if ( months > 11 ) {
months -= 12;
years += 1;
}

/**************************************************************/
/* Now we have to make adjustment if we are on the last day of*/
/* the month. For instance if date is 31 May and we add 1 */
/* month the result should be 30 June. */
/**************************************************************/

ld1 = month_table[wrk ->dt_month];
if ( wrk->dt_month == 1 ) ld1 += wrk->dt_leap_year;
if ( wrk->dt_mday == ld1 ) {
ld2 = month_table[months];
if ( months == 1 ) ld2 += is_it_a_leap_year(years +
wrk->dt_year);
if (ld1 > ld2 ) wrk->dt_mday = ld2;
}
wrk->dt_month = months;
}

wrk -> dt_year += years;

/******************************************************************/
/* The following is a fixup in case we started on Feb 29 */
/* and we are computing into another year. */
/******************************************************************/

ld1 = month_table[ wrk -> dt_month ];
if ( wrk->dt_month == 1 ) ld1 += is_it_a_leap_year(wrk->dt_year);
if (wrk->dt_mday > ld1) wrk->dt_mday = ld1;

/******************************************************************/
/* Call mkdate() to do the work. */
/******************************************************************/

rv += mkdate( wrk );
return rv;
}

/**********************************************************************/
/* Name: easter().
*/
/*
*/
/* Description:
*/
/* This function calculates a date value for Easter in a given
*/
/* Year. The algorithm is complicated and shamelessly taken from
*/
/* the excellent calendar FAQ by Claus Tondering which can be
*/
/* found at:
*/
/*
*/
/* http://www.cis.ohio-state.edu/hypertext/faq/usenet/calendars.
*/
/*
*/
/* Arguments:
*/
/* int year - The year to find the Easter.
*/
/*
*/
/* Return Value:
*/
/* A value of date_t of which is the numeric value of the
*/
/* Easter date.
*/
/*
*/
/**********************************************************************/

date_t
easter( int year )
{
date_t rv;
int g, c, h, i, j, l, month, day;

/******************************************************************/
/* Make sure the year is in bounds. */
/******************************************************************/

if ( year < 1 || year > MAXYEAR )
rv = (date_t) 1L;
else {

/**************************************************************/
/* Use the complicated calendar FAQ formula. I will not */
/* bother to try and explain it. If you want to understand */
/* it get the FAQ where it is explained in excruciating */
/* detail. */
/**************************************************************/

g = year % 19;
c = year / 100;
h = ( c - c/4 - (8 * c + 13) / 25 + 19 * g + 15) % 30;
i = h - (h / 28) * (1 - (h / 28) * (29 / (h + 1)) * ((2 - g) /
11));
j = (year + year / 4 + i + 2 - c + c / 4) % 7;
l = i - j;
month = 3 + (l + 40) / 44;
day = l + 28 - 31 * (month / 4);

/**************************************************************/
/* Now, convert everything into a date type. */
/**************************************************************/

rv = day;
rv += years_to_days( year );
rv += months_to_days( month, is_it_a_leap_year( year ) );
}

return rv;
}

#ifdef TEST
int
main( void )
{

int x_sub;
char buf[50];

for ( x_sub = 1992; x_sub < 2001; x_sub++ )
puts( to_char( buf, easter( x_sub ), SPELLDATE ) );

puts( to_char( buf, easter( 1968 ), SPELLDATE ) );
puts( to_char( buf, easter( 33 ), SPELLDATE ) );
return 0;
}
#endif


/*$no list *//*no trace <<< datetool.h >>> */
/**********************************************************************/
/* File Id: datetool.h.
*/
/* Author: Stan Milam.
*/
/* Date Written: 07-Jul-1996.
*/
/* Description:
*/
/* Header file for all the toolbox date constants and function
*/
/* prototypes.
*/
/*
*/
/* (c) Copyright 2006 by Stan Milam.
*/
/* All rights reserved.
*/
/*
*/
/**********************************************************************/

/* $Revision: 1.2 $ */

#ifndef DATETOOL_H
# define DATETOOL_H 1
# ifdef __cplusplus
extern "C" {
# endif

/**********************************************************************/
/* Include adjust.h if it has not already been done.
*/
/**********************************************************************/

#ifndef ADJUST_H
# include "adjust.h"
#endif

/***************************************************************/
/* Define values for the days of the week. */
/***************************************************************/

#define SUNDAY 0
#define MONDAY 1
#define TUESDAY 2
#define WEDNESDAY 3
#define THURSDAY 4
#define FRIDAY 5
#define SATURDAY 6

/***************************************************************/
/* Define the values used by to_date() & to_char() for date */
/* strings. */
/***************************************************************/

#define JULDATE 1 /* CCYYDDD */
#define GREGDATE 2 /* MM/DD/CCYY */
#define SPELLDATE 3 /* DD-MMM-CCYY */
#define MILDATE 4 /* DD/MM/CCYY */
#define SYSDATE 5 /* CCYYMMDD */
#define DDMMCCYY 6 /* MILDATE without '/' */
#define MMDDCCYY 7 /* GREGDATE without / */
#define ISODATE 8 /* YYYY-MM-DD */

typedef long date_t;

struct dt {
int dt_leap_year; /* Indicates a leap year */
int dt_year; /* The actual year */
int dt_month; /* The month, 0 - 11 */
int dt_mday; /* The day of month, 1-31 */
int dt_yday; /* The day of the year, 0-365 */
int dt_wday; /* The day of the week, 0-6,
0=Sun*/
};

date_t date( date_t * );
date_t easter( int year );
date_t mkdate ( struct dt * );
date_t time_to_date( long tv );
struct dt *localdate( date_t * );
int get_day_of_week( date_t date_v );
date_t to_date( char *string, int type );
date_t last_day_of_month( date_t value );
date_t first_day_of_month( date_t value );
date_t next_day_of_week( date_t value, int day);
date_t previous_day_of_week( date_t value, int day);
char * to_char( char *buffer, date_t day, int type );
char * date_to_string( char *buffer, date_t day, int type);
size_t strfdate( char *buf, size_t size, char *format, struct dt *dt );
date_t compute_date(date_t start, int years, int months, int weeks, int
days);

/**********************************************************************/
/* Older date routines.
*/
/**********************************************************************/

long juldate(long t);
char *gregdate(long t);
char *spelldate(long t);
char *spelltime(long t);

#ifndef TBXCR
#define TBXCR "(c) Copyright 2006 by Stan Milam. All Rights Reserved."
#endif

# ifdef __cplusplus
}
# endif
#endif
/*$list *//*$trace <<< datetool.h >>> */
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top