Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将DateTime转换为C#中的朱利安日期(ToOADate Safe?)_C#_.net_Datetime_Date_Julian Date - Fatal编程技术网

将DateTime转换为C#中的朱利安日期(ToOADate Safe?)

将DateTime转换为C#中的朱利安日期(ToOADate Safe?),c#,.net,datetime,date,julian-date,C#,.net,Datetime,Date,Julian Date,我需要将标准的格里高利日期转换为朱利安日期 我在C#中没有看到任何可以直接做到这一点的文档,但我发现许多帖子(在谷歌搜索时)建议使用 关于的文档不建议将其作为儒略日期的有效转换方法 有人能澄清一下这个函数是否能准确地执行转换,或者是一个更合适的方法来将DateTime转换为Julian格式的字符串 根据验证时为我提供预期的数字 publicstaticlongconverttojulian(DateTime-Date) { int MOUNT=日期。月份; int Day=日期.Day; in

我需要将标准的格里高利日期转换为朱利安日期

我在C#中没有看到任何可以直接做到这一点的文档,但我发现许多帖子(在谷歌搜索时)建议使用

关于的文档不建议将其作为儒略日期的有效转换方法

有人能澄清一下这个函数是否能准确地执行转换,或者是一个更合适的方法来将DateTime转换为Julian格式的字符串


根据验证时为我提供预期的数字

publicstaticlongconverttojulian(DateTime-Date)
{
int MOUNT=日期。月份;
int Day=日期.Day;
int Year=日期。年份;
如果(月<3)
{
月=月+12;
年份=第1年;
}
长儒略历日=日+(153*月-457)/5+365*年+(年/4)-(年/100)+(年/400)+1721119;
返回朱利安代;
}
然而,这是没有一个魔术数字正在使用的理解

谢谢


参考文献:


OADate与朱利安日期相似,但使用不同的起点(1899年12月30日与公元前4713年1月1日),以及不同的“新的一天”点。朱利安约会认为中午是新的一天的开始,OADATS使用现代定义,午夜。p> 1899年12月30日午夜的儒略日期是2415018.5。此方法应为您提供适当的值:

public static double ToJulianDate(this DateTime date)
{
    return date.ToOADate() + 2415018.5;
}
至于算法:

  • if(Month<3).
    :为了让神奇的数字发挥我们的作用,他们把二月放在一年的“末尾”
  • (153*月-457)/5
    :哇,这真是一些神奇的数字。
    • 通常情况下,每个月的天数为3128313031,但在if报表中进行调整后,则变为31303128。或者,减去30,结果是101011-2。他们通过在整数空间进行除法来创建1和0的模式
    • 重新写入浮点,它将是
      (int)(30.6*月-91.4)
      。30.6是每月的平均天数,不包括2月(准确地说是30.63天)。91.4几乎是3个平均非2月份月份的天数。(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
    :这是公元前1年3月2日的儒略日期。由于我们将日历的“开始日期”从1月移到了3月,因此我们使用它作为偏移量,而不是1月1日。由于没有年份0,因此1BC获得整数值0。至于为什么3月2日而不是3月1日,我猜那是因为整个月的计算在最后还是有点偏离。如果原始编写器使用了
    -462
    而不是
    -457
    -92.4
    而不是浮点数学中的
    -91.4
    ),那么偏移量应该是3月1日
      当方法

      public static double ToJulianDate(this DateTime date) { return date.ToOADate() + 2415018.5; }
      
      适用于现代日期,它有明显的缺点

      朱利安日期是为负日期定义的,即BCE(普通纪元之前)日期,在天文计算中很常见。您无法构造年份小于0的DateTime对象,因此无法使用上述方法计算BCE日期的儒略日期

      1582年的公历改革使公历在10月4日至15日之间有11天的空缺。这些日期在儒略历或公历中都没有定义,但DateTime接受它们作为参数。此外,使用上述方法不会返回任何儒略日期的正确值。使用System.Globalization.JulianCalendar.ToDateTime()或将JulianCalendar纪元传递到DateTime构造函数的实验仍然会对1582年10月5日之前的所有日期产生不正确的结果

      以下例程改编自Jean Meeus的“天文算法”,返回从1月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);
          }
      }
      
      公共类JulianDate
      {
      公共静态bool isJulianDate(整数年、整数月、整数日)
      {
      //1582年之前的所有日期都在儒略历中
      如果(年)<
      
       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);
          }
      }
      
          /*
           * convert magic numbers created by:
           *    (153*month - 457)/5) 
           * into an explicit array of integers
           */
          int[] CumulativeDays = new int[]
          {
              -92   // Month = 0  (Should not be accessed by algorithm)
            , -61   // Month = 1  (Should not be accessed by algorithm)
            , -31   // Month = 2  (Should not be accessed by algorithm)
            ,   0   // Month = 3  (March)
            ,  31   // Month = 4  (April)
            ,  61   // Month = 5  (May)
            ,  92   // Month = 6  (June)
            , 122   // Month = 7  (July)
            , 153   // Month = 8  (August)
            , 184   // Month = 9  (September)
            , 214   // Month = 10 (October)
            , 245   // Month = 11 (November)
            , 275   // Month = 12 (December)
            , 306   // Month = 13 (January, next year)
            , 337   // Month = 14 (February, next year)
          };
      
        int julianDay = day
                        + CumulativeDays[month]
                        + 365*year
                        + (year/4)
      
      (153*month - 457)/5)
      
      public static int IntegerDate(DateTime date)
          {
              int Month = date.Month;
              int Day = date.Day;
              int Year = date.Year;
      
              if (Month < 3)
              {
                  Month = Month + 12;
                  Year = Year - 1;
              }
              //modified Julian Date
              return Day + (153 * Month - 457) / 5 + 365 * Year + (Year / 4) - (Year / 100) + (Year / 400) - 678882;
          }
      
      public static DateTime FromDateInteger(int mjd)
          {
              long a = mjd + 2468570;
              long b = (long)((4 * a) / 146097);
              a = a - ((long)((146097 * b + 3) / 4));
              long c = (long)((4000 * (a + 1) / 1461001));
              a = a - (long)((1461 * c) / 4) + 31;
              long d = (long)((80 * a) / 2447);
              int Day = (int)(a - (long)((2447 * d) / 80));
              a = (long)(d / 11);
              int Month = (int)(d + 2 - 12 * a);
              int Year = (int)(100 * (b - 49) + c + a);
              return new DateTime(Year, Month, Day);
          }
      
      public static DateTime FromJulianDate(double julianDate)
      {
          return DateTime.FromOADate(julianDate - 2415018.5);
      }
      
      typedef struct {
          unsigned int8   seconds;    // 0 to 59
          unsigned int8   minutes;    // 0 to 59
          unsigned int8   hours;      // 0 to 23  (24-hour time)
          unsigned int8   day;        // 1 to 31
          unsigned int8   weekday;    // 0 = Sunday, 1 = Monday, etc.
          unsigned int8   month;      // 1 to 12
          unsigned int8   year;       // (2)000 to (2)255
          unsigned int32  julian;     // Julian date
      } date_time_t;
      
          
      
      void JulianTime(date_time_t * dt)
      {
          unsigned int8   m, y;
      
          y = dt->year;
          m = dt->month;
          if (m > 2) m -= 3;
          else {
              m +=  9;
              y --;
          }
          dt->julian  = ((1461 * y) / 4) + ((153 * m + 2) / 5) + dt->day;
          dt->weekday = ( dt->julian + 2 ) % 7;
          dt->julian  = (dt->julian * 24) + (dt->hours   ); 
          dt->julian  = (dt->julian * 60) + (dt->minutes );     
          dt->julian  = (dt->julian * 60) + (dt->seconds );     
      }
      
      void GregorianTime(date_time_t *dt) 
      {
          unsigned int32  j = dt->julian;
      
          dt->seconds = j % 60;
          j /= 60;
          dt->minutes = j % 60;
          j /= 60;
          dt->hours   = j % 24;
          j /= 24;
          dt->weekday = ( j + 2 ) % 7; // Get day of week
          dt->year = (4 * j) / 1461;
          j = j - ((1461 * dt->year) / 4);
          dt->month = (5 * j - 3) / 153;
          dt->day  = j - (((dt->month * 153) + 3) / 5);
          if ( dt->month < 10 )
          {
              dt->month += 3;
          }
          else
          {
              dt->month -= 9;
              dt->year ++;
          }
      }