El grupo al cual envías entradas es un grupo Usenet. Si envías mensajes a este grupo, cualquier usuario de Internet podrá ver tu dirección de correo electrónico
I found an old "Perpetual Gregorian Calendar" on the Internet.
I improved it a little bit, but I would like to know more about its inner working.
First, my version:
10 REM CALENDAR.BAS by Emmanuel ROCHE 20 : 30 REM Perpetual Gregorian Calendar 40 REM "Astronomical Computing", "Sky & Telescope", July 1985, p.62 50 REM http://www.skyandtelescope.com/resources/software/3304911.html?page=3... 60 : 70 DIM c$ (42), d$ (31), e (12), m$ (12) 80 RESTORE 100 90 FOR i = 1 TO 31 : READ d$ (i) : NEXT i 100 DATA " 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9"," 10" 110 DATA " 11"," 12"," 13"," 14"," 15"," 16"," 17"," 18"," 19"," 20" 120 DATA " 21"," 22"," 23"," 24"," 25"," 26"," 27"," 28"," 29"," 30" 130 DATA " 31" 140 RESTORE 160 150 FOR i = 1 TO 12 : READ e (i) : NEXT i 160 DATA 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 170 RESTORE 190 180 FOR i = 1 TO 12 : READ m$ (i) : NEXT i 190 DATA January, February, March, April, May, June, July 200 DATA August, September, October, November, December 210 x$ = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC" 220 PRINT 230 INPUT "CALENDAR> Enter MONth, Year (JANuary,2001): ", m2$, y 240 m = VAL (m2$) 250 y$ = SPACE$ (3) 260 LSET y$ = UPPER$ (m2$) 270 IF m = 0 THEN m = (INSTR (x$, y$) + 2) / 3 280 IF m <> ROUND (m) OR m < 1 OR m > 12 THEN 230 290 REM Adoption: Friday 15 October 1582 300 IF y <= 1582 AND m <= 9 THEN 230 310 REM Valid until 4099 only 320 IF y > 4099 THEN 230 330 PRINT 340 PRINT " " m$ (m) y 350 PRINT 360 PRINT " Su Mo Tu We Th Fr Sa" 370 PRINT 380 IF y < 100 THEN y = y + 1900 390 j = 367*y-INT(7*(y+INT((m+9)/12))/4)+INT(275*m/9)+1721031! 400 k = 0 : IF m <= 2 THEN k = -1 410 j = j - INT (3 * (INT ((y + k) / 100) + 1) / 4) 420 k = e (m) 430 IF m <> 2 THEN 500 440 w = INT (y - 100 * INT (y / 100)) 450 x = INT (y - 4 * INT (y / 4)) 460 z = INT (y - 400 * INT (y / 400)) 470 IF x <> 0 THEN 500 480 IF w = 0 AND z <> 0 THEN 500 490 k = 29 500 x = j - 7 * INT (j / 7) 510 FOR i = 1 TO 42 : c$ (i) = " " : NEXT i 520 FOR i = 1 TO k : c$ (i + x) = d$ (i) : NEXT i 530 FOR i = 1 TO 6 540 j = 7 * i 550 PRINT c$(j-6) c$(j-5) c$(j-4) c$(j-3) c$(j-2) c$(j-1) c$(j) 560 NEXT i 570 INPUT "Another calendar (Y/N)? ", a$ 580 IF UPPER$ (a$) = "Y" THEN 220 590 PRINT 600 END
As you can see, this program was originally published in the "Sky and Telescope" magazine, in July 1985, page 62.
Unfortunately, impossible, during one week, to reach their online archives.
So, I have no idea if this program was provided with an in-depth discussion of its variables.
The original program was not checking for the bounds, and obliged to enter the month as a number.
As you can see, the program is still MBASIC-compatible, so can run under any version of MBASIC, until Quick BASIC.
Searching on the Internet, I have found dozens of Web site who display the same output as this program. I took this opportunity to check its output against them: so far, I have found no difference.
Hence my interest: I would really like to know the reason of the variables and their values.
> On Nov 20, 4:35 pm, "Mr. Emmanuel Roche, France" > <Roche...@Laposte.Net> wrote: > ... >> Hence my interest: I would really like to know the >> reason of the variables and their values.
> I found an old "Perpetual Gregorian Calendar" on the Internet.
> I improved it a little bit, but I would like to know more about its inner > working.
> First, my version:
[snip]
Here is a version of your program in which I've inserted some comments to describe what (I think) is going on. Hope it helps.
10 REM CALENDAR.BAS by Emmanuel ROCHE 20 : 30 REM Perpetual Gregorian Calendar 40 REM "Astronomical Computing", "Sky & Telescope", July 1985, p.62 50 REM http://www.skyandtelescope.com/resources/software/3304911.html?page=3... 60 : 70 DIM c$ (42), d$ (31), e (12), m$ (12) 80 RESTORE 100 90 FOR i = 1 TO 31 : READ d$ (i) : NEXT i 100 DATA " 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9"," 10" 110 DATA " 11"," 12"," 13"," 14"," 15"," 16"," 17"," 18"," 19"," 20" 120 DATA " 21"," 22"," 23"," 24"," 25"," 26"," 27"," 28"," 29"," 30" 130 DATA " 31" 140 RESTORE 160 150 FOR i = 1 TO 12 : READ e (i) : NEXT i 160 DATA 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 170 RESTORE 190 180 FOR i = 1 TO 12 : READ m$ (i) : NEXT i 190 DATA January, February, March, April, May, June, July 200 DATA August, September, October, November, December 210 x$ = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC" 220 PRINT 230 INPUT "CALENDAR> Enter MONth, Year (JANuary,2001): ", m2$, y ' ' The month can be entered as either numerically or as a string ' such as JAN or FEB, or 1 or 2. The following code sorts out which. ' 240 m = VAL (m2$) 'If numeric, set m to the entered value, else m = 0 250 y$ = SPACE$ (3) 260 LSET y$ = UPPER$ (m2$) 'Convert to upper case 270 IF m = 0 THEN m = (INSTR (x$, y$) + 2) / 3 'If numeric pull associated month string out of x$ 280 IF m <> ROUND (m) OR m < 1 OR m > 12 THEN 230 'If numeric was not valid integer month, try again ' ' At this point y is the year and m is the month. Check for valid date range. ' 290 REM Adoption: Friday 15 October 1582 'When Gregorian calendar was adopted (mostly...) 300 IF y <= 1582 AND m <= 9 THEN 230 'If date not in Gregorian calendar go back 310 REM Valid until 4099 only 320 IF y > 4099 THEN 230 'Not sure why year 4099 cutoff... ' ' Format the calendar headers ' 330 PRINT 340 PRINT " " m$ (m) y 350 PRINT 360 PRINT " Su Mo Tu We Th Fr Sa" 370 PRINT 380 IF y < 100 THEN y = y + 1900 'If a two digit year was entered (pointless since ' 'we checked for y <= 1582 above. This is a bug) ' ' Calculate the Julian Day number + 1.5 ' 390 j = 367*y-INT(7*(y+INT((m+9)/12))/4)+INT(275*m/9)+1721031! 400 k = 0 : IF m <= 2 THEN k = -1 410 j = j - INT (3 * (INT ((y + k) / 100) + 1) / 4) ' ' Determine last day of the month, adjust for leap years if month is February ' 420 k = e (m) 'k is last day of the month (normal year) 430 IF m <> 2 THEN 500 'If month not Feb, skip check 440 w = INT (y - 100 * INT (y / 100)) '100 year rule; year mod 100 450 x = INT (y - 4 * INT (y / 4)) '4 year rule; year mod 4 460 z = INT (y - 400 * INT (y / 400)) '400 year rule; year mod 400 470 IF x <> 0 THEN 500 'If year not multiple of 4 then not a leap year 480 IF w = 0 AND z <> 0 THEN 500 'If century but not divisible by 400 then not a leap year 490 k = 29 'Last day of Feb for leap year ' ' Determine the day of the week for the first day of the month ' 500 x = j - 7 * INT (j / 7) 'Day of week for first day of month; j mod 7. 0=SUN,1=MON,2=TUE etc. ' ' Format the calendar ' 510 FOR i = 1 TO 42 : c$ (i) = " " : NEXT i 520 FOR i = 1 TO k : c$ (i + x) = d$ (i) : NEXT i 530 FOR i = 1 TO 6 540 j = 7 * i 550 PRINT c$(j-6) c$(j-5) c$(j-4) c$(j-3) c$(j-2) c$(j-1) c$(j) 560 NEXT i ' ' Poll user for another go ' 570 INPUT "Another calendar (Y/N)? ", a$ 580 IF UPPER$ (a$) = "Y" THEN 220 590 PRINT 600 END
> Here is a version of your program in which I've inserted > some comments to describe what (I think) is going on. > Hope it helps.
Well, as line 50 explained, I found this program on the "Sky & Telescope" Web site. I just added the easier month entry, and checking the bounds.
Original program:
> 70 DIM c$ (42), d$ (31), e (12), m$ (12) > 80 RESTORE 100 > 90 FOR i = 1 TO 31 : READ d$ (i) : NEXT i > 100 DATA " 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9"," 10" > 110 DATA " 11"," 12"," 13"," 14"," 15"," 16"," 17"," 18"," 19"," 20" > 120 DATA " 21"," 22"," 23"," 24"," 25"," 26"," 27"," 28"," 29"," 30" > 130 DATA " 31" > 140 RESTORE 160 > 150 FOR i = 1 TO 12 : READ e (i) : NEXT i > 160 DATA 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 > 170 RESTORE 190 > 180 FOR i = 1 TO 12 : READ m$ (i) : NEXT i > 190 DATA January, February, March, April, May, June, July > 200 DATA August, September, October, November, December
So, "D$" is the number of the day in ASCII, "E" is the number of days per month, and "M$" is the names of the months in ASCII.
My addition follows, to make the entry of months easier (now, either month names (at least the first 3 letters, hence the upper cases in the prompt) or still a number). The only problem is that you must type a "," between both entries, but this is often the case in English (not in French). (Using LINE INPUT could get rid of this, with a test for a space, or a change from letters to numbers.)
> 210 x$ = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC" > 220 PRINT > 230 INPUT "CALENDAR> Enter MONth, Year (JANuary,2001): ", m2$, y > ' > ' The month can be entered as either numerically or as a string > ' such as JAN or FEB, or 1 or 2. The following code sorts out which. > ' > 240 m = VAL (m2$) 'If numeric, set m to the entered value, else m > = 0 > 250 y$ = SPACE$ (3) > 260 LSET y$ = UPPER$ (m2$) 'Convert to upper case > 270 IF m = 0 THEN m = (INSTR (x$, y$) + 2) / 3 'If numeric pull > associated month string out of x$ > 280 IF m <> ROUND (m) OR m < 1 OR m > 12 THEN 230 'If numeric was not valid > integer month, try again > ' > ' At this point y is the year and m is the month. Check for valid date > range.
Correct interpretation. (LSET = take into account only the first 3 characters of the month.)
> 290 REM Adoption: Friday 15 October 1582 'When Gregorian calendar > was adopted (mostly...) > 300 IF y <= 1582 AND m <= 9 THEN 230 'If date not in Gregorian > calendar go back > 310 REM Valid until 4099 only > 320 IF y > 4099 THEN 230 'Not sure why year 4099 > cutoff...
Those are the check bounds that I added. I found on the Internet that the first legal Gregorian date was Friday 15 October 1582. Since the program work only on inputted months and years, I could only check them.
I then searched on the Internet for the "last day of the Gregorian calendar": most answers I found simply say: "31 December"... I was meaning: which year. According to Wikipedia "Gregorian calendar": "This approximation has an error of about one day per 3300 years". That is to say: the Gregorian calendar starts in 1582 and, 3300 years later, will have to be modified. The year most commonly mentioned was 4099 (some say 4100), so I use it for the upper limit.
We are now re-entering the original program, that I did not understood.
> ' Format the calendar headers > ' > 330 PRINT > 340 PRINT " " m$ (m) y > 350 PRINT > 360 PRINT " Su Mo Tu We Th Fr Sa" > 370 PRINT > 380 IF y < 100 THEN y = y + 1900 'If a two digit year was > entered (pointless since > ' 'we checked for y <= 1582 > above. This is a bug)
Good remark. I had not noticed this! So, the original author of this program was expecting the minimum date to be 1900, or the 20th century. However, when I tested this program against the calendar for the year 1582, I did not find any discrepancy, so he was modest.
> ' Calculate the Julian Day number + 1.5 > ' > 390 j = 367*y-INT(7*(y+INT((m+9)/12))/4)+INT(275*m/9)+1721031! > 400 k = 0 : IF m <= 2 THEN k = -1 > 410 j = j - INT (3 * (INT ((y + k) / 100) + 1) / 4)
I had not understood that "J" was meaning "Julian". Question: Why, in a Gregorian calendar, compute a Julian day? Could you explain more the formula in line 390? What is the purpose of the last number, 1721031? Would an INTEGER version (probably 21031) still works? This is the only Single Precision Floating-Point number of the program. Everything else fit easily inside INTEGERs.
> ' Determine last day of the month, adjust for leap years if month is > February > ' > 420 k = e (m) 'k is last day of the month (normal > year) > 430 IF m <> 2 THEN 500 'If month not Feb, skip check > 440 w = INT (y - 100 * INT (y / 100)) '100 year rule; year mod 100 > 450 x = INT (y - 4 * INT (y / 4)) '4 year rule; year mod 4 > 460 z = INT (y - 400 * INT (y / 400)) '400 year rule; year mod 400 > 470 IF x <> 0 THEN 500 'If year not multiple of 4 then not > a leap year > 480 IF w = 0 AND z <> 0 THEN 500 'If century but not divisible by 400 > then not a leap year > 490 k = 29 'Last day of Feb for leap year
I had grossly undestood this, thanks to the "100" and "400" numbers.
> ' Determine the day of the week for the first day of the month > ' > 500 x = j - 7 * INT (j / 7) 'Day of week for first day of month; > j mod 7. 0=SUN,1=MON,2=TUE etc.
Do you mean that I could replace this line by 500 x = j MOD 7 ? And lines 440, 450, and 460? (Maybe replace those 4 lines by a function? Since only the values change.)
> ' Format the calendar > ' > 510 FOR i = 1 TO 42 : c$ (i) = " " : NEXT i
Fill array "C$" with spaces. (c = column?)
> 520 FOR i = 1 TO k : c$ (i + x) = d$ (i) : NEXT i
Copy the day numbers in the correct day locations (offset by "X"), until the "K" computed above.
> 530 FOR i = 1 TO 6 > 540 j = 7 * i > 550 PRINT c$(j-6) c$(j-5) c$(j-4) c$(j-3) c$(j-2) c$(j-1) c$(j) > 560 NEXT i
Display 7 day-numbers per line. (All my French calendars display day- names and day-numbers vertically, under a month title.) 7 day-numbers * 6 lines = 42, mentioned in line 510 and line 70.
> ' Poll user for another go > ' > 570 INPUT "Another calendar (Y/N)? ", a$ > 580 IF UPPER$ (a$) = "Y" THEN 220 > 590 PRINT > 600 END
Many thank for your comments. So, most of the code can be understood, except lines 390-410, which need more explanation.
In sci.astro message <4b072840$0$970$ba4ac...@news.orange.fr>, Sat, 21 Nov 2009 00:35:00, "Mr. Emmanuel Roche, France" <Roche...@Laposte.Net> posted:
>40 REM "Astronomical Computing", "Sky & Telescope", July 1985, p.62
Did you check the copyright status?
>290 REM Adoption: Friday 15 October 1582 >300 IF y <= 1582 AND m <= 9 THEN 230 >310 REM Valid until 4099 only
(a) That's not very perpetual (b) There's nothing special about 4099 apart IIRC for a naive assertion that it will by then be changed. The Gregorian Calendar is perpetual; His Holiness said so. Some day we may cease to use it.
>320 IF y > 4099 THEN 230 >330 PRINT >340 PRINT " " m$ (m) y >350 PRINT >360 PRINT " Su Mo Tu We Th Fr Sa"
Not ISO 8601 compliant - presumably foreign.
>370 PRINT
Better to use a modern language, with an ISO or other standard. JavaScript, for example.
Since the Gregorian Calendar (neglecting Easter) repeats every 400 years, you can make a perpetual calendar by calculating with YEAR MOD 400.
-- (c) John Stockton, nr London, UK. ?...@merlyn.demon.co.uk Turnpike v6.05. Web <URL:http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms PAS EXE etc : <URL:http://www.merlyn.demon.co.uk/programs/> - see 00index.htm Dates - miscdate.htm estrdate.htm js-dates.htm pas-time.htm critdate.htm etc.
>> ' Calculate the Julian Day number + 1.5 >> ' >> 390 j = 367*y-INT(7*(y+INT((m+9)/12))/4)+INT(275*m/9)+1721031! >> 400 k = 0 : IF m <= 2 THEN k = -1 >> 410 j = j - INT (3 * (INT ((y + k) / 100) + 1) / 4)
> I had not understood that "J" was meaning "Julian". Question: Why, in > a Gregorian calendar, compute a Julian day? Could you explain more the > formula in line 390? What is the purpose of the last number, 1721031? > Would an INTEGER version (probably 21031) still works? This is the > only Single Precision Floating-Point number of the program. Everything > else fit easily inside INTEGERs.
The Julian Day number is not the same thing as a Julian Date. Julian dates correspond to the Julian calendar system, along with its leap years every four years, whereas Julian Day number is a sequential count of days (and fractional portions thereof) from the beginning of the year -4712.
The algorithm converts a date to a Julian Day number by calculating the total number of days elapsed between the given date and some reference day number (hence the constant 1721031). It does so making allowance for all the leap years that occurred between the reference date and the given date. Hence all the odd-looking INT's etc. You can find similar algorithms if you do a search on Julian Day algorithm.
Since the gregorian calendar repeats itself every 400 years you should be able to modify the constant. JD 1721031 corresponds to a date in the Gregorian algorithm of December 5, 2BCE (note I don't say Gregorian calendar, since it didn't come into play until the 1500's). You might try a constant of 113929 and check to see if it gives the right results.
>> ' Determine last day of the month, adjust for leap years if month is >> February >> ' >> 420 k = e (m) 'k is last day of the month (normal >> year) >> 430 IF m <> 2 THEN 500 'If month not Feb, skip check >> 440 w = INT (y - 100 * INT (y / 100)) '100 year rule; year mod 100 >> 450 x = INT (y - 4 * INT (y / 4)) '4 year rule; year mod 4 >> 460 z = INT (y - 400 * INT (y / 400)) '400 year rule; year mod 400 >> 470 IF x <> 0 THEN 500 'If year not multiple of 4 then not >> a leap year >> 480 IF w = 0 AND z <> 0 THEN 500 'If century but not divisible by 400 >> then not a leap year >> 490 k = 29 'Last day of Feb for leap year
> I had grossly undestood this, thanks to the "100" and "400" numbers.
>> ' Determine the day of the week for the first day of the month >> ' >> 500 x = j - 7 * INT (j / 7) 'Day of week for first day of month; >> j mod 7. 0=SUN,1=MON,2=TUE etc.
> Do you mean that I could replace this line by 500 x = j MOD 7 ? And > lines 440, 450, and 460? (Maybe replace those 4 lines by a function? > Since only the values change.)
> >> 500 x = j - 7 * INT (j / 7) 'Day of week for first day of > >> month; j mod 7. 0=SUN,1=MON,2=TUE etc.
> > Do you mean that I could replace this line by 500 x = j MOD 7 ? And > > lines 440, 450, and 460? (Maybe replace those 4 lines by a function? > > Since only the values change.)
> Sure
Well, not exactly...
First, I made a function. But, when I ran the program, I got
Overflow in 510 Ok edit 510 510 x = FN modulo (j, 7) ? j 2443511 Ok
Haaaaa! A Floating-Point number! That's why the program is not using MOD, but its own FP-version of modulo... QED!
Below, you will find the new version of CALENDAR.BAS:
10 REM CALENDAR.BAS by Emmanuel ROCHE 20 : 30 REM Perpetual Gregorian Calendar 40 REM "Astronomical Computing", "Sky & Telescope", July 1985, p.62 50 REM http://www.skyandtelescope.com/resources/software/3304911.html?page=3... 60 : 70 DEF FN FPmod (var, FPval) = INT (var - FPval * INT (var / FPval)) 80 : 90 DIM c$ (42), d$ (31), e (12), m$ (12) 100 RESTORE 120 110 FOR i = 1 TO 31 : READ d$ (i) : NEXT i 120 DATA " 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9"," 10" 130 DATA " 11"," 12"," 13"," 14"," 15"," 16"," 17"," 18"," 19"," 20" 140 DATA " 21"," 22"," 23"," 24"," 25"," 26"," 27"," 28"," 29"," 30" 150 DATA " 31" 160 RESTORE 180 170 FOR i = 1 TO 12 : READ e (i) : NEXT i 180 DATA 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 190 RESTORE 210 200 FOR i = 1 TO 12 : READ m$ (i) : NEXT i 210 DATA January, February, March, April, May, June, July 220 DATA August, September, October, November, December 230 x$ = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC" 240 PRINT 250 INPUT "CALENDAR> Enter MONth, Year (JANuary,2001): ", m2$, y 260 m = VAL (m2$) 270 y$ = SPACE$ (3) 280 LSET y$ = UPPER$ (m2$) 290 IF m = 0 THEN m = (INSTR (x$, y$) + 2) / 3 300 IF m <> ROUND (m) OR m < 1 OR m > 12 THEN 250 310 REM Adoption: Friday 15 October 1582 320 IF y <= 1582 AND m <= 9 THEN 250 330 REM Valid until 4099 only 340 IF y > 4099 THEN 250 350 PRINT 360 PRINT " " m$ (m) y 370 PRINT 380 PRINT " Su Mo Tu We Th Fr Sa" 390 PRINT 400 j = 367*y-INT(7*(y+INT((m+9)/12))/4)+INT(275*m/9)+1721031! 410 k = 0 : IF m <= 2 THEN k = -1 420 j = j - INT (3 * (INT ((y + k) / 100) + 1) / 4) 430 k = e (m) 440 IF m <> 2 THEN 510 450 w = FN FPmod (y, 100) 460 x = FN FPmod (y, 4) 470 z = FN FPmod (y, 400) 480 IF x <> 0 THEN 510 490 IF w = 0 AND z <> 0 THEN 510 500 k = 29 510 x = FN FPmod (j, 7) 520 FOR i = 1 TO 42 : c$ (i) = " " : NEXT i 530 FOR i = 1 TO k : c$ (i + x) = d$ (i) : NEXT i 540 FOR i = 1 TO 6 550 j = 7 * i 560 PRINT c$(j-6) c$(j-5) c$(j-4) c$(j-3) c$(j-2) c$(j-1) c$(j) 570 NEXT i 580 INPUT "Another calendar (Y/N)? ", a$ 590 IF UPPER$ (a$) = "Y" THEN 240 600 PRINT 610 END
Except for the famous lines:
400 j = 367*y-INT(7*(y+INT((m+9)/12))/4)+INT(275*m/9)+1721031! 410 k = 0 : IF m <= 2 THEN k = -1 420 j = j - INT (3 * (INT ((y + k) / 100) + 1) / 4)
Everything is now clear.
(So far, I could not find exactly the same algorithm on the Internet.)
However, each time I compared the output of this program with one of the calendars available on the 'Net, I found no discrepancy.
So, at least for 1582 < year < 4099, I now trust this program.
CALENDAR> Enter MONth, Year (JANuary,2001): October,1582
> Since the gregorian calendar repeats itself every 400 years > you should be able to modify the constant. JD 1721031 > corresponds to a date in the Gregorian algorithm of December 5, 2BCE > (note I don't say Gregorian calendar, since it didn't come into > play until the 1500's). You might try a constant of 113929 and > check to see if it gives the right results.
I made a quick check for the lower and upper bound, and found no discrepancies.
However, even 113929 is a Floating-Point number.
So, this program needs at least 24 bits of accuracy. I know how to make multi-byte arithmetics but, for just a date, it is simpler to keep using BASIC.
>>>> 500 x = j - 7 * INT (j / 7) 'Day of week for first day of >>>> month; j mod 7. 0=SUN,1=MON,2=TUE etc.
>>> Do you mean that I could replace this line by 500 x = j MOD 7 ? And >>> lines 440, 450, and 460? (Maybe replace those 4 lines by a function? >>> Since only the values change.)
>> Sure
> Well, not exactly...
> First, I made a function. But, when I ran the program, I got
> Overflow in 510 > Ok > edit 510 > 510 x = FN modulo (j, 7) > ? j > 2443511 > Ok
> Haaaaa! A Floating-Point number! That's why the program is not using > MOD, but its own FP-version of modulo... QED!
I suppose it depends upon the particular BASIC implementation. POWER BASIC (which I'm using) handles it okay.
[snip good stuff]
>> Since the gregorian calendar repeats itself every 400 years >> you should be able to modify the constant. JD 1721031 >> corresponds to a date in the Gregorian algorithm of December 5, 2BCE >> (note I don't say Gregorian calendar, since it didn't come into >> play until the 1500's). You might try a constant of 113929 and >> check to see if it gives the right results.
> I made a quick check for the lower and upper bound, and found no > discrepancies.
> However, even 113929 is a Floating-Point number.
By subtracting another 11 x 400 years from the date represented by 113929 I've found that you can replace the constant with 4. Even so, the values for j calculated by the rest of the function may require more than 24 bits for far-future dates (after 40,000 years!).
> So, this program needs at least 24 bits of accuracy. I know how to > make multi-byte arithmetics but, for just a date, it is simpler to > keep using BASIC.
> I suppose it depends upon the particular BASIC implementation. > POWER BASIC (which I'm using) handles it okay.
So, it is obviously a 32-bits BASIC. MBASIC was first written for the 8-bit Intel 8080, before being ported to the 16-bit Intel 8088 CPU of the IBM PC. Until Quick BASIC, it was always the same FP math routines. (Before the 8087.)
> By subtracting another 11 x 400 years from the date represented by > 113929 I've found that you can replace the constant with 4. Even > so, the values for j calculated by the rest of the function may > require more than 24 bits for far-future dates (after 40,000 years!).
I tested this. (I have another program which display all the dates vertically.) I compared both versions: they display the same result. So, this simplifies quite a lot the formula.
By the way, speaking of formula, during an Internet search, I found:
' days to J2000 - FNday may only work from 1900 to 2100 - see Meeus DEF FNday (y, m, d, h) = 367 * y - 7 * (y + (m + 9) \ 12) \ 4 + 275 * m \ 9 + d - 730531.5 + h / 24
So, the original test IF y < 100 THEN y = y + 1900 was intented because the original programmer was expecting that his program would provide good results only for the range 1900-2100... In practice, his program is a little bit better.
I also tested the Wikipedia Gregorian-to-Julian algorithm:
> By the way, speaking of formula, during an Internet search, I found:
> ' days to J2000 - FNday may only work from 1900 to 2100 - see Meeus > DEF FNday (y, m, d, h) = 367 * y - 7 * (y + (m + 9) \ 12) \ 4 + 275 * > m \ 9 + d - 730531.5 + h / 24
> So, the original test IF y < 100 THEN y = y + 1900 was intented > because the original programmer was expecting that his program would > provide good results only for the range 1900-2100... In practice, his > program is a little bit better.
> I also tested the Wikipedia Gregorian-to-Julian algorithm:
As before, your program wants to use the Julian date + 1, so add one to the above.
The problem, as far as variable range is concerned, will be with the y*365 term. Maybe you can reduce the year by multiples of 400 to restrict the required range.
> As before, your program wants to use the Julian date + 1, so > add one to the above.
> The problem, as far as variable range is concerned, will be with > the y*365 term. Maybe you can reduce the year by multiples of > 400 to restrict the required range.
Sorry, I should have included the fact that the year and month numbers should first be adjusted as follows before applying the above:
>>> ' Calculate the Julian Day number + 1.5 >>> ' >>> 390 j = 367*y-INT(7*(y+INT((m+9)/12))/4)+INT(275*m/9)+1721031! >>> 400 k = 0 : IF m <= 2 THEN k = -1 >>> 410 j = j - INT (3 * (INT ((y + k) / 100) + 1) / 4)
>> I had not understood that "J" was meaning "Julian". Question: Why, in >> a Gregorian calendar, compute a Julian day? Could you explain more the >> formula in line 390? What is the purpose of the last number, 1721031? >> Would an INTEGER version (probably 21031) still works? This is the >> only Single Precision Floating-Point number of the program. Everything >> else fit easily inside INTEGERs.
>The Julian Day number is not the same thing as a Julian Date. >Julian dates correspond to the Julian calendar system,
Not always. Some of your Southern Neighbors use the term for Ordinal Date (YYYY-DDD).
> along >with its leap years every four years, whereas Julian Day number >is a sequential count of days (and fractional portions thereof) >from the beginning of the year -4712.
No; from noon GMT of that year. One cannot convert a local date to a Julian Date, unless one is 12 hours away from GMT. It is Chronological Julian Day Number which counts from 0.0 at the beginning of the local year.
>Since the gregorian calendar repeats itself every 400 years >you should be able to modify the constant. JD 1721031 >corresponds to a date in the Gregorian algorithm of December 5, 2BCE >(note I don't say Gregorian calendar, since it didn't come into >play until the 1500's).
You can say proleptic [astronomical] Gregorian Calendar.
The best base date, for AD work, is 0000-03-01 = Day 0; it simplifies the arithmetic.
-- (c) John Stockton, nr London, UK. ?...@merlyn.demon.co.uk Turnpike v6.05 MIME. Web <URL:http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms & links; Astro stuff via astron-1.htm, gravity0.htm ; quotings.htm, pascal.htm, etc. No Encoding. Quotes before replies. Snip well. Write clearly. Don't Mail News.
In sci.astro message <dfa89564-81f4-4957-b890-6bd080876...@37g2000yqm.go oglegroups.com>, Sat, 21 Nov 2009 11:30:15, "Mr Emmanuel Roche, France" <roche...@laposte.net> posted:
>I then searched on the Internet for the "last day of the Gregorian >calendar": most answers I found simply say: "31 December"... I was >meaning: which year. According to Wikipedia "Gregorian calendar": >"This approximation has an error of about one day per 3300 years". >That is to say: the Gregorian calendar starts in 1582 and, 3300 years >later, will have to be modified. The year most commonly mentioned was >4099 (some say 4100), so I use it for the upper limit.
The Gregorian Calendar cannot be modified to suit the facts, since it was decreed /in perpetuo/. Remember that the Julian Calendar was not modified; it was replaced for civil use by the Gregorian.
We may well have a new Calendar eventually; but we will need to be careful not to name it after anyone called Gregory.
-- (c) John Stockton, nr London, UK. ?...@merlyn.demon.co.uk Turnpike v6.05. Web <URL:http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms PAS EXE etc : <URL:http://www.merlyn.demon.co.uk/programs/> - see 00index.htm Dates - miscdate.htm estrdate.htm js-dates.htm pas-time.htm critdate.htm etc.
In article <dfa89564-81f4-4957-b890-6bd080876...@37g2000yqm.googlegroups.com>, "Mr Emmanuel Roche, France" <roche...@laposte.net> wrote:
<snip>
> [...] I found on the Internet that the first legal Gregorian date was > Friday 15 October 1582. Since the program work only on inputted > months and years, I could only check them.
> I then searched on the Internet for the "last day of the Gregorian > calendar": most answers I found simply say: "31 December"... I was > meaning: which year. According to Wikipedia "Gregorian calendar": > "This approximation has an error of about one day per 3300 years". > That is to say: the Gregorian calendar starts in 1582 and, 3300 years > later, will have to be modified. The year most commonly mentioned was > 4099 (some say 4100), so I use it for the upper limit.
That assumes it will be decided that the calendar needs modification precisely when the accumulated discrepancy between it and the tropical year reaches 24.0 hours -- questionable IMO. The main concern for Pope Gregory _et al._ was for Easter not to arrive too long after the vernal equinox, a non-issue for secular purposes, and at any rate by their time the calendar had been allowed to creep a full ten days out of synch before the reform was considered necessary.
> In sci.astro message <4b0856c4$0$1587$9a6e1...@news.newshosting.com>, > Sat, 21 Nov 2009 16:08:17, Greg Neill <gneil...@MOVEsympatico.ca> > posted: >> Mr Emmanuel Roche, France wrote:
>>>> ' Calculate the Julian Day number + 1.5 >>>> ' >>>> 390 j = 367*y-INT(7*(y+INT((m+9)/12))/4)+INT(275*m/9)+1721031! >>>> 400 k = 0 : IF m <= 2 THEN k = -1 >>>> 410 j = j - INT (3 * (INT ((y + k) / 100) + 1) / 4)
>>> I had not understood that "J" was meaning "Julian". Question: Why, in >>> a Gregorian calendar, compute a Julian day? Could you explain more the >>> formula in line 390? What is the purpose of the last number, 1721031? >>> Would an INTEGER version (probably 21031) still works? This is the >>> only Single Precision Floating-Point number of the program. Everything >>> else fit easily inside INTEGERs.
>> The Julian Day number is not the same thing as a Julian Date. >> Julian dates correspond to the Julian calendar system,
> Not always. Some of your Southern Neighbors use the term for Ordinal > Date (YYYY-DDD).
That would be the Ordinal Date. In my opinion it's better to avoid referring to it as a Julian Day Number, in order to avoid confusion.
>> along >> with its leap years every four years, whereas Julian Day number >> is a sequential count of days (and fractional portions thereof) >> from the beginning of the year -4712.
> No; from noon GMT of that year. One cannot convert a local date to a > Julian Date, unless one is 12 hours away from GMT. It is Chronological > Julian Day Number which counts from 0.0 at the beginning of the local > year.
Picky picky. I was just describing the idea behind the Julian Day Number to distinguish it from a Julian Date, not offering a precise definition.
>> Since the gregorian calendar repeats itself every 400 years >> you should be able to modify the constant. JD 1721031 >> corresponds to a date in the Gregorian algorithm of December 5, 2BCE >> (note I don't say Gregorian calendar, since it didn't come into >> play until the 1500's).
> You can say proleptic [astronomical] Gregorian Calendar.
> The best base date, for AD work, is 0000-03-01 = Day 0; it simplifies > the arithmetic.
> In sci.astro message <dfa89564-81f4-4957-b890-6bd080876...@37g2000yqm.go > oglegroups.com>, Sat, 21 Nov 2009 11:30:15, "Mr Emmanuel Roche, France" > <roche...@laposte.net> posted:
>> I then searched on the Internet for the "last day of the Gregorian >> calendar": most answers I found simply say: "31 December"... I was >> meaning: which year. According to Wikipedia "Gregorian calendar": >> "This approximation has an error of about one day per 3300 years". >> That is to say: the Gregorian calendar starts in 1582 and, 3300 years >> later, will have to be modified. The year most commonly mentioned was >> 4099 (some say 4100), so I use it for the upper limit.
> The Gregorian Calendar cannot be modified to suit the facts, since it > was decreed /in perpetuo/. Remember that the Julian Calendar was not > modified; it was replaced for civil use by the Gregorian.
> We may well have a new Calendar eventually; but we will need to be > careful not to name it after anyone called Gregory.
Well, I'd best stop working on my perpetual calendar then. :-)
In sci.astro message <32743260-995a-497d-9380-0b6cab54a...@a31g2000yqn.g ooglegroups.com>, Sun, 22 Nov 2009 05:10:10, "Mr Emmanuel Roche, France" <roche...@laposte.net> posted:
>Except for the famous lines:
>400 j = 367*y-INT(7*(y+INT((m+9)/12))/4)+INT(275*m/9)+1721031! >410 k = 0 : IF m <= 2 THEN k = -1 >420 j = j - INT (3 * (INT ((y + k) / 100) + 1) / 4)
>Everything is now clear.
>(So far, I could not find exactly the same algorithm on the Internet.)
<URL:http://www.merlyn.demon.co.uk/js-date1.htm#CDC> has essentially that, under "Y M D to MJD without using a Date Object", in "function PauSch". Google for +schlyter +367 +275 and <stjarnhimlen.se/comp/p pcomp.html> comes up first.
-- (c) John Stockton, nr London, UK. ?...@merlyn.demon.co.uk Turnpike v6.05. Web <URL:http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms PAS EXE etc : <URL:http://www.merlyn.demon.co.uk/programs/> - see 00index.htm Dates - miscdate.htm estrdate.htm js-dates.htm pas-time.htm critdate.htm etc.
In sci.astro message <4b09fdb1$0$1615$9a6e1...@news.newshosting.com>, Sun, 22 Nov 2009 22:12:44, Greg Neill <gneil...@MOVEsympatico.ca> posted:
>> Not always. Some of your Southern Neighbors use the term for Ordinal >> Date (YYYY-DDD).
>That would be the Ordinal Date.
That's no doubt why I called it the Ordinal Date.
-- (c) John Stockton, Surrey, UK. ?...@merlyn.demon.co.uk Turnpike v6.05 MIME. Web <URL:http://www.merlyn.demon.co.uk/> - FAQish topics, acronyms, & links. Proper <= 4-line sig. separator as above, a line exactly "-- " (SonOfRFC1036) Do not Mail News to me. Before a reply, quote with ">" or "> " (SonOfRFC1036)
> <URL:http://www.merlyn.demon.co.uk/js-date1.htm#CDC> > has essentially that, under "Y M D to MJD without using a Date > Object", in "function PauSch". Google for +schlyter +367 +275 > and <stjarnhimlen.se/comp/ppcomp.html> comes up first.
I had a look to this Newsgroup, to see if my CALENDAR.BAS had generated any comments since I left.
I followed a few threads, and think that I have finally found the source of this algorithm, but not where you were thinking.
You pointed to this paragraph:
3. The time scale
The time scale in these formulae are counted in days. Hours, minutes, seconds are expressed as fractions of a day. Day 0.0 occurs at 2000 Jan 0.0 UT (or 1999 Dec 31, 0:00 UT). This "day number" d is computed as follows (y=year, m=month, D=date, UT=UT in hours+decimals):
d = 367*y - 7 * ( y + (m+9)/12 ) / 4 + 275*m/9 + D - 730530
Note that ALL divisions here should be INTEGER divisions. In Pascal, use "div" instead of "/", in MS-Basic, use "\" instead of "/". In Fortran, C and C++ "/" can be used if both y and m are integers. Finally, include the time of the day, by adding:
d = d + UT/24.0 (this is a floating-point division)
-----------
Ok. There is the formula, but no mention of its origin... Keeping searching, I found:
' FNday only works between 1901 to 2099 - see Meeus Chapter 7 ' DEF FNday (y,m,d,h) = 367 * y - 7 * (y + (m + 9) \ 12) \ 4 + 275 * m\ 9 + d - 730531.5 + h / 24
Again, this "Meeus"! And a chapter is even given! Next search:
- "Astronomical Formulae for Calculators", Jean Meeus, 4th ed, Willmann-Bell 1988, ISBN 0-943396-22-0
- "Astronomical Algorithms", Jean Meeus, 1st ed, Willmann-Bell 1991, ISBN 0-943396-35-2
Two standard references for many kinds of astronomical computations. Meeus is an undisputed authority here---many other authors quote his books. "Astronomical Algorithms" is the more accurate and more modern of the two, and one can also buy a floppy disk containing software implementations (in BASIC or C) to that book.
In the field of celestial calculations, Jean Meeus has enjoyed wide acclaim and respect since long before microcomputers and pocket calculators appeared on the market. When he brought out his "Astronomical Formulae for Calculators" in 1979, it was practically the only book of its genre. It quickly became the "source among sources," even for other writers in the field. Many of them have warmly acknowledged their debt (or should have), citing the unparalleled clarity of his instructions and the rigor of his methods.
And now this Belgian astronomer has outdone himself yet again with Astronomical Algorithms! Virtually every previous handbook on celestial calculations (including his own earlier work) was forced to rely on formulae for the Sun, Moon, and planets that were developed in the last century — or at least before 1920. The past 10 years, however, have seen a stunning revolution in how the world's major observatories produce their almanacs. The Jet Propulsion Laboratory in California and the U.S. Naval Observatory in Washington, D.C., have perfected powerful new machine methods for modeling the motions and interactions of bodies within the solar system. At the same time in Paris, the Bureau des Longitudes has been a beehive of activity aimed at describing these motions analytically, in the form of explicit equations.
Yet until now the fruits of this exciting work have remained mostly out of reach of ordinary people. The details have existed mainly on reels of magnetic tape in a form comprehensible only to the largest brains, human or electronic. But "Astronomical Algorithms" changes all that. With his special knack for computations of all sorts, the author has made the essentials of these modern techniques available to us all.
The second edition contains new chapters about the Jewish and Moslem Calendars, and on the satellites of Saturn, and a new Appendix giving expressions (polynomials) for the heliocentric coordinates of the giant planets Jupiter to Neptune from 1998 to 2025.
Note: We are currently shipping the June 2005 printing which corrects all known errors.
Table of Contents
Some Symbols and Abbreviations 5 1. Hints and Tips 7 2. About Accuracy 15 3. Interpolation 23 4. Curve Fitting 35 5. Iteration 47 6. Sorting Numbers 55 7. Julian Day 59 8. Date of Easter 67 9. Jewish and Moslem Calendars 71 10. Dynamical Time and Universal Time 77 11. The Earth’s Globe 81 12. Sidereal Time at Greenwich 87 13. Transformation of Coordinates 91 14. The Parallactic Angle 97 15. Rising, Transit and Setting 101 16. Atmospheric Refraction 105 17. Angular Separation 109 18. Planetary Conjunctions 117 19. Bodies in a Straight Line 121 20. Smallest Circle Containing Three Celestial Bodies 127 21. Precession 131 22. Nutation and the Obliquity of the Ecliptic 143 23. Apparent Place of a Star 149 24. Reduction of Ecliptical Elements from One Equinox to Another One 159 25. Solar Coordinates 163 26. Rectangular Coordinates of the Sun 171 27. Equinoxes and Solstices 177 28. Equation of Time 183 29. Ephemeris for Physical Observations of the Sun 189 30. Equation of Kepler 193 31. Elements of the Planetary Orbits 197 32. Positions of the Planets 217 33. Elliptic Motion 223 34. Parabolic Motion 241 35. Near-Parabolic Motion 245 36. The Calculation of some Planetary Phenomena 249 37. Pluto 263 38. Planets in Perihelion and Aphelion 269 39. Passages through the Nodes 275 40. Correction for Parallax 279 41. Illuminated Fraction of the Disk and Magnitude of a Planet 283 42. Ephemeris for Physical Observations of Mars 287 43. Ephemeris for Physical Observations of Jupiter 293 44. Positions of the Satellites of Jupiter 301 45. The Ring of Saturn 317 46. Positions of the Satellites of Saturn 323 47. Position of the Moon 337 48. Illuminated Fraction of the Moon’s Disk 345 49. Phases of the Moon 349 50. Perigee and Apogee of the Moon 355 51. Passages of the Moon through the Nodes 363 52. Maximum Declinations of the Moon 367 53. Ephemeris for Physical Observations of the Moon 371 54. Eclipses 379 55. Semidiameters of the Sun, Moon and Planets 389 56. Stellar Magnitudes 393 57. Binary Stars 397 58. Calculation of a Planar Sundial 401 Appendix I Constants 407 Appendix II Some Astronomical Terms 409 Appendix III Planets: Periodic Terms 413 Appendix IV Coefficients for the Heliocentric Coordinates of Jupiter to Neptune, 1998–2025 455 Index
You will notice that Chapter 7 "Julian Day" is, indeeed, concerned with calculating it.
QED.
(This said, I have no special interest in 477 pages of algorithms to compute various astronomical things: all I wanted was to know the reason for the various variables. Maybe I should try to borrow it at the public library, to read Chapter 7?)
> You will notice that Chapter 7 "Julian Day" is, indeeed, concerned > with calculating it.
> QED.
> (This said, I have no special interest in 477 pages of algorithms to > compute various astronomical things: all I wanted was to know the > reason for the various variables. Maybe I should try to borrow it at > the public library, to read Chapter 7?)
Meeus doesn't go into any details on the actual origin of nor a derivation of the particular method he presents.
I think that if you want to be able to 'dissect' these methods you'll have to do some research on calendrical calculations, or track down the original papers of some of the method authors.
Google Books yoelds an interesting looking entry:
Calendrical Calculations by Edward M. Reingold, Nachum Dershowitz
In sci.astro message <3f2f3839-bbd1-4a7c-a9e1-e9f475f53...@o13g2000vbl.g ooglegroups.com>, Tue, 24 Nov 2009 00:21:46, "Mr Emmanuel Roche, France" <roche...@laposte.net> posted:
>I followed a few threads, and think that I have finally found the >source of this algorithm, but not where you were thinking. > ... >Ok. There is the formula, but no mention of its origin...
So many people have published algorithms of this nature, often without date or a claim to originality or a statement of where they came from; and so many algorithms are minor variations of others; it is generally impractical to determine who originated any daycount to/from date algorithm.
It's easier to assign origins for Easter routines, at least for pre-Web days.
-- (c) John Stockton, nr London, UK. ?...@merlyn.demon.co.uk Turnpike v6.05 MIME. Web <URL:http://www.merlyn.demon.co.uk/> - FAQqish topics, acronyms & links; Astro stuff via astron-1.htm, gravity0.htm ; quotings.htm, pascal.htm, etc. No Encoding. Quotes before replies. Snip well. Write clearly. Don't Mail News.
Be aware that Google Books has appeared to offer different levels of visibility to would-be readers in different locations, favouring North America (or parts thereof?).
Searching Google Books for +"Calendrical Calculations" +Dershowitz did not find that Millennium Edition, but found the 2007 one.
To me in UK, both are partially readable.
-- (c) John Stockton, Surrey, UK. ?...@merlyn.demon.co.uk Turnpike v6.05 MIME. Web <URL:http://www.merlyn.demon.co.uk/> - FAQish topics, acronyms, & links. Proper <= 4-line sig. separator as above, a line exactly "-- " (SonOfRFC1036) Do not Mail News to me. Before a reply, quote with ">" or "> " (SonOfRFC1036)