简体   繁体   English

如何在Java Calendar API中使用Julian Day Numbers?

[英]How do I use Julian Day Numbers with the Java Calendar API?

Julian Day Numbers are a means of representing timestamps as a continuous count of days (and fractional days) since noon UTC, January 1, 4713 BC The Java 7 SE API does not contain support for this format. Julian Day Numbers是一种将时间戳表示为自公元前4713年1月1日中午UTC以来连续天数(和小数天数)的方法.Java 7 SE API不包含对此格式的支持。 Developers who have used the SQLite database may have used the native Julian Day support provided by the strftime() functions. 使用过SQLite数据库的开发人员可能使用了strftime()函数提供的本机Julian Day支持。

The advantages of representing timestamps as Julian Day Numbers include: 将时间戳表示为Julian Day Numbers的优点包括:

  • A date and time can be represented to millisecond precision in a primitive data type (double) 日期和时间可以表示为基本数据类型的毫秒精度(双精度)
  • Days in a year are somewhat more concrete than seconds in a day 一年中的日子比一天中的几天更具体
  • Circumvents the problem of "leap seconds" if this degree of precision is unimportant 如果这种精确度不重要,可以解决“闰秒”的问题
  • Days between dates arithmetic is trivial; 日期算术之间的天数是微不足道的; sorting precedence is easily determined 排序优先级很容易确定
  • Very lightweight 很轻巧

Disadvantages 缺点

  • The Java Date/Time API does not have built-in support for JDN's Java Date / Time API没有对JDN的内置支持
  • Unsuitable for very precise time measurements 不适合进行非常精确的时间测量
  • Only defined for UTC and must be mapped from UTC to local time 仅为UTC定义,必须从UTC映射到本地时间
  • Unsuitable for display to end-users; 不适合向最终用户展示; must be converted/formatted before display 必须在显示之前转换/格式化

Julian Day Numbers are commonly used in astronomical calculations and their definition is highly standardized and accepted. 朱利安日数通常用于天文计算,其定义高度标准化并被接受。 Similarly, Modified Julian Day Numbers (which count from midnight UTC, 17 November 1858) are standardly defined and used in aerospace applications (see http://tycho.usno.navy.mil/mjd.html ). 同样,修改后的朱利安日数(从1858年11月17日午夜开始计算)是标准定义并用于航空航天应用(见http://tycho.usno.navy.mil/mjd.html )。

For applications that make extensive use of date/time arithmetic or chronological sorting (or if persisting lightweight primitives is more appealing than persisting timestamps), internally representing dates and times as JDN's or MJD's may make sense for you. 对于广泛使用日期/时间算法或按时间顺序排序的应用程序(或者如果持久化轻量级基元比持久化时间戳更具吸引力),在内部将日期和时间表示为JDN或MJD可能对您有意义。

The following code defines functions that facilitate using either Julian Day Numbers or Modified Julian Day Numbers with the Java Date/Time/Calendar API. 以下代码定义了有助于将Julian Day Numbers或Modified Julian Day Numbers与Java Date / Time / Calendar API一起使用的函数。 The code is based on algorithms published in Jean Meeus's "Astronomical Algorithms", 1st ed., 1991. 该代码基于Jean Meeus的“Astronomical Algorithms”,第1版,1991年发表的算法。

public class JulianDay {

    private static final int YEAR = 0;
    private static final int MONTH = 1;
    private static final int DAY = 2;
    private static final int HOURS = 3;
    private static final int MINUTES = 4;
    private static final int SECONDS = 5;
    private static final int MILLIS = 6;

    :
    :

    // Converts a timestamp presented as an array of integers in the following
    // order (from index 0 to 6): year,month,day,hours,minutes,seconds,millis
    // month (1-12), day (1-28 or 29), hours (0-23), min/sec (0-59) to a
    // Modified Julian Day Number.
    // For clarity and simplicity, the input values are assumed to be well-formed;
    // error checking is not implemented in the snippet.

    public static double toMJD(int[] ymd_hms) {

        int y = ymd_hms[YEAR];
        int m = ymd_hms[MONTH];
        double d = (double) ymd_hms[DAY];

        d = d + ((ymd_hms[HOURS] / 24.0) +
                 (ymd_hms[MINUTES] / 1440.0) +
                 (ymd_hms[SECONDS] / 86400.0) +
                 (ymd_hms[MILLIS] / 86400000.0));

        if (m == 1 || m == 2) {
            y--;
            m = m + 12;
        }

        double a = Math.floor(y / 100);
        double b = 2 - a + Math.floor(a / 4);

        return (Math.floor(365.25 * (y + 4716.0)) +
               Math.floor(30.6001 * (m + 1)) +
               d + b - 1524.5) - 2400000.5;  // for Julian Day omit the 2400000.5 term
    }

    // Converts an Modified Julian Day Number (double) to an integer array representing
    // a timestamp (year,month,day,hours,mins,secs,millis). Works for all positive JDN

    public static int[] toTimestamp(double mjd) {

        int ymd_hms[] = { -1, -1, -1, -1, -1, -1, -1 };
        int a, b, c, d, e, z;

        double jd = mjd + 2400000.5 + 0.5;  // if a JDN is passed as argument,
                                            // omit the 2400000.5 term
        double f, x;

        z = (int) Math.floor(jd);
        f = jd - z;

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

        b = a + 1524;
        c = (int) Math.floor((b - 122.1) / 365.25);
        d = (int) Math.floor(365.25 * c);
        e = (int) Math.floor((b - d) / 30.6001);

        ymd_hms[DAY] = b - d - (int) Math.floor(30.6001 * e);
        ymd_hms[MONTH] = (e < 14)
                ? (e - 1)
                : (e - 13);
        ymd_hms[YEAR] = (ymd_hms[MONTH] > 2)
                ? (c - 4716)
                : (c - 4715);

        for (int i = HOURS; i <= MILLIS; i++) {
            switch(i) {
                case HOURS:
                    f = f * 24.0;
                    break;
                case MINUTES: case SECONDS:
                    f = f * 60.0;
                    break;
                case MILLIS:
                    f = f * 1000.0;
                    break;  
            }
            x = Math.floor(f);
            ymd_hms[i] = (int) x;
            f = f - x;
        }   

        return ymd_hms;
    }
}

This answer has been provided here as well: How can I convert between a Java Date and Julian day number? 这里也提供了这个答案: 如何在Java Date和Julian day number之间进行转换? . In the current post, references for the algorithm are provided along with some more discussion. 在当前的帖子中,提供了该算法的参考文献以及一些更多的讨论。 The implementation of algorithms above also contains no Java API dependencies (aside from Math functions). 上述算法的实现也不包含Java API依赖(除了Math函数)。

I know that this is not a Java Calendar API, but maybe you should try Jodd tool. 我知道这不是Java Calendar API,但也许您应该尝试使用Jodd工具。

JulianDateStamp julianStamp = new JulianDateStamp(julianDays);
JDateTime jdate = new JDateTime(julianStamp);
Date date = new Date(jdate.getTimeInMillis());

This works perfect for: 这适用于:

  • 2113488,2746855323 -> 1074.06.01 18:35 2113488,2746855323 - > 1074.06.01 18:35
  • 2453479,5866961805 -> 2005.04.19 02:04 2453479,5866961805 - > 2005.04.19 02:04

Read more . 阅读更多

java.time java.time

The java.time framework built into Java 8 and later supplants the old date-time classes bundled with the earliest versions of Java. Java 8及更高版本中内置的java.time框架取代了与最早版本的Java捆绑在一起的旧日期时间类。 See Oracle Tutorial . 请参阅Oracle教程 Much of the functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP . 许多功能已被后移植到Java 6和7在ThreeTen-反向移植并且还适于在到Android ThreeTenABP

The java.time classes include the java.time.temporal.JulianFields . java.time类包括java.time.temporal.JulianFields This class provides three implementations of TemporalField to give limited support for Julian date-only values (no time-of-day). 此类提供了TemporalField三个实现,以便为Julian仅日期值(无时间)提供有限支持。 So you can get whole number of days, not the double requested in the Question. 所以你可以得到整天,而不是问题中要求的double Read that class doc closely to be sure it behaves to your expectations. 仔细阅读该课程文档,以确保它符合您的期望。 Note that unlike most other java.time classes, these Julian classes ignore any offset-from-UTC or time zone information (always treated as a local date). 请注意,与大多数其他java.time类不同,这些Julian类会忽略任何来自UTC或时区的偏移信息(始终视为本地日期)。

  • JULIAN_DAY → Count of whole days since day 0, which is January 1, 4713 BCE in the Julian calendar ( -4713-11-24 Gregorian ). JULIAN_DAY因为0天整天→计数,这是1月1日,4713 BCE儒略历(-4713-11-24 公历 )。
  • MODIFIED_JULIAN_DAY → Like JULIAN_DAY but subtracting 2_400_000.5 (basically dropping the first two digits of Julian date number). MODIFIED_JULIAN_DAY →与JULIAN_DAY相似但减去2_400_000.5 (基本上删除了Julian日期编号的前两位数字)。 Note that results here are one fewer (-1) than Julian date number of item above. 请注意,此处的结果比上面项目的Julian日期数少一(-1)
  • RATA_DIE → Similar to the two items above in that it is a count of days from an epoch. RATA_DIE →与上述两个项目类似,它是一个时代的天数。 But here the epoch is the ISO 8601 date of 0001-01-01 . 但这里的时代是ISO 86010001-01-01日期。

In this example we start with the ISO 8601 date of 1970-01-01 . 在本例中,我们从1970-01-01的ISO 8601日期开始。

LocalDate localDate = LocalDate.of ( 1970 , 1 , 1 );
long julianDate = JulianFields.JULIAN_DAY.getFrom ( localDate );
long modifiedJulianDate = JulianFields.MODIFIED_JULIAN_DAY.getFrom ( localDate );
long rataDie = JulianFields.RATA_DIE.getFrom ( localDate );

localDate: 1970-01-01 | localDate:1970-01-01 | julianDate: 2440588 | 朱利安日期:2440588 | modifiedJulianDate: 40587 | modifiedJulianDate:40587 | rataDie: 719163 rataDie:719163

ThreeTen-Extra ThreeTen-EXTRA

The ThreeTen-Extra project is the experimental proving grounds for possible future additions to java.time. ThreeTen-Extra项目是未来可能添加到java.time的实验性验证基础。 The name comes from the JSR 310 that defines java.time. 该名称来自定义java.time的JSR 310

This library includes additional support for Julian dates in its Julian calendar system ( Chronology ). 该库在其Julian日历系统年表 )中包含对朱利安日期的额外支持。 Like the support in Java 8, this library is limited to date-only values (no partial days or time-of-day). 与Java 8中的支持一样,此库仅限于仅限日期的值(不包括部分日期或时间)。

With this library you can instantiate JulianDate objects. 使用此库,您可以实例化JulianDate对象。

Many methods and features for you to examine there. 有许多方法和功能供您查看。

If you are willing to move outside the core JDK classes, then Joda can be a solution. 如果您愿意转移到核心JDK类之外,那么Joda可以成为一个解决方案。 Joda supports the Julian calendar system. Joda支持Julian日历系统。 From their doc page: 从他们的文档页面:

Chronology julianChrono = JulianChronology.getInstance();
DateTime dt = new DateTime(1066, 10, 14, 0, 0, 0, julianChrono);

That would be the Battle of Hastings 1066 in the Julian Calendar system. 那将是朱利安历法系统中的黑斯廷斯战役1066。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM