jwodder / julian-rs

Convert between Julian day numbers and Julian & Gregorian calendars
MIT License
3 stars 1 forks source link

Julian days tick over at noon #73

Open tysen opened 10 months ago

tysen commented 10 months ago

Hi, thanks for this crate. Any plans to handle the half day discrepancy caused by not considering the time of day? The documentation claims that Julian day 0 began at midnight, which is contrary to my understanding (that is, I understand that it began at noon UT on January 1, 4713 BC, proleptic Julian calendar).

I could handle this within my application but it seems better to handle it within this crate. I may be able to help with the implementation but I thought first to ask whether this was a conscious design decision.

jwodder commented 10 months ago

I am aware that the "technically correct" definition of Julian day numbers has them start at noon. I believe my thinking for the behavior of this crate went as follows:

So:

[^1]: That is, Calendar::now(), Calendar::at_system_time(), Calendar::at_unix_time(), system2jdn(), unix2jdn(), and jdn2unix().

tysen commented 10 months ago

All of my interaction w/ Julian dates has been in astronomy, wherein the 12 hour difference is relevant. Certainly, the whole noon thing is awkward (hence the move to MJD). I understand that there are other uses for the Julian day numbering system for which this discrepancy is not relevant.

My goal is predict the sky position (right ascension / declination) of various solar system objects (the planets, the sun, and Earth's moon) at specific points in the future at specific places on the planet. I have a separate tool to achieve this, and it takes as its input Julian dates. So I would like to convert from chrono::DateTime<Utc> to Julian dates. The 12 hours matter for most of these objects, and especially for the moon.

Here are some preliminary ideas for how to support this in this crate (any subset of these would help):

Rename julian::Date to julian::Day

The thought here is to use the distinction noted here between "Date" and "Day" where the former is the instant in time (including the fractional amount since the last noon) and the latter is only the integral part of this value.

Assume a 00:00:00 UTC timestamp for conversion to julian::Date and julian::Day from chrono::NaiveDate

That is:

// chrono::NaiveDate uses the Gregorian calendar, and a year 0, so this is November 24, 4714 BC
let start = chrono::NaiveDate::from_ymd_opt(-4713, 11, 24).unwrap();
let date: julian::Date = start.into(); // would be same for `julian::Day`
assert_eq(-1, date.julian_day_number()); // not 0

I think these are the least astonishing assumptions (midnight in UTC) to make for a chrono::NaiveDate.

Add a Date and/or Day ::modified_julian_day_number fn

In my opinion, MJD is the appropriate value to support if ticking over at midnight is a primary design goal.

Define a new julian::Date

Date could have an impl of From<DateTime<Utc>> and perhaps a Date::instant fn (maybe a better name exists) returning an f64 which is the (noon-based) Julian day number with the fractional (since noon) day included.

jwodder commented 9 months ago

I've been thinking about this on & off, and while I'm still unsure whether I want to do this or even when I might get around to doing it, if I were to support JDN rollover at noon, I'd do something like the following, just adding functionality without breaking anything: