Velocity Reviews > formula used in calculating diffrence between dates

# formula used in calculating diffrence between dates

celsius
Guest
Posts: n/a

 01-03-2005
Hi folks,
Al Bowers wrote this program on comp.lang.c
Date: 2001-07-09 13:41:58 PST
#include <stdio.h>

int isleap (unsigned yr);
static unsigned months_to_days (unsigned month);
static long years_to_days (unsigned yr);
long ymd_to_scalar (unsigned yr, unsigned mo, unsigned day);

int main(void) {
unsigned y1 = 2000, m1 = 2, d1 = 1, /* represent 01FEB2000 */
y2 = 2000, m2 = 3,d2 = 1; /* represent 01MAR2000 */
long date1,date2;

date1 = ymd_to_scalar(y1,m1,d1);
date2 = ymd_to_scalar(y2,m2,d2);
printf("There are %ld days\n",date2-date1);
printf("It %s a leap year\n",(isleap(y1))?"is":"is not");
return 0;
}

int isleap (unsigned yr)
{ return yr % 400 == 0 || (yr % 4 == 0 && yr % 100 != 0);}

static unsigned months_to_days (unsigned month)
{ return (month * 3057 - 3007) / 100; }

static long years_to_days (unsigned yr)
{return yr * 365L + yr / 4 - yr / 100 + yr / 400;}

long ymd_to_scalar (unsigned yr, unsigned mo, unsigned day)
{
long scalar;
scalar = day + months_to_days(mo);
if ( mo > 2 ) /* adjust if past February */
scalar -= isleap(yr) ? 1 : 2;
yr--;
scalar += years_to_days(yr);
return scalar;
}

can anybody explain the logic or formula applied in functions:-

static unsigned months_to_days (unsigned month);
static long years_to_days (unsigned yr):

if want to know about the formula which is used here
--
comp.lang.c.moderated - moderation address: http://www.velocityreviews.com/forums/(E-Mail Removed) -- you must
or the newsgroup name in square brackets in the subject line. Sorry.

William Gabler
Guest
Posts: n/a

 01-05-2005

"celsius" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Hi folks,
> Al Bowers wrote this program on comp.lang.c
> Date: 2001-07-09 13:41:58 PST
> #include <stdio.h>
>
> int isleap (unsigned yr);
> static unsigned months_to_days (unsigned month);
> static long years_to_days (unsigned yr);
> long ymd_to_scalar (unsigned yr, unsigned mo, unsigned day);
>
> int main(void) {
> unsigned y1 = 2000, m1 = 2, d1 = 1, /* represent 01FEB2000 */
> y2 = 2000, m2 = 3,d2 = 1; /* represent 01MAR2000 */
> long date1,date2;
>
> date1 = ymd_to_scalar(y1,m1,d1);
> date2 = ymd_to_scalar(y2,m2,d2);
> printf("There are %ld days\n",date2-date1);
> printf("It %s a leap year\n",(isleap(y1))?"is":"is not");
> return 0;
> }
>
> int isleap (unsigned yr)
> { return yr % 400 == 0 || (yr % 4 == 0 && yr % 100 != 0);}
>
> static unsigned months_to_days (unsigned month)
> { return (month * 3057 - 3007) / 100; }
>
> static long years_to_days (unsigned yr)
> {return yr * 365L + yr / 4 - yr / 100 + yr / 400;}
>
> long ymd_to_scalar (unsigned yr, unsigned mo, unsigned day)
> {
> long scalar;
> scalar = day + months_to_days(mo);
> if ( mo > 2 ) /* adjust if past February */
> scalar -= isleap(yr) ? 1 : 2;
> yr--;
> scalar += years_to_days(yr);
> return scalar;
> }
>
> can anybody explain the logic or formula applied in functions:-
>
> static unsigned months_to_days (unsigned month);
> static long years_to_days (unsigned yr):
>
>
> if want to know about the formula which is used here
> --

IMHO the formula in months_to_days is ad hoc, made up to work.
Remember that integer divides truncate. Follow the flow of control
to figure out what is done where. Start at main, January is month 1
since Feb is month 2. ymd_to_scalar is called. Clearly this takes
year-month-day to a long (i.e. scalar).

In ymd_to_scalar, months_to_days(month) is called. This returns
0 for January, 31 for February. Jan 1 is 0 days into the year,
Feb 1 is 31 days into the year. For March the formula gives 61.64,
truncates to 61, 2 days more than Mar 1 is into a non-leap year(31+28=59).
This goes on with 2 days extra. (I checked it for December).
if ( mo > 2 ) /* adjust if past February */
scalar -= isleap(yr) ? 1 : 2;
This takes out the extra day in leap year and extra 2 days in
non-leap years.

Now, scalar is the number of days into the year, based on day of month,
month and leapyear. Then scalar is adjusted by the number of days since
some the fictitious year zero, including adjustments for leap days. The
leap day formula in isleap() and years_to_days() is based on
the Gregorian calendar which did not exist until 1582 (see the calendar FAQ
http://www.tondering.dk/claus/calendar.html ). Therefore, DO NOT USE
this program for years before Gregorian calendar was introduced.

yr--; //NEW NOTE calculate days that occurred
before this year
scalar += years_to_days(yr);

> static long years_to_days (unsigned yr)
> {return yr * 365L + yr / 4 - yr / 100 + yr / 400;}

Here, yr*365L is the days if all years are non-leap years (365L is a long
constant).
+ yr/4 adds a day for each four year cycle
-yr/100 subtracts a day for each century year (like 1900,
2000)
+yr/400 adds a day for century years that are leap years
(2000).

---------------- Bill

> comp.lang.c.moderated - moderation address: (E-Mail Removed) -- you must

seen,
> or the newsgroup name in square brackets in the subject line. Sorry.

--
comp.lang.c.moderated - moderation address: (E-Mail Removed) -- you must
or the newsgroup name in square brackets in the subject line. Sorry.

Stan Milam
Guest
Posts: n/a

 01-05-2005
celsius wrote:

> Hi folks,
> Al Bowers wrote this program on comp.lang.c
> Date: 2001-07-09 13:41:58 PST
> #include <stdio.h>
>
> int isleap (unsigned yr);
> static unsigned months_to_days (unsigned month);
> static long years_to_days (unsigned yr);
> long ymd_to_scalar (unsigned yr, unsigned mo, unsigned day);
>
> int main(void) {
> unsigned y1 = 2000, m1 = 2, d1 = 1, /* represent 01FEB2000 */
> y2 = 2000, m2 = 3,d2 = 1; /* represent 01MAR2000 */
> long date1,date2;
>
> date1 = ymd_to_scalar(y1,m1,d1);
> date2 = ymd_to_scalar(y2,m2,d2);
> printf("There are %ld days\n",date2-date1);
> printf("It %s a leap year\n",(isleap(y1))?"is":"is not");
> return 0;
> }
>
> int isleap (unsigned yr)
> { return yr % 400 == 0 || (yr % 4 == 0 && yr % 100 != 0);}
>
> static unsigned months_to_days (unsigned month)
> { return (month * 3057 - 3007) / 100; }
>
> static long years_to_days (unsigned yr)
> {return yr * 365L + yr / 4 - yr / 100 + yr / 400;}
>
> long ymd_to_scalar (unsigned yr, unsigned mo, unsigned day)
> {
> long scalar;
> scalar = day + months_to_days(mo);
> if ( mo > 2 ) /* adjust if past February */
> scalar -= isleap(yr) ? 1 : 2;
> yr--;
> scalar += years_to_days(yr);
> return scalar;
> }
>
> can anybody explain the logic or formula applied in functions:-
>
> static unsigned months_to_days (unsigned month);
> static long years_to_days (unsigned yr):
>
>
> if want to know about the formula which is used here

The years_to_days() function is based on the formula used to calculate
when a year is a leap year or not. This is years evenly divisible by 4
are leap years, unless they are also evenly divisable by 100 with the
exception they are evenly divisible by 400. Clear as mud, right?
Basically, it calculates the number of days in a year (365L) and adjusts
for all the leap years (366 days a year) that have intervened.

I am not quite sure of what the month_to_days() function is based on,
but I feel strongly that it is premised on the fact that months are
either 30 or 31 days, with the exception of February which has 28 or 29
days. The function is flawed because it makes the adjustment for leap
years outside of the of the function. By this I mean that
month_to_days() should take care of make the adjustments, not the
calling function. If I were writing this I would do the following:

1. Determine if the year is a leap year and store that value ( 0 or 1 ):
is_it_a_leap_year = isleap( yr );

2. Determine the number of days elapsed for years and store that:
days = years_to_days( yr );

Also, years_to_days() should make the adjustment of subtracting 1
from the year.

3. Determine the number of days elapsed in the current year as follows:
days += month_to_days( month, day, is_it_a_leap_year );

The month_to_days() function would make the adjustment for leap years
(subtract 2 days for non leap years, or 1 day for leap years).

--
Regards,
Stan Milam.
-----------------------------------------------------------------------------
Vita Brevis. Carpe Guitarum! - Jamie Kinscherff
-----------------------------------------------------------------------------
--
comp.lang.c.moderated - moderation address: (E-Mail Removed) -- you must
or the newsgroup name in square brackets in the subject line. Sorry.