如何使用儒略日数与Java日历API?(How do I use Julian Day Number

2019-07-20 06:35发布

儒略日的数字是代表时间戳作为天的连续数(和分数天),因为中午UTC,1月1日,4713 BC的Java 7的SE API不包含这种格式支持的一种手段。 谁使用SQLite数据库开发者可能已经使用的的strftime()函数提供的本地儒略日的支持。

表示时间戳作为儒略日数的优点包括:

  • 日期和时间可以被表示在一个基本数据类型到毫秒精度(双)
  • 在一年的日子一定程度上比在一天秒更具体
  • 规避的“闰秒”的问题,如果这个精确度是不重要
  • 日期算术之间的天是微不足道的; 排序优先级容易地确定
  • 非常轻巧

缺点

  • Java的日期/时间API不具有内置支持JDN的
  • 不适合非常精确的时间测量
  • 只为UTC规定,必须从UTC到当地时间映射
  • 不适合用于显示给最终用户; 必须转换/显示之前格式化

儒略日数在天文计算常用和他们的定义是高度标准化和接受。 类似地,修改的儒略日数(其从午夜UTC计数,1858年11月17日)作为标准定义,并且在航空航天应用(见用于http://tycho.usno.navy.mil/mjd.html )。

对于广泛使用的日期/时间算术或时间排序的应用程序(或者,如果持续轻量级元比持续时间戳更吸引人),在内部表示日期和时间为JDN公司或MJD的可以让你的感觉。

下面的代码定义使用任一儒略日数或修饰的儒略日数与Java日期/时间/日历API促进功能。 该代码是基于公布的琼·米斯的“天文算法”,第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;
    }
}

这个答案已经在这里提供的还有: 我怎样才能在Java日期和Julian天数之间的转换? 。 在目前的职位,与一些更多的讨论以及提供该算法引用。 上述算法的实现也包含没有Java API依赖(除了数学函数)。

Answer 1:

我知道这是不是一个Java日历API,但也许你应该尝试Jodd工具。

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

这工作完美:

  • 2113488,2746855323 - > 1074年6月1日18时35分
  • 2453479,5866961805 - > 2005年4月19日2点04分

阅读更多 。



Answer 2:

java.time

内置到Java 8和更高版本java.time框架取代了与Java的早期版本中捆绑的旧日期时间类。 见甲骨文教程 。 许多功能已被后移植到Java 6和7在ThreeTen-反向移植并且还适于在到Android ThreeTenABP 。

该java.time类包括java.time.temporal.JulianFields 。 这个类提供了三种实现TemporalField给朱利安日期值只提供有限的支持(没有时间的日)。 所以,你可以得到天的整数,而不是double的问题提出要求。 阅读类文档密切合作,以确保它的行为对你的期望。 请注意,与其他大多数java.time类,这些类朱利安忽略任何偏移从-UTC或时区信息(始终视为本地日期)。

  • JULIAN_DAY因为0天整天→计数,这是1月1日,4713 BCE儒略历(-4713-11-24 公历 )。
  • MODIFIED_JULIAN_DAY →JULIAN_DAY一样,但减去2_400_000.5 (基本上是下降的儒略日数的前两位)。 请注意,结果这里有一个比上述项目的儒略日数较少(-1)。
  • RATA_DIE →到两个项目上面,这是从一个时代的天数相似。 但这里的时代是ISO 8601的日期0001-01-01

在这个例子中,我们开始的ISO 8601日期1970-01-01

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 | julianDate:2440588 | modifiedJulianDate:40587 | rataDie:719163

ThreeTen-EXTRA

该ThreeTen-EXTRA项目是为将来可能增加的java.time实验试验场。 这个名字来自于JSR 310定义java.time。

这个库包括在它的朱利安日期额外的支持儒略历系统 ( 年表 )。 象Java 8支持,这个库仅限于日期仅值(无分天或时间的天)。

有了这个库可以实例JulianDate对象。

许多方法和功能,为您检查那里。



Answer 3:

如果你愿意的核心JDK类外移动,然后乔达可以是一个解决办法。 乔达支持儒略历系统。 从他们的文档页面:

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

这将是黑斯廷斯1066的儒略历系统战役。



文章来源: How do I use Julian Day Numbers with the Java Calendar API?