sco*_*ttb 7 java timestamp calendar date julian-date
Julian Day Numbers是一种将时间戳表示为自公元前4713年1月1日中午UTC以来连续天数(和小数天数)的方法.Java 7 SE API不包含对此格式的支持.使用过SQLite数据库的开发人员可能使用了strftime()函数提供的本机Julian Day支持.
将时间戳表示为Julian Day Numbers的优点包括:
缺点
朱利安日数通常用于天文计算,其定义高度标准化并被接受.同样,修改后的朱利安日数(从1858年11月17日午夜开始计算)是标准定义并用于航空航天应用(见http://tycho.usno.navy.mil/mjd.html).
对于广泛使用日期/时间算法或按时间顺序排序的应用程序(或者如果持久化轻量级基元比持久化时间戳更具吸引力),在内部将日期和时间表示为JDN或MJD可能对您有意义.
以下代码定义了有助于将Julian Day Numbers或Modified Julian Day Numbers与Java Date/Time/Calendar API一起使用的函数.该代码基于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;
}
}
Run Code Online (Sandbox Code Playgroud)
这里也提供了这个答案:如何在Java Date和Julian day number之间进行转换?.在当前的帖子中,提供了该算法的参考文献以及一些更多的讨论.上述算法的实现也不包含Java API依赖(除了Math函数).
Java 8 中内置的 java.time 框架后来取代了与最早版本的 Java 捆绑在一起的旧日期时间类。请参阅Oracle 教程。许多功能已在ThreeTen-Backport中向后移植到 Java 6 和 7,并在ThreeTenABP中进一步适应 Android 。
\n\njava.time 类包括java.time.temporal.JulianFields. 此类提供了三种实现,TemporalField为仅朱利安日期值(无时间)提供有限支持。因此,您可以获得整数天数,而不是double问题中要求的天数。仔细阅读该类文档以确保它符合您的期望。请注意,与大多数其他 java.time 类不同,这些 Julian 类忽略任何距 UTC 的偏移量或时区信息(始终被视为本地日期)。
2_400_000.5(基本上删除儒略日期数字的前两位数字)。请注意,此处的结果比上面项目的儒略日期编号少一位 (-1)。0001-01-01。在此示例中,我们从 ISO 8601 日期 开始1970-01-01。
LocalDate localDate = LocalDate.of ( 1970 , 1 , 1 );\nlong julianDate = JulianFields.JULIAN_DAY.getFrom ( localDate );\nlong modifiedJulianDate = JulianFields.MODIFIED_JULIAN_DAY.getFrom ( localDate );\nlong rataDie = JulianFields.RATA_DIE.getFrom ( localDate );\nRun Code Online (Sandbox Code Playgroud)\n\n\n\n\n本地日期: 1970-01-01 | 朱利安日期: 2440588 | 修改朱利安日期:40587 | 拉塔模具:719163
\n
ThreeTen -Extra项目是 java.time 未来可能添加的实验性试验场。该名称来自定义 java.time 的JSR 310 。
\n\n该库在其儒略历系统(Chronology )中包含对儒略日期的额外支持。与 Java 8 中的支持一样,该库仅限于仅日期值(没有部分日期或时间)。
\n\n使用这个库你可以实例化JulianDate对象。
许多方法和功能供您研究。
\n如果您愿意移出核心 JDK 类,那么Joda可以是一个解决方案。Joda 支持儒略历系统。从他们的文档页面:
Chronology julianChrono = JulianChronology.getInstance();
DateTime dt = new DateTime(1066, 10, 14, 0, 0, 0, julianChrono);
Run Code Online (Sandbox Code Playgroud)
这就是儒略历系统中第 1066 年的黑斯廷斯战役。