在C#中将日期时间转换为Julian日期(ToOADate Safe?) [英] Convert DateTime to Julian Date in C# (ToOADate Safe?)

查看:771
本文介绍了在C#中将日期时间转换为Julian日期(ToOADate Safe?)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要从标准的公历日期转换为朱利安日数。



我没有看到没有记录在C#中直接做到这一点,但是我发现了许多帖子(而Google Googling)建议使用 ToOADate



文档在 ToOADate 上不建议将其作为有效的转换方法为朱利安日期。



任何人都可以澄清这个功能是否能正确执行转换,也可能是一种更合适的方法来将DateTime转换为朱利安格式的字符串。






这个维基百科的朱利安日页验证时提供预期的数字

  public static long ConvertToJulian(DateTime Date)
{
int Month = Date.Month;
int Day = Date.Day;
int Year = Date.Year;

if(Month< 3)
{
Month = Month + 12;
年=年 - 1;
}
long JulianDay =天+(153 *月 - 457)/ 5 + 365 *年+(年/ 4) - (年/ 100)+(年/ 400)+ 1721119;
return JulianDay;
}

然而,这并不了解所使用的魔术数字。 p>

谢谢






参考文献: / p>


解决方案

OADate是类似的到朱利安日期,但使用不同的出发点(1899年12月30日与公元前4713年1月1日)和不同的新天点。朱利安日期认为中午是新的一天的开始,OADates使用现代定义,午夜。



1899年12月30日午夜的朱利安日期是2415018.5。这个方法应该给你正确的值:

  public static double ToJulianDate(this DateTime date)
{
return date.ToOADate()+ 2415018.5;
}

关于算法:




  • if(Month< 3)... :为了使魔术数字正常工作,

  • (153 *月 - 457)/ 5 :哇,这是一些严重的魔术数字。

    • 通常,每个月的天数为31 28 31 30 31 30 31 31 30 31 30 31,但在if语句调整后,变为31 30 31 30 31 31 30 31 30 31 31 28.或者减去30,最后得到1 0 1 0 1 1 0 1 0 1 1 -2。他们通过在整数空间中进行除法来创建1和0的模式。

    • 重新写入浮点数,这将是(int)(30.6 * Month - 91.4)。 30.6是每月的平均天数,不包括二月(30.63重复)。 91.4几乎是3月份非二月份的平均天数。 (30.6 * 3是91.8)。

    • 所以,我们删除30,只关注0.6天。如果我们将它乘以月数,然后截断为一个整数,我们将得到一个0和1的模式。

      • 0.6 * 0 = 0.0 - > 0

      • 0.6 * 1 = 0.6 - > 0(差异为0)

      • 0.6 * 2 = 1.2 - > 1(差异1)

      • 0.6 * 3 = 1.8 - > 1(差异为0)

      • 0.6 * 4 = 2.4 - > 2(差异1)

      • 0.6 * 5 = 3.0 - > 3(差异1)

      • 0.6 * 6 = 3.6 - > 3(差异为0)

      • 0.6 * 7 = 4.2 - > 4(差异1)

      • 0.6 * 8 = 4.8 - > 4(差异为0)


    • 看到右边的差异模式?这是上面列表中的相同模式,每个月的天数减去30.减去91.8将补偿前三个月的天数,并将其移动到年底,并调整0.4移动1(0.6 * 4和0.6 * 5在上表中)的连续差异与31天的相邻月份相一致。

    • 由于二月份现在处于年底,我们无需处理其长度。这可能是45天(46岁,闰年),唯一必须改变的是365年的一天中的天数不变。

    • 请注意这取决于30和31个月的模式。如果连续两个月连续30天,这是不可能的。


  • 365 *年份:每年天数

  • (年/ 4) - (年/ 100)+(年/ 400):每4年加一个闰日,每100个减一个,每400个加一个。

  • + 1721119 :This是公元前1年3月2日的朱利安日期。由于我们将日历的开始从1月份移动到3月份,因此我们将其用作偏移量,而不是1月1日。由于没有年份零,1 BC得到整数值0.至于为什么3月2日而不是3月1日,我猜这是因为整个月的计算结果仍然有点偏差。如果原作者使用 - 462 而不是 - 457 - 92.4 而不是 - 91.4 在浮点数学中),那么偏移量将是3月1日。


I need to convert from a standard Gregorian date to a Julian day number.

I've seen nothing documented in C# to do this directly, but I have found many posts (while Googling) suggesting the use of ToOADate.

The documentation on ToOADate does not suggest this as a valid conversion method for Julian dates.

Can anyone clarify if this function will perform conversion accurately, or perhaps a more appropriate method to convert DateTime to a Julian formatted string.


This provides me with the expected number when validated against Wikipedia's Julian Day page

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;
}

However, this is without an understanding of the magic numbers being used.

Thanks


References:

解决方案

OADate is similar to Julian Dates, but uses a different starting point (December 30, 1899 vs. January 1, 4713 BC), and a different 'new day' point. Julian Dates consider noon to be the beginning of a new day, OADates use the modern definition, midnight.

The Julian Date of midnight, December 30, 1899 is 2415018.5. This method should give you the proper values:

public static double ToJulianDate(this DateTime date)
{
    return date.ToOADate() + 2415018.5;
}

As for the algorithm:

  • if (Month < 3) ...: To make the magic numbers work our right, they're putting February at the 'end' of the year.
  • (153 * Month - 457) / 5: Wow, that's some serious magic numbers.
    • Normally, the number of days in each month is 31 28 31 30 31 30 31 31 30 31 30 31, but after that adjustment in the if statement, it becomes 31 30 31 30 31 31 30 31 30 31 31 28. Or, subtract 30 and you end up with 1 0 1 0 1 1 0 1 0 1 1 -2. They're creating that pattern of 1s and 0s by doing that division in integer space.
    • Re-written to floating point, it would be (int)(30.6 * Month - 91.4). 30.6 is the average number of days per month, excluding February (30.63 repeating, to be exact). 91.4 is almost the number of days in 3 average non-February months. (30.6 * 3 is 91.8).
    • So, let's remove the 30, and just focus on that 0.6 days. If we multiply it by the number of months, and then truncate to an integer, we'll get a pattern of 0s and 1s.
      • 0.6 * 0 = 0.0 -> 0
      • 0.6 * 1 = 0.6 -> 0 (difference of 0)
      • 0.6 * 2 = 1.2 -> 1 (difference of 1)
      • 0.6 * 3 = 1.8 -> 1 (difference of 0)
      • 0.6 * 4 = 2.4 -> 2 (difference of 1)
      • 0.6 * 5 = 3.0 -> 3 (difference of 1)
      • 0.6 * 6 = 3.6 -> 3 (difference of 0)
      • 0.6 * 7 = 4.2 -> 4 (difference of 1)
      • 0.6 * 8 = 4.8 -> 4 (difference of 0)
    • See that pattern of differences in the right? That's the same pattern in the list above, the number of days in each month minus 30. The subtraction of 91.8 would compensate for the number of days in the first three months, that were moved to the 'end' of the year, and adjusting it by 0.4 moves the successive differences of 1 (0.6 * 4 and 0.6 * 5 in the above table) to align with the adjacent months that are 31 days.
    • Since February is now at the 'end' of the year, we don't need to deal with its length. It could be 45 days long (46 on a leap year), and the only thing that would have to change is the constant for the number of days in a year, 365.
    • Note that this relies on the pattern of 30 and 31 month days. If we had two months in a row that were 30 days, this would not be possible.
  • 365 * Year: Days per year
  • (Year / 4) - (Year / 100) + (Year / 400): Plus one leap day every 4 years, minus one every 100, plus one every 400.
  • + 1721119: This is the Julian Date of March 2nd, 1 BC. Since we moved the 'start' of the calendar from January to March, we use this as our offset, rather than January 1st. Since there is no year zero, 1 BC gets the integer value 0. As for why March 2nd instead of March 1st, I'm guessing that's because that whole month calculation was still a little off at the end. If the original writer had used - 462 instead of - 457 (- 92.4 instead of - 91.4 in floating point math), then the offset would have been to March 1st.

这篇关于在C#中将日期时间转换为Julian日期(ToOADate Safe?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆