メソッド
public static double ToJulianDate(this DateTime date) { return date.ToOADate() + 2415018.5; }
現代の日付で機能しますが、重大な欠点があります。
ユリウス日は負の日付、つまり紀元前 (紀元前) の日付に対して定義され、天文学の計算では一般的です。年が 0 未満の DateTime オブジェクトを作成することはできないため、上記の方法を使用して紀元前の日付のユリウス日を計算することはできません。
1582 年のグレゴリオ暦の改革により、暦には 10 月 4 日から 15 日までの 11 日間の穴ができました。これらの日付は、ユリウス暦でもグレゴリオ暦でも定義されていませんが、DateTime はそれらを引数として受け入れます。さらに、上記のメソッドを使用すると、ユリウス日付の正しい値が返されません。System.Globalization.JulianCalendar.ToDateTime() を使用したり、JulianCalendar の紀元を DateTime コンストラクターに渡したりして実験を行っても、1582 年 10 月 5 日より前のすべての日付に対して正しくない結果が生成されます。
次のルーチンは、Jean Meeus の「Astronomical Algorithms」から採用されたもので、ユリウス暦のタイム ゼロである -4712 年 1 月 1 日の正午から始まるすべての日付に対して正しい結果を返します。また、無効な日付が渡された場合、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);
}
}