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