Skip to main content

juliandate

Simple conversions between Julian Dates and Julian/Gregorian calendar dates, supporting ancient dates (BCE)

Installation

pip install juliandate

Usage

Converting from Julian Date to Gregorian or Julian Calendar Date

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)

Both to_julian() and to_gregorian() raise a ValueError passed a negative number. The published algorithm is not defined for numbers less than 0.

Converting from Gregorian or Julian Calendar Date to Julian Date

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

The "Astronomical" Day

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)

No datetime Objects

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)

Imprecision and Domain

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.

Command Line Script

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.

Sources

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.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/seanredmond/juliandate

Release files for juliandate 1.0.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for juliandate 1.0.5
File Size Uploaded
juliandate-1.0.5.tar.gz 18.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for juliandate 1.0.5
File Interpreter ABI Platform
juliandate-1.0.5-py3-none-any.whl Python 3 none any Details

Total release size: 37.0 kB

Release files / juliandate-1.0.5.tar.gz

Download URL juliandate-1.0.5.tar.gz
Size 18.5 kB
Tags Source
SHA-256 checksum
How to use checksums
1272e8e7099110eba87a1d65badf01d984befb1271040896df51e99c523f502a
BLAKE2b-256 checksum
How to use checksums
1c38f023a2914ea89276da29b3ca5dba878f287491709248dff794a1a7c0d008
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.7

Release files / juliandate-1.0.5-py3-none-any.whl

Download URL juliandate-1.0.5-py3-none-any.whl
Size 18.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ac3f542916ce75ae92c4ac0b0dd6a491ab013c2a792865bfa550ae8660a18a27
BLAKE2b-256 checksum
How to use checksums
107deddba9471294305c5d918b4742747d87d0f88e23a87f192b9ad2fe9397e9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.0.1 CPython/3.12.7

Release history Release notifications | RSS feed

This release

1.0.5 This release

2 release files

1.0.4

2 release files

1.0.3

2 release files

1.0.2

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page