Хотя метод
public static double ToJulianDate(this DateTime date) { return date.ToOADate() + 2415018.5; }
работает для современных дат, он имеет существенные недостатки.
Юлианская дата определена для отрицательных дат - то есть дат до нашей эры (до общей эры) и является обычной в астрономических вычислениях.Вы не можете построить объект DateTime с годом меньше 0, и поэтому юлианская дата не может быть рассчитана для дат BCE с использованием вышеуказанного метода.
Реформа григорианского календаря 1582 года создала 11-дневную дыру в календаре между4 и 15 октября.Эти даты не определены ни в юлианском календаре, ни в григорианском календаре, но DateTime принимает их в качестве аргументов.Кроме того, использование вышеуказанного метода не возвращает правильное значение для любой юлианской даты.Эксперименты с использованием System.Globalization.JulianCalendar.ToDateTime () или передачей эры JulianCalendar в конструктор DateTime по-прежнему дают неверные результаты для всех дат до 5 октября 1582 года.
Следующие процедуры, адаптированные из Jean«Астрономические алгоритмы» Мееуса возвращают правильные результаты для всех дат, начиная с полудня 1 января, -4712, нулевого времени в юлианском календаре.Они также генерируют ArgumentOutOfRangeException, если передана недопустимая дата.
public class JulianDate
{
public static bool isJulianDate(int year, int month, int day)
{
// All dates prior to 1582 are in the Julian calendar
if (year < 1582)
return true;
// All dates after 1582 are in the Gregorian calendar
else if (year > 1582)
return false;
else
{
// If 1582, check before October 4 (Julian) or after October 15 (Gregorian)
if (month < 10)
return true;
else if (month > 10)
return false;
else
{
if (day < 5)
return true;
else if (day > 14)
return false;
else
// Any date in the range 10/5/1582 to 10/14/1582 is invalid
throw new ArgumentOutOfRangeException(
"This date is not valid as it does not exist in either the Julian or the Gregorian calendars.");
}
}
}
static private double DateToJD(int year, int month, int day, int hour, int minute, int second, int millisecond)
{
// Determine correct calendar based on date
bool JulianCalendar = isJulianDate(year, month, day);
int M = month > 2 ? month : month + 12;
int Y = month > 2 ? year : year - 1;
double D = day + hour/24.0 + minute/1440.0 + (second + millisecond / 1000.0)/86400.0;
int B = JulianCalendar ? 0 : 2 - Y/100 + Y/100/4;
return (int) (365.25*(Y + 4716)) + (int) (30.6001*(M + 1)) + D + B - 1524.5;
}
static public double JD(int year, int month, int day, int hour, int minute, int second, int millisecond)
{
return DateToJD(year, month, day, hour, minute, second, millisecond);
}
static public double JD(DateTime date)
{
return DateToJD(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, date.Millisecond);
}
}