Astronomy Asked by vcapra1 on September 28, 2021
I’m trying to calculate the Julian Day, given a UTC year, month and date in the Gregorian calendar. I tried using the formula on Wikipedia, but that doesn’t work. Consider 2010-01-31 and 2010-02-01. These dates are exactly one day apart, but their JDNs, according to the formula on Wikipedia, are 2455230 and 2455229, respectively.
In fact, it seems that this issue appears at the beginning and end of February of every year. I wrote a Python script to go through every day from 2010-2020, and these are all similar discrepancies:
ERROR: 2010-01-31 00:00:00 (2455230) vs 2010-02-01 00:00:00 (2455229)
ERROR: 2010-02-28 00:00:00 (2455256) vs 2010-03-01 00:00:00 (2455259)
ERROR: 2011-01-31 00:00:00 (2455595) vs 2011-02-01 00:00:00 (2455594)
ERROR: 2011-02-28 00:00:00 (2455621) vs 2011-03-01 00:00:00 (2455624)
ERROR: 2012-01-31 00:00:00 (2455960) vs 2012-02-01 00:00:00 (2455959)
ERROR: 2012-02-29 00:00:00 (2455987) vs 2012-03-01 00:00:00 (2455989)
ERROR: 2013-01-31 00:00:00 (2456325) vs 2013-02-01 00:00:00 (2456325)
ERROR: 2013-02-28 00:00:00 (2456352) vs 2013-03-01 00:00:00 (2456355)
ERROR: 2014-01-31 00:00:00 (2456691) vs 2014-02-01 00:00:00 (2456690)
ERROR: 2014-02-28 00:00:00 (2456717) vs 2014-03-01 00:00:00 (2456720)
ERROR: 2015-01-31 00:00:00 (2457056) vs 2015-02-01 00:00:00 (2457055)
ERROR: 2015-02-28 00:00:00 (2457082) vs 2015-03-01 00:00:00 (2457085)
ERROR: 2016-01-31 00:00:00 (2457421) vs 2016-02-01 00:00:00 (2457420)
ERROR: 2016-02-29 00:00:00 (2457448) vs 2016-03-01 00:00:00 (2457450)
ERROR: 2017-01-31 00:00:00 (2457786) vs 2017-02-01 00:00:00 (2457786)
ERROR: 2017-02-28 00:00:00 (2457813) vs 2017-03-01 00:00:00 (2457816)
ERROR: 2018-01-31 00:00:00 (2458152) vs 2018-02-01 00:00:00 (2458151)
ERROR: 2018-02-28 00:00:00 (2458178) vs 2018-03-01 00:00:00 (2458181)
ERROR: 2019-01-31 00:00:00 (2458517) vs 2019-02-01 00:00:00 (2458516)
ERROR: 2019-02-28 00:00:00 (2458543) vs 2019-03-01 00:00:00 (2458546)
The JDNs also do not match those on NASA’s calculator, as it gives 2010-01-31 to be JD 2455228.
Since Wikipedia isn’t always the most reliable resource, I scoured the internet for another website with a formula, and all I found was this page, which gives me the same issue, with a slightly different, step-by-step formula.
Am I doing something wrong? I’m sorry if I am posting this in the wrong community, if there is a better place please let me know.
The code I used to get the list above is below, with the Wikipedia algorithm:
import datetime
prev_d = None
prev = 0
def calc(_d):
global prev_d
global prev
y = _d.year
m = _d.month
d = _d.day
# Formula from Wikipedia
jd = ((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)
if jd - prev != 1:
print("ERROR: {} ({}) vs {} ({})".format(prev_d, prev, _d, jd))
prev = jd
prev_d = _d
# Iterate day-by-day, starting 2010-01-01 UTC
for d in range(1262304000, 1262304000 + 60 * 60 * 24 * 365 * 10, 60 * 60 * 24):
calc(datetime.datetime.utcfromtimestamp(d))
```
The formula in the wikipedia article explicitly uses integer division with round toward zero. Python's integer division uses round toward negative infinity (i.e., floor).
The wikipedia article formula repeatedly uses (m-14)/12
. This evaluates to -1 for months 1 and 2 (January and February), zero otherwise. You can use the wikipedia article formula in python3 if you change every instance of (m-14)/12
in the wikipedia article formula to any of the following:
int((m-14)/12)
/
performs floating point division. Python's built-in int
function rounds toward zero.((m+9)//12-1)
(m+9)//12)
evaluates to 0 for January and February (m=1 and 2), 1 for all later months.(-1 if m<3 else 0)
Correct answer by David Hammen on September 28, 2021
Adding to the answers above: One of the problems here is that Julian Day Numbers start at noon of a particular Gregorian Date. For the dates under consideration
You mentioned needing a reliable source for date algorithms. I recommend https://www.researchgate.net/publication/316558298_Date_Algorithms (an earlier version is archived at https://web.archive.org/web/20090405221644/http:/mysite.verizon.net:80/aesir_research/date/date0.htm) which is specifically designed to help programmers write fast date algorithms. It includes specific dates needed to check your program, discusses integer vs. float, word length, and other issues. The document also gives proofs for variations of all the algorithms.
Answered by Peter Baum on September 28, 2021
The formula is correct. However, the "problem" is with Python1. https://stackoverflow.com/questions/5535206/negative-integer-division-surprising-result.
Here is the fix to the formula:
jd = (1461 * (y + 4800 + int(float(m-14)/12))) // 4 + (367 * (m - 2 - 12 * (int(float(m-14)/12)))) // 12 - (3 * ((y + 4900 + int(float(m-14)/12)) // 100)) // 4 + d - 32075
1Usually integer division means you drop all the decimal digits... like 4 / 3 = 1.333 = 1. But in Python, integer division means "floor" division which means you go to the smaller integer. Again, example above, 4/3 = 1. Problem is with negative. -4/3 = -1.3333 (which lies between -1 and -2, hence the smaller is -2). They suppose to fix that with Python 3.... but my version 3 still does not work. The work around is convert to float then using int on the answer to drop the decimals. As for the script above, (m-14) always negative no matter what month m is; hence, problem arises.
Answered by Huy Pham on September 28, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP