Dilwyn Jones wrote:

...
> In fact, as I was given permission to include those articles on the
> Documentation CD, may I ask you if I can also include these routines 
> as
> well?

Sure.

>       If so, a few lines explaining the algorithm may be in order. I
> understand parts of it, but not all of it: for example what's the
> significance of the (dy+0.8) ?

It's the "Fudge factor" to get the leap year calculations correct - it could 
possibly be removed by changing the base year (of the shifted year) from 
1960 to 1959 (and adding an extra 366, ie +972 instead of +306 to the days) 
but I haven't checked it:

0.8 was chosen, as otherwise the first year would be a leap year with 366 
days (0-365), the 2nd would then be days 366-730, 3rd 731-1095, 4th 
1096-1460; the 5th would also be a leap year.

The my_mth_no() fn is just the month stuff extracted from my_date proc, so 
I'll just explain my_date.

I'm not a very good technical author (and I'm currently half asleep), so 
I'll write what it does and I'll let you tidy it up (if you want to).

----8<--------8<--------8<--------8<--------8<--------8<--------8<--------8<----


The way it works is by using a calendar based on day 0 = 1 March 1960.  The 
"year" in this calendar runs from 1 March to 28/29 February - the leap day 
is added at the end of the year, every 1460 days. (4 years)  Having the leap 
day at the end of the year means that we don't have to worry about it when 
working out the day offset for any date in the year 1 March or later.

As we're passed seconds, we divide by 86400 = 24 * 60 * 60, the number of 
seconds in a day and ignore the fraction.  The passed date needs to be 
adjusted for our shifted year and as day 306 is 1 January 1961, an offset of 
306 is added.

The current year is calculated from the base by checking out every 365.25 
days.  (The "fudge factor" of (dy + 0.8) simplifies the calculation so that 
yr 0 = days 0-364, yr 1 = 365-729, yr 2 = 730-1094, yr 3 (leap) = 1095-1460, 
etc.)  Once the relative year to the base year is found, the number of days 
until the start of that year is removed leaving the day offset within the year.

The number 30.6 is useful in that its multiples, when ignoring the fraction 
bit, provide an increase of 30, 31, 30, 31, 31 which then repeats.  This 
matches the number of days in each of the months in the year that need to be 
added to get to the start of the current month: 31 (March), 30 (April), 31, 
30, 31, 31, 30, 31, 30, 31, 31 (February has 28/29 which then starts the 
next year and so we don't need it).

Adding 31 to the current day number corrects for the sequence of the 
multiples of 30.6 so that it matches the month sequence.  Dividing by 30.6 
then gives the month number in the shifted year.

We need to subtract the number of days in the month(s) preceeding this one 
from the day offset in the year.  Again, we need to shift the 30.6 sequence 
and the (mn + 3) provides this.  However, we also have to correct for 
INT(30.6 * 3) = 92 extra days which are subtracted, so we need to add them 
back with a +92

Finally the shifted month is corrected for the real year by adding 2.  If 
the resultant month is > 12 (ie a month past December, ie January or 
February), subtract 12 from the month number and add one to the year.  The 
year is corrected to the real year by adding the base year of 1960.


_______________________________________________
QL-Users Mailing List
http://www.q-v-d.demon.co.uk/smsqe.htm

Reply via email to