cwe*_*ton 29 .net c# datetime date julian-date
我需要将标准格里高利日期转换为儒略日日期.
我在C#中没有看到任何直接执行此操作的文档,但我发现许多帖子(谷歌搜索时)建议使用ToOADate.
ToOADate上的文档并未将此建议为Julian日期的有效转换方法.
任何人都可以澄清这个函数是否会准确地执行转换,或者可能是一个更合适的方法将DateTime转换为Julian格式的字符串.
在根据维基百科的Julian Day页面进行验证时,这为我提供了预期的数字
public static long ConvertToJulian(DateTime Date)
{
int Month = Date.Month;
int Day = Date.Day;
int Year = Date.Year;
if (Month < 3)
{
Month = Month + 12;
Year = Year - 1;
}
long JulianDay = Day + (153 * Month - 457) / 5 + 365 * Year + (Year / 4) - (Year / 100) + (Year / 400) + 1721119;
return JulianDay;
}
Run Code Online (Sandbox Code Playgroud)
但是,这并不了解所使用的幻数.
谢谢
参考文献:
Dav*_*Yaw 83
OADate类似于Julian Dates,但使用了不同的起点(1899年12月30日对公元前4713年1月1日),以及不同的"新的一天"点.Julian Dates认为中午是新的一天的开始,OADates使用现代定义,午夜.
1899年12月30日午夜的朱利安日期是2415018.5.这个方法应该给你正确的值:
public static double ToJulianDate(this DateTime date)
{
return date.ToOADate() + 2415018.5;
}
Run Code Online (Sandbox Code Playgroud)
至于算法:
if (Month < 3) ...:为了让神奇数字成为我们的权利,他们将二月放在今年的"年底".(153 * Month - 457) / 5:哇,这是一些严肃的魔术数字.
(int)(30.6 * Month - 91.4).30.6是每月的平均天数,不包括二月份(准确地说是30.63重复).91.4几乎是3月平均非2月份的天数.(30.6*3是91.8).365 * Year:每年的天数(Year / 4) - (Year / 100) + (Year / 400):每4年增加一个闰日,每100个减1个,每400个减1个. + 1721119:这是公元前1月3日的朱利安日期.由于我们将日历的"开始"从1月移到3月,我们将其用作抵消,而不是1月1日.由于没有零年,1 BC得到整数值0.至于为什么3月2日而不是3月1日,我猜这是因为整个月的计算结果仍然有点偏差.如果原作者使用- 462而不是- 457(- 92.4而不是- 91.4浮点数学),那么偏移将是3月1日.小智 8
而方法
public static double ToJulianDate(this DateTime date) { return date.ToOADate() + 2415018.5; }
Run Code Online (Sandbox Code Playgroud)
适用于现代日期,它有很大的缺点.
朱利安日期定义为负日期 - 即BCE(普通时代之前)日期,并且在天文计算中很常见.您不能构建年份小于0的DateTime对象,因此无法使用上述方法计算BCE日期的Julian日期.
1582年的格里高利历改革在10月4日至15日之间的历法中设置了11天.这些日期未在Julian日历或Gregorian日历中定义,但DateTime接受它们作为参数.此外,使用上述方法不会返回任何Julian日期的正确值.使用System.Globalization.JulianCalendar.ToDateTime()或将JulianCalendar时代传递到DateTime构造函数的实验仍然会对1582年10月5日之前的所有日期产生不正确的结果.
以下例程改编自Jean Meeus的"天文算法",从-4712年1月1日中午开始的所有日期返回正确的结果,在Julian日历上为零时间.如果传递的日期无效,它们也会抛出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);
}
}
Run Code Online (Sandbox Code Playgroud)
如果有人需要从儒略日期转换为 DateTime ,请参见下文:
public static DateTime FromJulianDate(double julianDate)
{
return DateTime.FromOADate(julianDate - 2415018.5);
}
Run Code Online (Sandbox Code Playgroud)