Simple conversions between Julian Dates and Julian/Gregorian calendar dates, supporting ancient dates (BCE)
pip install juliandate
A Julian Date such as 2440423.345486
indicates the number of days
(and fractional part) since noon January 1, 4713 BCE (Julian) or
November 24, 4714 BCE (Gregorian), a system proposed by Joseph
Scaliger
in 1583. 2440423
is the number of full days, and the fractional
part, 0.345486
indicates that a little more than a third of a day
has passed (since noon).
To convert this to a Gregorian calendar date:
>>> import juliandate as jd
>>> jd.to_gregorian(2440423.345139)
(1969, 7, 20, 20, 17, 0, 9609)
The return value is tuple consisting of the year, month, day, hour (in
24-hour format) minutes, seconds, and microseconds All are integers
and the last value is rounded to the nearest microsecond. This value,
(1969, 7, 20, 20, 17, 0, 9609)
, means July 20, 1969 at 20:17 or 8:17
PM (when Apollo 11 touched down on the moon). There is some
imprecision in the seconds due to floating-point division.
For ancient dates, conversions to the Julian calendar (and prior to 8 CE the Proleptic Julian Calendar) are supported.
>>> jd.to_julian(1705426)
(-43, 3, 15, 12, 0, 0, 0)
The negative year indicates BCE. 1 BCE is 0, so -43 means 44 BCE, and this value is March 15, 44 BCE (the Ides of March)
Note that since there is no fractional part of a day in 1705426
,
this comes out to noon, the start of the Julian Day. If we add half a
day or more, we will be into the next calendar day (March 16):
>>> jd.to_julian(1705426.5)
(-43, 3, 16, 0, 0, 0.0)
Conversions to the Proleptic Gregorian Calendar work as well. The Julian calendar date March 15, 44 BCE corresponds to a Gregorian Calendar date of March 13:
>>> jd.to_gregorian(1705426)
(-43, 3, 13, 12, 0, 0)
The reverse functions are:
>>> jd.from_gregorian(1969, 7, 20, 20, 17, 0, 0)
2440423.345138889
>>> jd.from_julian(-43, 3, 15, 0, 0, 0, 0)
1705425.5
Hours, minutes, seconds, and microseconds are optional so that latter could be:
>>> jd.from_julian(-43, 3, 15)
1705425.5
Julian dates begin at noon, the start of the astronomical day. This can lead to some confusion since a calendar day, such as March 15 44 BCE, runs from 1705425.5 (inclusive) to 1705426.5 (exclusive).
# Midnight
>>> jd.to_julian(1705425.5)
(-43, 3, 15, 0, 0, 0, 0)
# 6 AM
>>> jd.to_julian(1705425.75)
(-43, 3, 15, 6, 0, 0, 0)
# Noon
>>> jd.to_julian(1705426)
(-43, 3, 15, 12, 0, 0, 0)
# 9 PM
>>> jd.to_julian(1705426.25)
(-43, 3, 15, 18, 0, 0, 0)
# Midnight, next calendar day
>>> jd.to_julian(1705426.5)
(-43, 3, 16, 0, 0, 0, 0)
If all you care about is the calendar day, add 0.5 to the Julian Date and take the integral part. This will return noon of the calendar day. For example:
# 6 AM
>>> jd.to_julian(int(1705425.75 + 0.5))
(-43, 3, 15, 12, 0, 0)
# Noon
>>> jd.to_julian(int(1705426 + 0.5))
(-43, 3, 15, 12, 0, 0)
# 9 PM
>>> jd.to_julian(int(1705426.25 + 0.5))
(-43, 3, 15, 12, 0, 0)
juliandate
does not use Python datetime
objects because these do
not support dates before 1 CE. Any date that can be represented as a
Python datetime
can easily be converted:
>>> import juliandate as jd
>>> from datetime import datetime
>>> datetime(*jd.to_gregorian(2440423.345139))
datetime.datetime(1969, 7, 20, 20, 17, 0, 9609)
As noted above, floating-point math causes some imprecision in the seconds and microseconds. This is unavoidable since 24ths and 60ths don't divide equally. This round-trip, for instance, ends up being off by 7 microseconds. Take care if this is important.
>>> jd.to_gregorian(jd.from_gregorian(1969, 7, 20, 20, 17))
(1969, 7, 20, 20, 16, 59, 999993)
You can check juliandate
's calculations against the US Naval
Observeratory's Julian Date
Converter.
The conversion formulas used by juliandate
are valid only for JDN ≥ 0. That is, juliandate
calculations cannot be considered correct for dates before Julian January 1, 4713 BCE = Gregorian November 24, 4714 BCE.
juliandate
comes with a command-line script jd
for converting Juliand Days
$ jd 1705426.25
-43, 3, 13, 18, 0, 0, 0
Use jd -h
for more usage details.
The conversion formulas are taken from pages 604 and 606 of:
Seidelmann, P.K. 2006 Explanatory Supplement to the Astronomical Almanac: A Revision to the Explanatory Supplement to the Astronomical Ephemeris and the American Ephemeris and Nautical Almanac. Sausalito, University Science Books.
and pages 617–619 of:
Urban, Sean E., and P. Kenneth Seidelmann, eds. Explanatory Supplement to the Astronomical Almanac. 3. ed. Mill Valley, Calif: University Science Books, 2012.
Bug reports and pull requests are welcome on GitHub at https://github.com/seanredmond/juliandate