Hello.
When dealing with Astronomy, it can be useful to convert between Julian Day numbers, and Gregorian Calendar date.
If the topic intrigues you, then I recommend reading the article at Wikipedia Referenced in the code.
I have tested both handlers, and the conversion from a Julian Date Number seems to work for every date after but not including 15th October 1582, which was the day the Gregorian Calendar Reform was implemented.
You can test the handlers towards this calculator.
# Version 1.5 corrected faulty truncation to integer in
# timeTriplet from JD
# Added handler for returning UTTIME(JD)
# Added handler converting from JDEtoJD(), and renamed its
# twin to JDtoJDE()
# Version 1.4 corrected faulty truncation to integer in
# gregorianCalendarTriplet
# Version 1.3 added: JDN_0h that returns Julian day at 0h
# Added JD_dayOfWeek that returns the weekday.
# version 1.2 Fixed up deltaT with horner and put here.
# Version 1.1 Added handler timeTriplet from JDN that
# returns time in "standard format
property EpochJD2000 : 2.451545E+6
property JulianDaysInCentury : 36525
# Added 19 sep 2013
# http://en.wikipedia.org/wiki/Julian_day
# http://macscripter.net/viewtopic.php?pid=166599#p166599
# JD stands for Julian Date. 0h is 00:00 midnight, 12h
# is 12:00 noon, GMT unless specified else wise.
# http://en.wikipedia.org/wiki/Julian_day
# set jdnr to JDN(1600, 1, 1, 12, 1, 17.8)
# for playing with time below.
# set jdnr to JDN(1600, 1, 1, 11, 30, 17.8)
#set time_now_GMT to (current date)
#tell time_now_GMT
#
#
# set year of it to 1995
# set month of it to 10
# set day of it to 1
#
# set hours of it to 9
# set minutes of it to 0
# set seconds of it to 0
#
#end tell
#tell (my datelib's makeDateTimeSextet(time_now_GMT))
# set JD to (my JulianDateLib's JDN(item 1, item 2, item 3, item 4, item 5, item 6))
#end tell
# my JulianDateLib's JDN(1995, 10, 1, 9, 0, 0)
# set jdnr to JDN(1582, 10, 16, 0, 0, 0)
# set mtime to timeTriplet from jdnr
# set gregTriplet to gregorianCalendarTriplet from jdnr
# Handlers that adjust the time of a JDN back to the
# civil system, where the day starts at 0h midnight with
# a 24 hour clock. It is your responsibility to differ
# Between UT and TD times (deltaT). Both handlers deliver
# the times in decimal time.
# returns the Julian day number at UT time 0h for that day.
on JDN_UT0h(JD)
return (JD - ((JD + 0.5) mod 1))
end JDN_UT0h
# returns the UTTime for a Julian Day number.
# the time is translated back to normal, that is
# 12 hours are added, since we are counting hours from
# Midnight, and not from noon the previous day!
on UTTIME(JD)
return ((JD + 0.5) mod 1)
end UTTIME
# returns a time triplet, from a Julian day number,
# Adjusted to return UT.
on timeTriplet from JDN
# This returns as standard time triplet, where the first point of time of a day is 00:00
# and the last point of a time is 23:59:59.9999999 and so on...
local timeFraction, tempvar, _hours, _minutes, _seconds
set timeFraction to (JDN mod 1) * 24
set tempvar to (timeFraction div 1 as integer)
set _hours to (tempvar + 12) mod 24
set timeFraction to (timeFraction - tempvar)
set _minutes to timeFraction * 60 div 1
set _seconds to (timeFraction - (_minutes / 60)) * 3600
return {_hours, _minutes, _seconds}
end timeTriplet
# Handlers that generates the Julian Day Number JD,
# or the Julian Ephemeris Time Daynber JED.
# for a given date and time sextet.
on JDN(_year, _month, _day, _hour, _min, _sec)
# From Wikipedia
# The Julian Date (JD) of any instant is the Julian day number
# for the preceding noon plus the fraction of the day since
# that instant. Julian Dates are expressed as a Julian day
# number with a decimal fraction added. For example, The Julian
# Date for 00:30:00.0 1 January 2013 is 2456293.520833.
local a, y, m, _JDN, time_fraction
set a to ((14 - _month) div 12)
set y to _year + 4800 - a
set m to _month + (12 * a) - 3
# Gregorian Calendar starts October 15, 1582
if _year > 1582 then
set _JDN to _day + ((153 * m + 2) div 5) + 365 * y + (y div 4) - y div 100 + y div 400 - 32045
else if _year = 1582 and _month > 10 then
set _JDN to _day + ((153 * m + 2) div 5) + 365 * y + (y div 4) - y div 100 + y div 400 - 32045
else if _year = 1582 and _month = 10 and _day ≥ 15 then
set _JDN to _day + ((153 * m + 2) div 5) + 365 * y + (y div 4) - y div 100 + y div 400 - 32045
else
# Julian calendar before oct 15, 1582
set _JDN to _day + ((153 * m + 2) div 5) + 365 * y + (y div 4) - 32083
end if
set _hour to (_hour - 12) / 24
if _min ≠0 then
set _min to _min / 1440 # minutes per day
end if
if _sec ≠0 then
set _sec to _sec / 86400 # seconds per day
end if
set _JDN to _JDN + _hour + _min + _sec
return _JDN
end JDN
on JDE(_year, _month, _day, _hour, _min, _sec)
# it is a way to get JDE directly when not
# JD is needed.
# From Wikipedia
# The Julian Date (JD) of any instant is the Julian day number
# for the preceding noon plus the fraction of the day since
# that instant. Julian Dates are expressed as a Julian day
# number with a decimal fraction added. For example, The Julian
# Date for 00:30:00.0 1 January 2013 is 2456293.520833.
local a, y, m, _JDN, time_fraction
set a to ((14 - _month) div 12)
set y to _year + 4800 - a
set m to _month + (12 * a) - 3
# Gregorian Calendar starts October 15, 1582
if _year > 1582 then
set _JDN to _day + ((153 * m + 2) div 5) + 365 * y + (y div 4) - y div 100 + y div 400 - 32045
else if _year = 1582 and _month > 10 then
set _JDN to _day + ((153 * m + 2) div 5) + 365 * y + (y div 4) - y div 100 + y div 400 - 32045
else if _year = 1582 and _month = 10 and _day ≥ 15 then
set _JDN to _day + ((153 * m + 2) div 5) + 365 * y + (y div 4) - y div 100 + y div 400 - 32045
else
# Julian calendar before oct 15, 1582
set _JDN to _day + ((153 * m + 2) div 5) + 365 * y + (y div 4) - 32083
end if
set _hour to (_hour - 12) / 24
if _min ≠0 then
set _min to _min / 1440 # minutes per day
end if
if _sec ≠0 then
set _sec to _sec / 86400 # seconds per day
end if
set _JDN to _JDN + _hour + _min + _sec
return (_JDN + ((deltaT(decimalYear(_year, _month))) / 86400))
end JDE
# utility handler that converts between JD and JDE dates
# (Adjusts for dynamical time)
on JDtoJDE(JD, yr, mnt)
# Meus p. 131, but the deltaT is from Nasa
return (JD + ((deltaT(decimalYear(yr, mnt))) / 86400))
end JDtoJDE
on JDEtoJD(JDE, yr, mnt)
# Meus p. 131, but the deltaT is from Nasa
return (JDE - ((deltaT(decimalYear(yr, mnt))) / 86400))
end JDEtoJD
# returns the number of Julian centuries that has passed
# since the JDE
on JulianCenturies by JDE
# Meeus (11.1)
return ((JDE - (my EpochJD2000)) / (my JulianDaysInCentury))
end JulianCenturies
# returns the day of a week for a JD 0 is sunday, 6 is Saturday
on JD_dayofweek(JD)
# Meeus p. 65
return (((JD div 1 + 0.5) + 1.5) mod 7)
end JD_dayofweek
# http://www2.arnes.si/~gljsentvid10/sidereal.htm
# The formula below will find the days since J2000.o for any
# date after 1900 and before 2099.
on JDAysSinceJD_2000(_year, _month, _day, _hour, _min, _sec)
# Faster way if you want the difference
set dwhole to 367 * _year - ¬
((7 * (_year + ((_month + 9) / 12) as integer) / 4) ¬
as integer) + ¬
((275 * _month / 9) as integer) + ¬
_day - 7.305315E+5
set dfrac to (_hour + _min / 60 + _sec / 3600) / 24
set JD to dwhole + dfrac + 1
# I have added one for the same result as if I
# subtracted 2.451545E+6 julian date 1 of januar 2000 00:00
# from a date for consistency
return JD
end JDAysSinceJD_2000
on gregorianCalendarTriplet from JDN
# This is an algorithm by Richards to convert a Julian Day Number, J, to a date in the Gregorian calendar
# (proleptic, when applicable). Richards does not state which dates the algorithm is valid for.
# it seems to work for dates after, BUT NOT INCLUDING 15th of oct 1582.
# I have extended it to return a hour, min, sec triplet for the fractional part of the JDN.
local y, m, n, r, p, v, s, w, b, c, f, g, h, d, MT, yr, JD
set y to 4716
set j to 1401
set m to 2
set n to 12
set r to 4
set p to 1461
set v to 3
set u to 5
set s to 153
set w to 2
set b to 274277
set c to -38
set JD to JDN div 1
set f to JD + j + (((4 * JD + b) div 146097) * 3) div 4 + c
set e to r * f + v
set g to (e mod p) div r
set h to u * g + w
set d to (h mod s) div u + 1
set MT to (h div s + m) mod n + 1
set yr to e div p - y + (n + m - MT) div n
return {yr, MT, d}
end gregorianCalendarTriplet
# aDecimalYear = year + (month - 0.5) / 12
# returns a decimal year as needed by deltaT
on decimalYear(yr, mnth)
return (yr + (mnth - 0.5) / 12)
end decimalYear
on deltaT(aDecimalYear)
# http://eclipse.gsfc.nasa.gov/SEcat5/deltatpoly.html
# simplifed, halved the contents of the if tests,
# and speeded up the multiplication of powers thanks to Nigel Garvey
# Further improved speed and space by implementing Horners rule. Sedgewick Algorithms
# second edition p. 525, but I found that a left to right approach with regards to
# coeffecients for the powers, (like below), was a *much* easier scheme to implement.
local t
if aDecimalYear < -500 then
set t to (aDecimalYear - 1820) / 100
return (-20 + 32 * (t ^ 2))
else if aDecimalYear < 500 then
set t to aDecimalYear / 100
return (1.05836E+4 + (t * (-1014.41 + (t * (33.78311 + (t * (-5.952053 + (t * (-0.1798452 + (t * (0.022174192 + (t * 0.0090316521))))))))))))
else if aDecimalYear < 1600 then
set t to (aDecimalYear - 1000) / 100
return (1574.2 + (t * (-556.01 + (t * (71.23472 + (t * (0.319781 + (t * (-0.8503463 + (t * (-0.005050998 + (t * 0.0083572073))))))))))))
else if aDecimalYear < 1700 then
set t to aDecimalYear - 1600
return (120 + (t * (-0.9808 + (t * (-0.01532 + (t / 7129))))))
else if aDecimalYear < 1800 then
set t to aDecimalYear - 1700
return (8.83 + (t * (0.1603 + (t * (-0.0059285 + (t * (1.3336E-4 - (t / 1174000))))))))
else if aDecimalYear < 1860 then
set t to aDecimalYear - 1800
return (13.72 + (t * (-0.332447 + (t * (0.0068612 + (t * (0.0041116 + (t * (-3.7436E-4 + (t * (1.21272E-5 + (t * (-1.69E-7 + (t * 8.75E-10))))))))))))))
else if aDecimalYear < 1900 then
set t to aDecimalYear - 1860
return (7.62 + (t * (0.5737 + (t * (-0.251574 + (t * (0.01680668 + (t * (-4.473624E-4 + (t / 233174))))))))))
else if aDecimalYear < 1920 then
set t to aDecimalYear - 1900
return (-2.79 + (t * (1.494119 + (t * (-0.0598939 + (t * (0.0061966 - (t * 1.97E-4))))))))
else if aDecimalYear < 1941 then
set t to aDecimalYear - 1920
return (21.2 + (t * (0.84493 + (t * (-0.0761 + (t * 0.0020936))))))
else if aDecimalYear < 1961 then
set t to aDecimalYear - 1950
return (29.07 + (t * (0.407 + (t * (-1 / 233 + (t / 2547))))))
else if aDecimalYear < 1986 then
set t to aDecimalYear - 1975
return (45.45 + (t * (1.067 + (t * (-1 / 260 - (t / 718))))))
else if aDecimalYear < 2005 then
set t to aDecimalYear - 2000
return (63.86 + (t * (0.3345 + (t * (-0.060374 + (t * (0.0017275 + (t * (6.51814E-4 + (t * 2.373599E-5))))))))))
else if aDecimalYear < 2050 then
set t to aDecimalYear - 2000 # (correct!)
return (62.92 + (t * (0.32217 + (t * 0.005589))))
else if aDecimalYear < 2150 then
return (-20 + (32 * (((aDecimalYear - 1820) / 100) ^ 2 - (0.5628 * (2150 - aDecimalYear)))))
else
set t to (aDecimalYear - 1820) / 100
return (-20 + (32 * (t ^ 2)))
end if
end deltaT