这是joda time中的错误吗?处理非常古老(0000 年)的即时/负纪元
Posted
技术标签:
【中文标题】这是joda time中的错误吗?处理非常古老(0000 年)的即时/负纪元【英文标题】:Is this a bug in joda time? Handling very old (year 0000) instant / negative epoch 【发布时间】:2021-12-02 02:26:07 【问题描述】:当我们从带有年份0001
的java.util.Date
构造它时,似乎DateTime
没有用正确的日期初始化它自己。
import java.time.LocalDateTime;
import java.util.TimeZone;
public class TestMain
public static void main(String[] args)
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
java.util.Date d = new java.util.Date(-62135640000000L);
java.time.Instant i = java.time.Instant.ofEpochMilli(-62135640000000L);
System.out.println("d = new java.util.Date(-62135640000000L) : " + new java.util.Date(-62135640000000L));
System.out.println("new org.joda.time.DateTime(d) : " + new org.joda.time.DateTime(d));
System.out.println("new org.joda.time.DateTime(-62135640000000L) : " + new org.joda.time.DateTime(-62135640000000L));
System.out.println("java.time.LocalDateTime.ofInstant(i, java.time.ZoneOffset.UTC): " + LocalDateTime.ofInstant(i, java.time.ZoneOffset.UTC));
输出:
d = new java.util.Date(-62135640000000L) : Sun Jan 02 12:00:00 UTC 1
new org.joda.time.DateTime(d) : 0000-12-31T12:00:00.000Z
new org.joda.time.DateTime(-62135640000000L) : 0000-12-31T12:00:00.000Z
java.time.LocalDateTime.ofInstant(i, java.time.ZoneOffset.UTC): 0000-12-31T12:00
除了时区相关的差异,如果你注意:
日期是02
in Date
object 和 31
in DateTime
(或00
,如果您更改为UTC
)
年份是0001
in Date
object 和 0000
in DateTime
是我做错了什么,还是这是一个错误?
做了更多的计算
62135640000000 / 1000 / 3600 / 24 / 365.25 = 1968.9596167008898015058179329227
0.9596167008898015058179329227 * 365.25 = 350.5
365.25 - 350.5 = 14.75
所以-62135640000000
= 负 1969 年零 350.5 天。或 0000 年开始后约 14.75 天。
【问题讨论】:
一年不是 365.0000 天。 @VGR,你是对的。更新。还添加了java.time
行为。
【参考方案1】:
不是错误:儒略历与预测公历
这不是错误。它是有意识地设计的。这里有两种不同的日历系统:
-
过时的
java.util.Date
类使用儒略历来表示 1582 年之前的日期。它试图反映当时欧洲大部分地区实际使用的日历系统。
默认情况下,Joda-Time 和 java.time 都使用 ISO 8601 日历系统(如果您明确指定其他日历系统,则支持它们)。 ISO 8601 反过来使用预测公历。 Proleptic Gregorian calendar 是通过将 Gregorian calendar 的规则外推到 Gregorian calendar 发明和引入之前的时代而创建的。因此,它给出的日期与当时实际使用的日期不一致,但反过来,定义更明确。
这两个日历在大多数日期中相隔几天,当我们接近 1582 年或更晚的朱利安-格里高利交叉时,最长可能会相隔几周,具体取决于司法管辖区。
Joda-Time 支持公历/儒略历
Joda-TIme 也通过 GJChronology
类支持 Date
使用的联合公历/朱安历系统。
DateTime dt = new DateTime(-62_135_640_000_000L,
GJChronology.getInstanceUTC());
System.out.println("DateTime with GJChronology: " + dt);
输出:
GJChronology 的日期时间:0001-01-02T12:00:00.000Z
年、月、日都与您从Date
得到的一致。
链接
ISO8601 Java calendar system 在 Joda-Time 网站上。 Wikipedia article: ISO 8601 ***上的Proleptic Gregorian calendar 类似问题:Java: How to get the timestamp of '1000-01-01 00:00:00' in UTC? 不同之处在于该问题是关于来自 java.time 的ZonedDateTime
,而不是关于 Joda-Time。
【讨论】:
以上是关于这是joda time中的错误吗?处理非常古老(0000 年)的即时/负纪元的主要内容,如果未能解决你的问题,请参考以下文章
JAVA秒会技术之Joda-Time满足你所有关于日期的处理
joda-time的使用,创建时间处理工具类DateTimeUtil
HSQLDB + EclipseLink + 生成 DDL + DATE JODA TIME = 错误的 TIMESTAMP