Mientras que el método
public static double ToJulianDate(this DateTime date) { return date.ToOADate() + 2415018.5; }
obras para las fechas modernas, tiene importantes deficiencias.
La fecha juliana se define para fechas negativas, es decir, fechas BCE (antes de la era común) y es común en cálculos astronómicos. No puede construir un objeto DateTime con un año inferior a 0, por lo que la fecha juliana no se puede calcular para las fechas BCE utilizando el método anterior.
La reforma del calendario Gregoriano de 1582 puso un agujero de 11 días en el calendario entre el 4 y el 15 de octubre. Esas fechas no están definidas ni en el calendario juliano ni en el calendario gregoriano, pero DateTime las acepta como argumentos. Además, el uso del método anterior no devuelve el valor correcto para cualquier fecha juliana. Los experimentos con el uso de System.Globalization.JulianCalendar.ToDateTime() o al pasar la era JulianCalendar al constructor DateTime aún producen resultados incorrectos para todas las fechas anteriores al 5 de octubre de 1582.
Las siguientes rutinas, adaptadas de los "Astronomical Algorithms" de Jean Meeus, arrojan resultados correctos para todas las fechas a partir del mediodía del 1 de enero, -4712, hora cero en el calendario juliano. También lanzan una ArgumentOutOfRangeException si se pasa una fecha no válida.
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);
}
}
Gracias por esta explicación detallada. – cweston
+1. Impresionante publicación. – BSalita
Lo siento, no me gustan las matemáticas, pero lo hiciste genial. Gracias – fiberOptics