【问题标题】:Julian day of the year in JavaJava 中的儒略日
【发布时间】:2011-03-01 15:20:51
【问题描述】:

我在http://www.rgagnon.com/javadetails/java-0506.html 看到了“解决方案”,但它不能正常工作。例如。昨天(6 月 8 日)应该是 159,但它说是 245。

那么,是否有人在 Java 中提供了获取当前日期的三位数儒略日(不是儒略日 - 我需要今年的这一天)的解决方案?

谢谢!标记

【问题讨论】:

  • 嘿,马克,我也想知道这一点,因为我想在我正在研究的天文学程序中使用它,而且我更喜欢直接在 java 中这样做,而不是自己编码 :)
  • 这一年中的这一天 (1-366) 更准确地称为Ordinal Date。 “朱利安”在这里的使用很常见,但据我所知,这是不正确的。显然与Julian Day 合并,它是从世界时间中午开始的儒略日计数中分配给整个太阳日的整数,儒略日编号 0 分配给从公元前 4713 年 1 月 1 日中午开始的日子,预言儒略日历(公元前 4714 年 11 月 24 日,在公历中)。例如:2000-01-01T12:00:00Z = 2,451,545。

标签: java julian-date


【解决方案1】:
import java.util.Calendar;
// ...
final int julianDay = Calendar.getInstance().get(Calendar.DAY_OF_YEAR);

请注意,这并没有考虑到您引用的那个奇怪网站声称的“中午开始”交易。当然,这可以通过检查时间来解决。

【讨论】:

  • 在我的系统上 System.out.println(Calendar.getInstance().getClass()); 打印 class java.util.GregorianCalendar 但也许这与 julian 相同。
  • “儒略日”或“儒略日”对我来说一直意味着一年中的某一天。我认为除了严肃的古典学者之外,每个人都是如此。如果有人正在寻找前公历计算的日期,我的解决方案将不起作用。请注意,问题中包含“我需要今年这一天”这句话。
  • 在计算之前做setGregorianChange( new Date( Long.MAX_VALUE) )。然后是Julian 一天。
  • 我认为你们都误解了“朱利安日”在这种情况下的含义。它不是关于历史日历的。现代数据处理应用程序中的术语“儒略日”或“儒略日”仅表示“一年中的某一天”。不信的话谷歌一下。
  • 另请注意,原始问题说 2010 年 6 月 8 日应该是“159”,如果“朱利安日”的意思是“一年中的某一天”,这是正确的。
【解决方案2】:

如果您只想要一年中的某一天,为什么不使用 GregorianCalendars DAY_OF_YEAR 字段?

import java.util.GregorianCalendar;
public class CalTest {
    public static void main(String[] argv) {
        GregorianCalendar gc = new GregorianCalendar();
        gc.set(GregorianCalendar.DAY_OF_MONTH, 8);
        gc.set(GregorianCalendar.MONTH, GregorianCalendar.JUNE);
        gc.set(GregorianCalendar.YEAR, 2010);
        System.out.println(gc.get(GregorianCalendar.DAY_OF_YEAR));
}

}

或者,您可以计算今天的儒略日期与今年 1 月 1 日之间的差异。但请务必将结果加 1,因为 1 月 1 日不是一年中的第 0 天:

int[] now = {2010, 6, 8};
int[] janFirst = {2010, 1, 1};
double dayOfYear = toJulian(now) - toJulian(janFirst) + 1
System.out.println(Double.valueOf(dayOfYear).intValue());

【讨论】:

  • 非常感谢!这非常有效 - 我知道必须有一个简单的答案。
  • 仅供参考,存在严重缺陷的日期时间类,例如 java.util.Datejava.util.Calendarjava.text.SimpleDateFormat,现在是 legacy,被 Java 8 及更高版本中内置的 java.time 类所取代.
【解决方案3】:

如果我们得到一个双朱利安日期,例如和弦决策经理

http://java.ittoolbox.com/groups/technical-functional/java-l/java-function-to-convert-julian-date-to-calendar-date-1947446

以下工作正常,但第二个未处理 How can I convert between a Java Date and Julian day number?

公共静态字符串 julianDate(String julianDateStr) {

    try{
        // Calcul date calendrier Gr?gorien ? partir du jour Julien ?ph?m?ride 
        // Tous les calculs sont issus du livre de Jean MEEUS "Calcul astronomique" 
        // Chapitre 3 de la soci?t? astronomique de France 3 rue Beethoven 75016 Paris 
        // Tel 01 42 24 13 74 
        // Valable pour les ann?es n?gatives et positives mais pas pour les jours Juliens n?gatifs
        double jd=Double.parseDouble(julianDateStr);
          double z, f, a, b, c, d, e, m, aux;
            Date date = new Date();
            jd += 0.5;
            z = Math.floor(jd);
            f = jd - z;

            if (z >= 2299161.0) {
              a = Math.floor((z - 1867216.25) / 36524.25);
              a = z + 1 + a - Math.floor(a / 4);
            } else {
              a = z;
            }

            b = a + 1524;
            c = Math.floor((b - 122.1) / 365.25);
            d = Math.floor(365.25 * c);
            e = Math.floor((b - d) / 30.6001);
            aux = b - d - Math.floor(30.6001 * e) + f;
            Calendar calendar = new GregorianCalendar();
            calendar.setTime(date);
            calendar.set(Calendar.DAY_OF_MONTH, (int) aux);

            double hhd= aux-calendar.get(Calendar.DAY_OF_MONTH);                
            aux = ((aux - calendar.get(Calendar.DAY_OF_MONTH)) * 24);




            calendar.set(Calendar.HOUR_OF_DAY, (int) aux);

            calendar.set(Calendar.MINUTE, (int) ((aux - calendar.get(Calendar.HOUR_OF_DAY)) * 60));



         // Calcul secondes 
            double mnd = (24 * hhd) - calendar.get(Calendar.HOUR_OF_DAY);
            double ssd = (60 * mnd) - calendar.get(Calendar.MINUTE); 
            int ss = (int)(60 * ssd);
            calendar.set(Calendar.SECOND,ss);



            if (e < 13.5) {
              m = e - 1;
            } else {
              m = e - 13;
            }
            // Se le resta uno al mes por el manejo de JAVA, donde los meses empiezan en 0.
            calendar.set(Calendar.MONTH, (int) m - 1);
            if (m > 2.5) {
              calendar.set(Calendar.YEAR, (int) (c - 4716));
            } else {
              calendar.set(Calendar.YEAR, (int) (c - 4715));
            }


        SimpleDateFormat sdf=new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        //System.out.println("Appnumber= "+appNumber+" TimeStamp="+timeStamp+" Julian Date="+julianDateStr+" Converted Date="+sdf.format(calendar.getTime()));
        return sdf.format(calendar.getTime());

}catch(Exception e){
    e.printStackTrace();
}
return null;

}  

【讨论】:

    【解决方案4】:
    DateFormat d = new SimpleDateFormat("D");
    System.out.println(d.format(date));
    

    【讨论】:

      【解决方案5】:

      我已阅读所有帖子,但我认为有些地方不太清楚。

      user912567 提到了 Jean Meeus,他完全正确

      Jean Meeus 在其“天文算法”一书中给出了我找到的最准确的定义(必须拥有,真的……)。

      Julian Date 是一个日期,照常表示,有年、月和日。

      Julian Day 是一个 数字(实数),从 -4712 年开始计算,并且是“...天数的连续计数...”(以及天数的小数)。 用于精确天文计算的有用时间尺度。

      Jean Meeus :“儒略日与儒略历无关”(“天文算法”,第 2 版,第 59 页)

      【讨论】:

      • 正是如此。值得注意的是,与这里的许多答案和 cmets 不同,儒略日在现代计算中仍然很有用,因为您可以在几天内用它计算日期差异,而无需付出任何努力。
      【解决方案6】:

      tl;博士

      LocalDate.now().getDayOfYear()
      

      ……或者……

      org.threeten.extra.DayOfYear.now() 
      

      “儒略日”术语

      “朱利安日”一词有时用于表示一年中的 ordinalOrdinal date,表示从 1 到 365 或 366 的数字 (leap years)。 1 月 1 日为 1,1 月 2 日为 2,12 月 31 日为 365(或闰年为 366)。

      这种对Julian 的松散(不正确)使用可能来自use in astronomy 和其他跟踪日期字段,作为自公元前4713 年1 月1 日世界标准时间中午以来的连续天数(在Julian calendar 上)。如今,朱利安日期已接近 250 万,2,457,576 今天。

      java.time

      Java 8 及更高版本中内置的 java.time 框架提供了一种简单的工具来获取日期。

      LocalDate 类表示没有时间和时区的仅日期值。您可以查询一年中的某一天。

      LocalDate localDate = LocalDate.of ( 2010 , Month.JUNE , 8 );
      int dayOfYear = localDate.getDayOfYear ();
      

      转储到控制台。结果显示,2010 年 6 月 8 日确实是第 159 天。

      System.out.println ( "localDate: " + localDate + " | dayOfYear: " + dayOfYear );
      

      本地日期:2010-06-08 | dayOfYear: 159

      时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因区域而异。例如,法国巴黎午夜过后的几分钟是新的一天,而魁北克蒙特利尔仍然是“昨天”。

      ZoneId z = ZoneId.of( “America/Montreal” );
      LocalDate today = LocalDate.now( z );
      int dayOfYear = today.getDayOfYear ();
      

      换个方向,从数字到日期。

      LocalDate ld = Year.of( 2017 ).atDay( 159 ) ;
      

      org.threeten.extra.DayOfYear

      ThreeTen-Extra 库为 Java 内置的 java.time 类添加了功能。

      这个库提供了一个类来明确表示任何一年的序数日:DayOfYear。使用此类而不是单纯的整数可以使您的代码更具自记录性,提供类型安全性并确保有效值。

      DayOfYear dayOfYear = DayOfYear.from( LocalDate.of ( 2010 , Month.JUNE , 8 ) ) ;
      

      获取具有特定年份的DayOfYear 的日期。

      LocalDate localDate = dayOfYear.atYear( 2023 ) ;
      

      关于java.time

      java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

      要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

      Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

      您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。 Hibernate 5 & JPA 2.2 支持 java.time

      从哪里获取 java.time 类?

      ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

      【讨论】:

        【解决方案7】:

        您也可以通过这种方式获取“朱利安日期”或“序数日期”:

        import java.util.Calendar;
        import java.util.Date;
        
        public class MyClass {
        
          public static void main(String[] args) {
            Calendar cal = Calendar.getInstance();
            LocalDate myObj = LocalDate.now();
            System.out.println(myObj);
            System.out.println("Julian Date:" + cal.get(Calendar.DAY_OF_YEAR));
        
          }
        }
        

        【讨论】:

        • 虽然我们感谢您的回答,但如果它在其他答案之上提供额外的价值会更好。在这种情况下,您的答案不会提供额外的价值,因为接受的答案包含该解决方案。如果之前的答案对您有帮助,您应该投票而不是重复相同的信息。
        【解决方案8】:

        根据@Basil Bourque 的回答,下面是我使用系统默认区域 ID 获取一年中儒略日的实现。

        LocalDate localDate = LocalDate.now(ZoneId.systemDefault());
        int julianDay = localDate.getDayOfYear();
        

        【讨论】:

          【解决方案9】:

          如果您正在寻找 day count since 4713 BC 中的 Julian Day,那么您可以改用以下代码:

          private static int daysSince1900(Date date) {
              Calendar c = new GregorianCalendar();
              c.setTime(date);
          
              int year = c.get(Calendar.YEAR);
              if (year < 1900 || year > 2099) {
                  throw new IllegalArgumentException("daysSince1900 - Date must be between 1900 and 2099");
              }
              year -= 1900;
              int month = c.get(Calendar.MONTH) + 1;
              int days = c.get(Calendar.DAY_OF_MONTH);
          
              if (month < 3) {
                  month += 12;
                  year--;
              }
              int yearDays = (int) (year * 365.25);
              int monthDays = (int) ((month + 1) * 30.61);
          
              return (yearDays + monthDays + days - 63);
          }
          
          /**
           * Get day count since Monday, January 1, 4713 BC
           * https://en.wikipedia.org/wiki/Julian_day
           * @param date
           * @param time_of_day percentage past midnight, i.e. noon is 0.5
           * @param timezone in hours, i.e. IST (+05:30) is 5.5
           * @return
           */
          private static double julianDay(Date date, double time_of_day, double timezone) {
              return daysSince1900(date) + 2415018.5 + time_of_day - timezone / 24;
          }
          

          以上代码基于https://stackoverflow.com/a/9593736,因此仅限于 1900 年到 2099 年之间的日期。

          【讨论】:

          • for monthDays ´(month + 1) * 153/5´ 仅适用于整数。遗憾的是,经过 2 年的 Java 运行时设计,您必须回到 Java 之前使用的基础知识。
          猜你喜欢
          • 1970-01-01
          • 2013-02-05
          • 2014-09-06
          • 1970-01-01
          • 1970-01-01
          • 2020-01-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多