![]()
Here’s the code for the moon phase calculations included on
my Web pages. This is based on calculations given in the book
Duffett-Smith, Peter. 1988. Practical Astronomy with Your Calculator, 3rd Ed. Cambridge Univ. Press.
Here’s a QBASIC program I wrote that asks the user to supply a date, time, and time zone, then calculates the moon phase for that time. This is simplified from my original code which performed calculations for a three-month period. Since it is based on user input, I tried to include as much error checking as occurred to me. Also, the calculations are cumbersome in places because QBASIC does not do date arithematic.
DIM Months$(12)
SCREEN 13: WIDTH 80
'Get the date from the user.
Retry:
COLOR 1
INPUT "Enter a date in the format mm-dd-yyyy> ", ThisDate$
year = VAL(RIGHT$(ThisDate$, 4))
month = VAL(LEFT$(ThisDate$, 2))
day = VAL(MID$(ThisDate$, 4, 2))
IF year = 0 OR month = 0 OR day = 0 THEN
PRINT "You did not enter the date in the proper format."
IF year = 0 THEN PRINT "You specified a year of 0."
IF month = 0 THEN PRINT "You specified a month of 0."
IF day = 0 THEN PRINT "You specified a day of 0."
PRINT "Please try again using the format mm-dd-yyyy."
GOTO Retry
END IF
IF year < 1000 OR year > 2500 THEN
PRINT "The year you entered was"; year
PRINT "That doesn't make sense to me."
INPUT "Do you want to continue anyway?", Reply$
Reply$ = LEFT$(Reply$, 1)
Reply$ = LCASE$(Reply$)
IF Reply$ = "n" THEN
CLS
GOTO Retry
END IF
END IF
IF day < 1 THEN
PRINT "The day you entered was"; day
PRINT "That doesn't make sense to me."
PRINT "Try again using mm-dd-yyyy format."
GOTO Retry
END IF
LeapCheck = (year - 1980) MOD 4
IF LeapCheck = 0 THEN
leap$ = "yes"
ELSEIF LeapCheck <> 0 THEN
leap$ = "no"
END IF
SELECT CASE month
CASE 1
month$ = "January"
IF day > 31 GOTO TooMany
CASE 2
month$ = "February"
IF leap$ = "yes" AND day > 29 GOTO TooMany
IF leap$ = "no" AND day > 28 GOTO TooMany
CASE 3
month$ = "March"
IF day > 31 GOTO TooMany
CASE 4
month$ = "April"
IF day > 30 GOTO TooMany
CASE 5
month$ = "May"
IF day > 31 GOTO TooMany
CASE 6
month$ = "June"
IF day > 30 GOTO TooMany
CASE 7
month$ = "July"
IF day > 31 GOTO TooMany
CASE 8
month$ = "August"
IF day > 31 GOTO TooMany
CASE 9
month$ = "September"
IF day > 30 GOTO TooMany
CASE 10
month$ = "October"
IF day > 31 GOTO TooMany
CASE 11
month$ = "November"
IF day > 30 GOTO TooMany
CASE 12
month$ = "December"
IF day > 31 GOTO TooMany
CASE ELSE
month$ = STR$(month)
PRINT month$; " is not a valid month."
PRINT "Please try again."
GOTO Retry
END SELECT
GOTO Verify
TooMany:
PRINT "There aren't"; day; "days in "; month$
PRINT "Please try again."
GOTO Retry
Verify:
COLOR 2
PRINT "The day you chose was "; day; month$; year
COLOR 3
INPUT "Is this correct? ", Reply$
Reply$ = LEFT$(Reply$, 1)
Reply$ = LCASE$(Reply$)
IF Reply$ = "n" THEN
CLS
GOTO Retry
END IF
'Get the time from the user.
Timetry:
COLOR 4
INPUT "Enter a time in the format hh:mm:ss> ", ThisTime$
second = VAL(RIGHT$(ThisTime$, 2))
hour = VAL(LEFT$(ThisTime$, 2))
minute = VAL(MID$(ThisTime$, 4, 2))
IF hour < 0 THEN
PRINT "You specified less than 0 hours."
PRINT "Try again."
GOTO Timetry
ELSEIF minute < 0 THEN
PRINT "You specified less than 0 minutes."
PRINT "Try again."
GOTO Timetry
ELSEIF second < 0 THEN
PRINT "You specified less than 0 seconds."
PRINT "Try again."
GOTO Timetry
ELSEIF second > 60 THEN
PRINT "You specified more than 60 seconds."
PRINT "Try again."
GOTO Timetry
ELSEIF minute > 60 THEN
PRINT "You specified more than 60 minutes."
PRINT "Try again."
GOTO Timetry
ELSEIF hour > 24 THEN
PRINT "You specified more than 24 hours."
PRINT "Try again."
GOTO Timetry
END IF
TimeOfDay:
COLOR 5
INPUT "Is this AM or PM?", ampm$
ampm$ = LEFT$(ampm$, 1)
ampm$ = LCASE$(ampm$)
IF ampm$ = "a" OR ampm$ = "p" THEN GOTO FixIt
GOTO TimeOfDay
FixIt:
IF ampm$ = "p" AND hour < 12 THEN hour = hour + 12
IF ampm$ = "a" AND hour > 12 THEN hour = hour - 12
COLOR 6
PRINT "The time you chose is"; hour; ":"; minute; ":"; second; ampm$
COLOR 7
INPUT "Is this correct? ", Reply$
Reply$ = LEFT$(Reply$, 1)
Reply$ = LCASE$(Reply$)
IF Reply$ = "n" THEN
CLS
GOTO Timetry
END IF
' correct to GMT
TimeZone:
COLOR 9
PRINT "Choose a Time Zone:"
COLOR 10
PRINT "5. Eastern Standard Time"
COLOR 11
PRINT "4. Eastern Daylight Time"
COLOR 12
PRINT "6. Central Standard Time"
COLOR 13
PRINT "5. Central Daylight Time"
COLOR 14
PRINT "0. Greenwich Mean Time"
COLOR 15
INPUT "Pick a number corresponding to a time zone. ", choice
uthour = hour + choice
IF uthour >= 24 THEN
uthour = uthour - 24
IF uthour < 12 THEN ampm$ = "a"
day = day + 1
END IF
IF day > 31 AND month = 1 THEN
month = 2
month$ = "February"
day = 1
ELSEIF day > 29 AND month = 2 AND leap$ = "yes" THEN
month = 3
month$ = "March"
day = 1
ELSEIF day > 28 AND month = 2 AND leap$ = "no" THEN
month = 3
month$ = "March"
day = 1
ELSEIF day > 31 AND month = 3 THEN
month = 4
month$ = "April"
day = 1
ELSEIF day > 30 AND month = 4 THEN
month = 5
month$ = "May"
day = 1
ELSEIF day > 31 AND month = 5 THEN
month = 6
month$ = "June"
day = 1
ELSEIF day > 30 AND month = 6 THEN
month = 7
month$ = "July"
day = 1
ELSEIF day > 31 AND month = 7 THEN
month = 8
month$ = "August"
day = 1
ELSEIF day > 31 AND month = 8 THEN
month = 9
month$ = "September"
day = 1
ELSEIF day > 30 AND month = 9 THEN
month = 10
month$ = "October"
day = 1
ELSEIF day > 31 AND month = 10 THEN
month = 11
month$ = "November"
day = 1
ELSEIF day > 30 AND month = 11 THEN
month = 12
month$ = "December"
day = 1
ELSEIF day > 31 AND month = 12 THEN
month = 1
month$ = "January"
day = 1
year = year + 1
END IF
COLOR 2
PRINT "The date and time you chose was "; day; month$; year; uthour; ":"; minute; ":"; second; ampm$; " UT"
NumHrs = uthour + (minute + (second / 60)) / 60
'Calculate number of days since beginning of the specified year.
IF month > 2 GOTO No8 'no 3-2
DayNo = month - 1 'no 3-3
IF leap$ = "no" THEN 'no 3-4
DayNo = DayNo * 63
ELSEIF leap$ = "yes" THEN
DayNo = DayNo * 62
END IF
DayNo = DayNo \ 2 'no 3-5&6
GOTO No12 'no 3-7
No8:
DayNo = (month + 1) * 30.6 'no 3-8&9
DayNo = INT(DayNo) 'no 3-10
IF leap$ = "no" THEN 'no 3-11
DayNo = DayNo - 63
ELSEIF leap$ = "yes" THEN
DayNo = DayNo - 62
END IF
No12:
DayNo = DayNo + day 'no 3-12
DayNo = DayNo + NumHrs / 24
'PRINT "This is"; DayNo; "days into the year."
OtherDays = (year - 1990) * 365
leapdays = INT((year - 1989) / 4)
D = OtherDays + leapdays 'no 46-1
'PRINT "Days from Jan. 1 of current year to 0-0-90 is "; D
D = D + DayNo 'no 46-2
'PRINT "Total days from then is "; D
NoOfDays = D + nCounter / 2
N = NoOfDays * (360 / 365.242191#) 'no 46-3
N = ABS(N) - INT(ABS(N / 360)) * 360 'no 46-3
Mo = N + 279.403303# - 282.768422# 'no 46-4
IF Mo < 0 THEN Mo = Mo + 360 'no 46-4
Ec = 360 * .016713 * SIN(Mo * 3.141592654# / 180) / 3.141592654# 'no 46-5
lamda = N + Ec + 279.403303# 'no 46-6
IF lamda > 360 THEN lamda = lamda - 360 'no 46-6
'PRINT "N", "Mo", "Ec", "Lamda"
'PRINT N, Mo, Ec, lamda
l = 13.1763966# * NoOfDays + 318.351648# 'no 65-4
l = ABS(l) - INT(ABS(l / 360)) * 360 'no 65-4
Mm = l - .1114041 * D - 36.34041# 'no 65-5
Mm = ABS(Mm) - INT(ABS(Mm / 360)) * 360 'no 65-5
N65 = 318.510107# - .0529539 * NoOfDays 'no 65-6
N65 = ABS(N65) - INT(ABS(N65 / 360)) * 360 'no 65-6
Ev = 1.2739 * SIN((2 * (1 - lamda) - Mm) * 3.141592654# / 180) 'no 65-7
'PRINT "l", "Mm", "N65", "Ev"
'PRINT l, Mm, N65, Ev
Ae = .1858 * SIN(Mo * 3.141592654# / 180) 'no 65-8
A3 = .37 * SIN(Mo * 3.141592654# / 180) 'no 65-8
Mmp = Mm + Ev - Ae - A3 'no 65-9
Ec = 6.2886 * SIN(Mmp * 3.141592654# / 180) 'no 65-10
'PRINT "Ae", "A3", "Mmp", "Ec"
'PRINT Ae, A3, Mmp, Ec
A4 = .214 * SIN((2 * Mmp) * 3.141592654# / 180) 'no 65-11
lp = l + Ev + Ec - Ae + A4 'no 65-12
V = .6583 * SIN((2 * (lp - lamda)) * 3.141592654# / 180) 'no 65-13
lpp = lp + V 'no 65-14
'PRINT "A4", "lp", "V", "lpp"
'PRINT A4, lp, V, lpp
D67 = lpp - lamda 'no 67-2
F = .5 * (1 - COS(D67 * 3.141592654# / 180)) 'no 67-3
'PRINT "D67", "F"
'PRINT D67, F
x = (SIN(D67 * 3.141592654# / 180))
'variables created include: NoOfDays, F, x
IF F < .01 OR (F > .45 AND F < .55) OR F > .98 THEN
SELECT CASE F
CASE IS < .003
Phase$ = "New"
MoonDate = NoOfDays
GOTO GotIt
CASE .47 TO .53
IF SGN(x) > 0 THEN Phase$ = "First Quarter"
IF SGN(x) < 0 THEN Phase$ = "Last Quarter"
MoonDate = NoOfDays
GOTO GotIt
CASE IS > .997
Phase$ = "Full"
MoonDate = NoOfDays
GOTO GotIt
END SELECT
END IF
'variables created include Phase$, MoonDate=NoOfDays
GotIt:
Months$(1) = "Jan"
Months$(2) = "Feb"
Months$(3) = "Mar"
Months$(4) = "Apr"
Months$(5) = "May"
Months$(6) = "Jun"
Months$(7) = "Jul"
Months$(8) = "Aug"
Months$(9) = "Sep"
Months$(10) = "Oct"
Months$(11) = "Nov"
Months$(12) = "Dec"
MoonDate = MoonDate - D - (choice / 24) 'recalc date from start of loop - ut correction
MoonDate = MoonDate + day
MoonDate = ((MoonDate * 100) \ 10) / 10
TxtMonth$ = Months$(month)
IF MoonDate > 31 AND (month = 1 OR month = 3 OR month = 5 OR month = 7 OR month = 8 OR month = 10 OR month = 12) THEN
MoonDate = MoonDate - 31
TxtMonth$ = Months$(month)
ELSEIF MoonDate > 28 AND month = 2 AND leap$ = "no" THEN
MoonDate = MoonDate - 28
TxtMonth$ = Months$(month)
ELSEIF MoonDate > 29 AND month = 2 AND leap$ = "yes" THEN
MoonDate = MoonDate - 29
TxtMonth$ = Months$(month)
ELSEIF MoonDate > 30 AND (month = 4 OR month = 6 OR month = 9 OR month = 11) THEN
MoonDate = MoonDate - 30
TxtMonth$ = Months$(month)
END IF
IF MoonDate > INT(MoonDate + .5) THEN
MoonDate = INT(MoonDate)
ELSE
MoonDate = INT(MoonDate + .5)
END IF
COLOR 3
PRINT "Phase", "Date"
COLOR 4
PRINT Phase$, MoonDate; " "; TxtMonth$; " "; year
COLOR 5
|
This code was eventually “translated” into JavaScript, again performing calculations for a three-month period. Since JavaScript has some built-in date functions, the date arithematic was easier. Again, here is a simplified version of the code that grabs the user’s system time and calculates the moon phase from that. In my original version, I included the option for user input, thus considerable error checking (similar to the above) was included. Since this version does not allow for user input, but works from the system time, all that error checking (is it really a valid date?) has not been included. These calculations have subsequently been updated to compensate for browser Y2K bugs and a slight error in the former calculations.
today = new Date(); // initialize to current date
hh = today.getHours(); // goes from 0 to 23
var ampm = "am"
var NoLoops = hh // this variable is also used for the cuckoo clock
if(hh == 0) { NoLoops = 12};
if(hh > 12) { NoLoops = hh - 12; ampm = "pm" }
if(hh == 12) { ampm = "pm" }
var dd = today.getDate();
var mm = today.getMonth() + 1; // Jan is 0, Feb is 1, etc., hence the +1
var dow = today.getDay();
MonNames = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
var ThisMonth = MonNames[mm];
// var yy = today.getYear();
// browser Y2K bug fix -- convert from msec to years because getYear() doesn't work right
var millisec = today.getTime(); // this gives msecs
var yy = ((((millisec / 1000) / 3600) / 24) / 365.25);
yy = Math.floor(yy);
yy +=1970;
var txtDate = "" + ((dd < 10) ? "0" : "") + dd; // add 0 if less than 10 so displays right
txtDate += " " + ThisMonth;
txtDate += " " + yy;
var mn = today.getMinutes(); // goes from 0 to 59
var txtTime = "" + ((NoLoops < 10) ? "0" : "") + NoLoops;
txtTime += ((mn<10) ? ":0" : ":") + mn;
// here's where the calculations from the book start
var moondate = today;
tzone = moondate.getTimezoneOffset() / 60 // in min so convert to hours
var moonmsec = moondate.getTime(); // this gives msecs
GMtime = moonmsec + (tzone * 60 * 60 * 1000) // GMT in msec
// adapted from my VB code
var startDate = new Date(89, 11, 31, 00, 00, 00); // equivalent of the book's 0 Jan 90
var startMsec = startDate.getTime();
var dmsec = GMtime - startMsec;
D = ((((dmsec /1000) /60) /60) /24);
var n = D * (360 / 365.242191); //no 46-3
if (n > 0) {
n = n - Math.floor(Math.abs(n / 360)) * 360; //no 46-3
} else {
n = n + (360 + Math.floor(Math.abs(n / 360)) * 360); //no 46-3
}
var Mo = n + 279.403303 - 282.768422; //no 46-4;
if(Mo < 0) { Mo = Mo + 360 } //no 46-4
var Ec = 360 * .016713 * Math.sin(Mo * 3.141592654 / 180) / 3.141592654; //no 46-5
var lamda = n + Ec + 279.403303; //no 46-6
if(lamda > 360) { lamda = lamda - 360 } //no 46-6
var l = 13.1763966 * D + 318.351648; //no 65-4
if (l > 0) {
l = l - Math.floor(Math.abs(l / 360)) * 360; //no 65-4
} else {
l = l + (360 + Math.floor(Math.abs(l / 360)) * 360); //no 65-4
}
var Mm = l - .1114041 * D - 36.34041; //no 65-5
if (Mm > 0) {
Mm = Mm - Math.floor(Math.abs(Mm / 360)) * 360; //no 65-5
} else {
Mm = Mm + (360 + Math.floor(Math.abs(Mm / 360)) * 360); //no 65-5
}
var N65 = 318.510107 - .0529539 * D; //no 65-6
if (N65 > 0) {
N65 = N65 - Math.floor(Math.abs(N65 / 360)) * 360; //no 65-6
} else {
N65 = N65 + (360 + Math.floor(Math.abs(N65 / 360)) * 360); //no 65-6
}
var Ev = 1.2739 * Math.sin((2 * (l - lamda) - Mm) * 3.141592654 / 180); //no 65-7
var Ae = .1858 * Math.sin(Mo * 3.141592654 / 180); //no 65-8
var A3 = .37 * Math.sin(Mo * 3.141592654 / 180); //no 65-8
var Mmp = Mm + Ev - Ae - A3; //no 65-9
var Ec = 6.2886 * Math.sin(Mmp * 3.141592654 / 180); //no 65-10
var A4 = .214 * Math.sin((2 * Mmp) * 3.141592654 / 180); //no 65-11
var lp = l + Ev + Ec - Ae + A4; //no 65-12
var V = .6583 * Math.sin((2 * (lp - lamda)) * 3.141592654 / 180); //no 65-13
var lpp = lp + V; //no 65-14
var D67 = lpp - lamda; //no 67-2
Ff = .5 * (1 - Math.cos(D67 * 3.141592654 / 180)); //no 67-3
Xx = (Math.sin(D67 * 3.141592654 / 180));
// figure out what phase the moon is in and what icon to use to go with it
var MoonPhaseMsg = "Just for fun, the moon is ";
if(Ff < .02) {
document.write ('<IMG name="moonpic" SRC="graphics/steincarter/moon/moon01.gif" HEIGHT="32" WIDTH="32" ALIGN="right" alt="">');
MoonPhaseMsg += "new."
}
if((Ff > .45) && (Ff < .55) && (Xx > 0)) {
document.write ('<IMG name="moonpic" SRC="graphics/steincarter/moon/moon03.gif" HEIGHT="32" WIDTH="32" ALIGN="right" alt="">');
MoonPhaseMsg += "first quarter."
}
if((Ff > .45) && (Ff < .55) && (Xx < 0)) {
document.write ('<IMG name="moonpic" SRC="graphics/steincarter/moon/moon07.gif" HEIGHT="32" WIDTH="32" ALIGN="right" alt="">');
MoonPhaseMsg += "last quarter."
}
if(Ff > .98) {
document.write ('<IMG name="moonpic" SRC="graphics/steincarter/moon/moon05.gif" HEIGHT="32" WIDTH="32" ALIGN="right" alt="">');
MoonPhaseMsg += "full."
}
if((Ff > .02) && (Ff < .45) && (Xx > 0)) {
document.write ('<IMG name="moonpic" SRC="graphics/steincarter/moon/moon02.gif" HEIGHT="32" WIDTH="32" ALIGN="right" alt="">');
MoonPhaseMsg += "waxing."
}
if((Ff > .02) && (Ff < .45) && (Xx < 0)) {
document.write ('<IMG name="moonpic" SRC="graphics/steincarter/moon/moon08.gif" HEIGHT="32" WIDTH="32" ALIGN="right" alt="">');
MoonPhaseMsg += "waning."
}
if((Ff > .55) && (Ff < .98) && (Xx > 0)) {
document.write ('<IMG name="moonpic" SRC="graphics/steincarter/moon/moon04.gif" HEIGHT="32" WIDTH="32" ALIGN="right" alt="">');
MoonPhaseMsg += "waxing gibbous."
}
if((Ff > .55) && (Ff < .98) && (Xx < 0)) {
document.write ('<IMG name="moonpic" SRC="graphics/steincarter/moon/moon06.gif" HEIGHT="32" WIDTH="32" ALIGN="right" alt="">');
MoonPhaseMsg += "waning gibbous."
}
document.write (MoonPhaseMsg);
document.write (' The moon phase calculations are based on your computer reporting that is is');
document.write (" " + txtTime + " " + ampm + " on " + txtDate + ",\n");
document.write (' and that you are ' + tzone + ' hours from GMT.');
|
Here is the JavaScript code in action:
If you’re using Netscape, the time zone offset is properly
reported, but if you're using IE, the time zone offset is reported in
negative numbers (however, the calculations still appear to work OK). For
comparison, EST is +5 hours and EDT is +4 hours. From some information I
found on the Web a couple years ago, if your computer is incorrectly
reporting your time zone (they tend to think they’re in Silicon Valley unless
you tell them otherwise) and you want to fix it, you need to add a line
similar to set TZ=EST+05EDT to your
autoexec.bat file (goodness only knows how to fix Bill Gates’ new non-DOS
wonders...), but if you are not in the Eastern Time Zone (eastern United
States), you will need to use the correct time zone offset for your area.
If you are using Windows 95, make sure you have supplied the correct settings
in the Date/Time portion of the Control Panel.
The saga continues. . .
In December of 2000, I had need of this code in a Perl script. All year I
had been “fixing” JavaScript and Perl scripts because neither language was/is
Y2K-compliant and scripts variously reported year 2000 as either “0” or “100.”
Both JavaScript and Perl (and perhaps other computer languages) were written
such that 1 January 1970 is time 0. JavaScript keeps track of times before
then as negative milliseconds from that time. For example, if JavaScript is
given a date of
EarlyDate = new Date(1963,10,22,14,0,0);,
this is interpreted as
milliseconds from 1-1-1970. Perl’s date functions are more limited than
JavaScript’s, and it totally refuses to deal with negative time values.
Thus, while SomeDate = new Date(-123);
will work in JavaScript,
$SomeDate = time(-123); does not work
in Perl.
However, JavaScript does not easily deal with dates before the year 1000.
For example,
EarlyDate = new Date(63,10,22,14,0,0);
is interpreted as
milliseconds from 1-1-1970, but that’s not what I wanted. If I go to all the
trouble to “manually” calculate the necessary number of milliseconds, I can
force it to use the correct date.
theMsec = (-1906 * 365.25 * 24 * 3600 * 1000);
returns
theMsec = (-1906 * 365.25 * 24 * 3600 * 1000) + (-25 * 24 * 3600 * 1000);
returns
and finally,
theMsec = (-1906 * 365.25 * 24 * 3600 * 1000) + (-25 * 24 * 3600 * 1000) + (7 * 3600 * 1000);
returns
However, that date was not a Thursday! According to the astronomy book cited above, back in 1582, Pope Gregory decreed that the days 5 through 14 October of that year just did not/do not exist. JavaScript, however, reports the day before 15 October 1582 as being 14 October, not 4 October, and thus, any day-of-week calculations it does before then are ten days off. Also, Pope Gregory adjusted our time calculations such that, since then, years that end in “00” are only leap years if they are divisible by 400. That means that 1600 and 2000 were leap years, but 1700, 1800, and 1900 were not. JavaScript dutifully takes that into account, so as far as it is concerned, 29 February 1500 did not exist. That means that day-of-week calculations for any dates in the 1400s are 11 days off. While I haven’t checked, I would suppose the same is true for 1400, 1300, etc.
So... back to the handy astronomy book, which includes calculations for what astronomers call “Julian dates” in honor of Julius Caesar. Now, the JavaScript code looks like this (isLegal is another function that tests to see if user input is really a valid number):
var today = new Date();
var tzone = today.getTimezoneOffset() / 60; // in min so convert to hours
tzhr = tzone;
tzone = tzone / 24; // convert to fraction of a day
var FractDay = 0;
// EpochDate = new Date(89, 11, 31, 00, 00, 00); // equivalent of the book's 0 Jan 90
// is equiv to JD 2447891.5
var Epoch = 2447891.5;
function phasecalc() { //button click handler
yyy = document.form1.theYear.value;
isNameOK = 1;
NotASpace = 0;
isLegal(yyy, 1);
while (isNameOK == 0 || NotASpace == 0 || newNameStr > 9999 || newNameStr < -4713) {
testNo = prompt ('Your year number can’t be \"' + newNameStr + '\"! Put a valid year here:', newNameStr);
isLegal(testNo, 1);
}
document.form1.theYear.value = yyy = parseFloat(newNameStr);
newNameStr = "";
isLeap = 0;
testLeap = yyy % 4; // will be 0 in leap year
testCent = yyy % 100; // is it a century year
testSkip = yyy % 400; // for 1700, 1800, 1900, don't do leap year, (but yes for 1500, 1600, 2000)
if ((yyy <=1582 && testLeap == 0) || (yyy > 1582 && testLeap == 0 && testCent != 0) || (yyy > 1582 && testLeap == 0 && testCent == 0 && testSkip == 0)) {
isLeap == 1;
}
mmm = document.form1.theMnth.value;
isNameOK = 1;
NotASpace = 0;
isLegal(mmm, 1);
while (isNameOK == 0 || NotASpace == 0 || newNameStr > 12 || newNameStr < 1) {
testNo = prompt ('Your month number can’t be \"' + newNameStr + '\"! Put a valid month here:', newNameStr);
isLegal(testNo, 1);
}
document.form1.theMnth.value = mmm = parseFloat(newNameStr);
newNameStr = "";
ddd = document.form1.theDate.value;
isNameOK = 1;
NotASpace = 0;
isLegal(ddd, 1);
while (isNameOK == 0 || NotASpace == 0 || newNameStr < 1 || ((mmm == 1 || mmm == 3 || mmm == 5 || mmm == 7 || mmm == 8 || mmm == 10 || mmm == 12) && newNameStr > 31) || ((mmm == 4 || mmm == 6 || mmm == 9 || mmm == 11) && newNameStr > 30) || (mmm == 2 && isLeap == 0 && newNameStr > 28) || (mmm == 2 && isLeap == 1 && newNameStr > 29)) {
testNo = prompt ('Your date number can’t be \"' + newNameStr + '\"! Put a valid date here:', newNameStr);
isLegal(testNo, 1);
}
document.form1.theDate.value = ddd = parseFloat(newNameStr);
newNameStr = "";
hhh = document.form1.theHour.value;
isNameOK = 1;
NotASpace = 0;
isLegal(hhh, 1);
while (isNameOK == 0 || NotASpace == 0 || newNameStr < 0 || newNameStr > 23 || (yyy == -4713 && mmm == 1 && ddd == 1 && hhh < 12)) {
testNo = prompt ('Your hour number can’t be \"' + newNameStr + '\"! Put a valid hour here:', newNameStr);
isLegal(testNo, 1);
}
document.form1.theHour.value = hhh = parseFloat(newNameStr);
newNameStr = "";
FractDay = hhh / 24;
mmn = document.form1.theMins.value;
isNameOK = 1;
NotASpace = 0;
isLegal(mmn, 1);
while (isNameOK == 0 || NotASpace == 0 || newNameStr > 59 || newNameStr < 0) {
testNo = prompt ('Your minutes number can’t be \"' + newNameStr + '\"! Put a valid minutes here:', newNameStr);
isLegal(testNo, 1);
}
document.form1.theMins.value = mmn = parseFloat(newNameStr);
newNameStr = "";
FractDay += mmn / 60 / 24;
// this calculates the Julian Date
if (mmm < 3) { // if 1 or 2 (this has been changed to 1-base)
yyy--;
mmm += 12;
}
if ((yyy >= 1583) || (yyy == 1582 && mmm > 10) || (yyy == 1582 && mmm == 10 && ddd >= 15)) {
// if it's after Gregory changed the calendar
AtoJD = Math.floor(yyy / 100);
BtoJD = 2 - AtoJD + Math.floor(AtoJD / 4);
} else {
BtoJD = 0;
}
if (yyy < 0) {
CtoJD = Math.ceil((365.25 * yyy) - 0.75);
} else {
CtoJD = Math.floor(365.25 * yyy);
}
DtoJD = Math.floor(30.6001 * (mmm + 1)); // gotta use 1 bec mmm is 1-based
JD = parseFloat(BtoJD) + parseFloat(CtoJD) + parseFloat(DtoJD) + parseFloat(ddd) + parseFloat(1720994.5);
// add on hr & min fract of a day
JDnow = JD + FractDay;
// because I was also using this for something else,
// correct for time zone after convert to JD
// if >= 1990, use local time zone, otherwise assume GMT
// note, it doesn't matter if it calculates the date correctly if all we want is the timezone
// just remember that the time zone correction must first be converted to a fraction of a day
if (yyy >= 1990) {
JDnow += tzone;
}
// here is where the previous calculations start
// note the new way of calculating D -- the answer is the same
D = JDnow - Epoch; // find diff from 31 Dec 1989
var n = D * (360 / 365.242191); //no 46-3
if (n > 0) {
n = n - Math.floor(Math.abs(n / 360)) * 360; //no 46-3
} else {
n = n + (360 + Math.floor(Math.abs(n / 360)) * 360); //no 46-3
}
var Mo = n + 279.403303 - 282.768422; //no 46-4;
if(Mo < 0) { Mo = Mo + 360 } //no 46-4
var Ec = 360 * .016713 * Math.sin(Mo * 3.141592654 / 180) / 3.141592654; //no 46-5
var lamda = n + Ec + 279.403303; //no 46-6
if(lamda > 360) { lamda = lamda - 360 } //no 46-6
var l = 13.1763966 * D + 318.351648; //no 65-4
if (l > 0) {
l = l - Math.floor(Math.abs(l / 360)) * 360; //no 65-4
} else {
l = l + (360 + Math.floor(Math.abs(l / 360)) * 360); //no 65-4
}
var Mm = l - .1114041 * D - 36.34041; //no 65-5
if (Mm > 0) {
Mm = Mm - Math.floor(Math.abs(Mm / 360)) * 360; //no 65-5
} else {
Mm = Mm + (360 + Math.floor(Math.abs(Mm / 360)) * 360); //no 65-5
}
var N65 = 318.510107 - .0529539 * D; //no 65-6
if (N65 > 0) {
N65 = N65 - Math.floor(Math.abs(N65 / 360)) * 360; //no 65-6
} else {
N65 = N65 + (360 + Math.floor(Math.abs(N65 / 360)) * 360); //no 65-6
}
var Ev = 1.2739 * Math.sin((2 * (l - lamda) - Mm) * 3.141592654 / 180); //no 65-7
var Ae = .1858 * Math.sin(Mo * 3.141592654 / 180); //no 65-8
var A3 = .37 * Math.sin(Mo * 3.141592654 / 180); //no 65-8
var Mmp = Mm + Ev - Ae - A3; //no 65-9
var Ec = 6.2886 * Math.sin(Mmp * 3.141592654 / 180); //no 65-10
var A4 = .214 * Math.sin((2 * Mmp) * 3.141592654 / 180); //no 65-11
var lp = l + Ev + Ec - Ae + A4; //no 65-12
var V = .6583 * Math.sin((2 * (lp - lamda)) * 3.141592654 / 180); //no 65-13
var lpp = lp + V; //no 65-14
var D67 = lpp - lamda; //no 67-2
Ff = .5 * (1 - Math.cos(D67 * 3.141592654 / 180)); //no 67-3
Xx = (Math.sin(D67 * 3.141592654 / 180)); // I added this to distinguish first from last quarters
// figure out what phase the moon is in and what icon to use to go with it
if(Ff < .02) { //new
document.form1.Phase.src = "../../graphics/steincarter/moon/phase01.gif"
document.form1.moonpic.src = "../../graphics/steincarter/moon/moon01.gif"
}
if((Ff > .45) && (Ff < .55) && (Xx > 0)) { //first
document.form1.Phase.src = "../../graphics/steincarter/moon/phase03.gif"
document.form1.moonpic.src = "../../graphics/steincarter/moon/moon03.gif"
}
if((Ff > .45) && (Ff < .55) && (Xx < 0)) { //last
document.form1.Phase.src = "../../graphics/steincarter/moon/phase07.gif"
document.form1.moonpic.src = "../../graphics/steincarter/moon/moon07.gif"
}
if(Ff > .98) { //full
document.form1.Phase.src = "../../graphics/steincarter/moon/phase05.gif"
document.form1.moonpic.src = "../../graphics/steincarter/moon/moon05.gif"
}
if((Ff > .02) && (Ff < .45) && (Xx > 0)) { //waxing
document.form1.Phase.src = "../../graphics/steincarter/moon/phase02.gif"
document.form1.moonpic.src = "../../graphics/steincarter/moon/moon02.gif"
}
if((Ff > .02) && (Ff < .45) && (Xx < 0)) { //waning
document.form1.Phase.src = "../../graphics/steincarter/moon/phase08.gif"
document.form1.moonpic.src = "../../graphics/steincarter/moon/moon08.gif"
}
if((Ff > .55) && (Ff < .98) && (Xx > 0)) { //waxing gibbous
document.form1.Phase.src = "../../graphics/steincarter/moon/phase04.gif"
document.form1.moonpic.src = "../../graphics/steincarter/moon/moon04.gif"
}
if((Ff > .55) && (Ff < .98) && (Xx < 0)) { //waning gibbous
document.form1.Phase.src = "../../graphics/steincarter/moon/phase06.gif"
document.form1.moonpic.src = "../../graphics/steincarter/moon/moon06.gif"
}
}
|
Thus, for the date 22 Nov 63 (not 1963) at 00:00 GMT, the Julian date would be
I would ask that if you choose to make use of this code, that you please give credit where credit is due.