|
|
Thread Tools | Display Modes |
#1
|
|||
|
|||
Perpetual Gregorian Calendar
Hello from France!
I am a retired COBOL programmer. 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/resou...tml?page=3&c=y 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. Yours Sincerely, Mr. Emmanuel Roche, France |
#2
|
|||
|
|||
Perpetual Gregorian Calendar
Dear Mr. Emmanuel Roche, France:
On Nov 20, 4:35*pm, "Mr. Emmanuel Roche, France" wrote: .... Hence my interest: I would really like to know the reason of the variables and their values. Probably better to choose a more modern implementation, one done with better comments: http://staffwww.fullcoll.edu/dcraig/.../javasteps.pdf David A. Smith |
#3
|
|||
|
|||
Perpetual Gregorian Calendar
dlzc wrote:
Dear Mr. Emmanuel Roche, France: On Nov 20, 4:35 pm, "Mr. Emmanuel Roche, France" wrote: ... Hence my interest: I would really like to know the reason of the variables and their values. Probably better to choose a more modern implementation, one done with better comments: http://staffwww.fullcoll.edu/dcraig/.../javasteps.pdf David A. Smith Oh yes, that's much better; *none* of the underlying mathematics is there! I suspect that the OP was interested in the particular algorithm used in the S&T article. |
#4
|
|||
|
|||
Perpetual Gregorian Calendar
Mr. Emmanuel Roche, France wrote:
Hello from France! I am a retired COBOL programmer. 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/resou...tml?page=3&c=y 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 |
#5
|
|||
|
|||
Perpetual Gregorian Calendar
In sci.astro message , Sat, 21
Nov 2009 00:35:00, "Mr. Emmanuel Roche, France" 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. URL:http://www.merlyn.demon.co.uk/js-date6.htm#SC URL:http://www.merlyn.demon.co.uk/vb-date2.htm#AM -- (c) John Stockton, nr London, 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. |
#6
|
|||
|
|||
Perpetual Gregorian Calendar
Hello, Greg!
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. Yours Sincerely, Mr. Emmanuel Roche, France |
#7
|
|||
|
|||
Perpetual Gregorian Calendar
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, 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.) Sure. |
#8
|
|||
|
|||
Perpetual Gregorian Calendar
Hello, Greg!
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/resou...tml?page=3&c=y 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 October 1582 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Another calendar (Y/N)? n Ok Such a range should be enough. 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. Yours Sincerely, Mr. Emmanuel Roche, France |
#9
|
|||
|
|||
Perpetual Gregorian Calendar
Mr Emmanuel Roche, France wrote:
Hello, Greg! 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. Yours Sincerely, Mr. Emmanuel Roche, France |
#10
|
|||
|
|||
Perpetual Gregorian Calendar
Re-Hello, Greg!
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. 400 j = 367*y-INT(7*(y+INT((m+9)/12))/4)+INT(275*m/9)+4 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: JDN = (1461 × (Y + 4800 + (M - 14)/12))/4 +(367 × (M - 2 - 12 × ((M - 14)/12)))/12 - (3 × ((Y + 4900 + (M - 14)/12)/100))/4 + D - 32075 but it did not produce the same results. However, for the range that I shall use, 1900 to 2100, I have checked it several times, and found no problem so far. So, even in its restricted form, this program suits me fine. If "Sky & Telescope" wants to upload the updated version, no problem. It was a pleasure meeting you. I will now go to other adventures. Fair Wind, Mr. Emmanuel Roche, France |
Thread Tools | |
Display Modes | |
|
|
Similar Threads | ||||
Thread | Thread Starter | Forum | Replies | Last Post |
(More) Perpetual Motion Machines | G=EMC^2 Glazier[_1_] | Misc | 3 | November 9th 09 02:35 PM |
When was Gregorian calendar right? | Crown-Horned Snorkack | Astronomy Misc | 14 | May 2nd 08 07:11 PM |
Perpetual motion... | gb6726 | Astronomy Misc | 5 | November 12th 07 03:34 PM |
The Aplanatic Gregorian: A Neglected Telescope Design? | Quadibloc | Amateur Astronomy | 25 | September 27th 07 09:13 PM |
Perpetual Motion on the Moon | G=EMC^2 Glazier | Misc | 16 | May 4th 05 04:35 PM |