A Space & astronomy forum. SpaceBanter.com

Go Back   Home » SpaceBanter.com forum » Astronomy and Astrophysics » Astronomy Misc
Site Map Home Authors List Search Today's Posts Mark Forums Read Web Partners

Perpetual Gregorian Calendar



 
 
Thread Tools Display Modes
  #1  
Old November 20th 09, 11:35 PM posted to sci.astro
Mr. Emmanuel Roche, France
external usenet poster
 
Posts: 1
Default 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  
Old November 21st 09, 02:51 AM posted to sci.astro
dlzc
external usenet poster
 
Posts: 1,426
Default 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  
Old November 21st 09, 03:08 AM posted to sci.astro
Greg Neill[_6_]
external usenet poster
 
Posts: 605
Default 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  
Old November 21st 09, 03:13 PM posted to sci.astro
Greg Neill[_6_]
external usenet poster
 
Posts: 605
Default 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  
Old November 21st 09, 06:46 PM posted to sci.astro
Dr J R Stockton[_50_]
external usenet poster
 
Posts: 7
Default 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  
Old November 21st 09, 07:30 PM posted to sci.astro
Mr Emmanuel Roche, France
external usenet poster
 
Posts: 4
Default 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  
Old November 21st 09, 09:08 PM posted to sci.astro
Greg Neill[_6_]
external usenet poster
 
Posts: 605
Default 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  
Old November 22nd 09, 01:10 PM posted to sci.astro
Mr Emmanuel Roche, France
external usenet poster
 
Posts: 4
Default 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  
Old November 22nd 09, 01:57 PM posted to sci.astro
Greg Neill[_6_]
external usenet poster
 
Posts: 605
Default 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  
Old November 22nd 09, 04:07 PM posted to sci.astro
Mr Emmanuel Roche, France
external usenet poster
 
Posts: 4
Default 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

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump

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


All times are GMT +1. The time now is 05:39 PM.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Copyright ©2004-2024 SpaceBanter.com.
The comments are property of their posters.