从XMLGregorianCalendar转换为Calendar时的日期更改

从XMLGregorianCalendar转换为Calendar时的日期更改,第1张

从XMLGregorianCalendar转换为Calendar时的日期更改

摘自

XMLGregorianCalendar.toGregorianCalendar()
JavaDoc的他们是如何创建的
GregorianCalendar
实例:

通过调用GregorianCalendar.setGregorianChange(new Date(Long.MIN_VALUE))获得纯阳历。

这意味着,创建的日历将是多用的,并且不会像默认情况下那样切换到朱利安日历(对于旧日期)。然后问题就在这里:

  • argCal.toGregorianCalendar()
    - 使用字段表示形式*XMLGregorianCalendar 转换为 GregorianCalendar (不使用Julian系统-参见上文) *
  • cal.setTime(calendarDate.getTime());
    • 这实际上是将字段表示形式转换为 时间戳表示形式, 并使用该时间戳初始化新日历
    • 新日历使用儒略历系统表示日期,因为该日期早于1582

有几种解决方法:

  • LocalDate#fromCalendarFiels
    如果您只对日期感兴趣,请使用JodaTime
  • 使用字段访问而不是
    #getTime
    方法转换日历
  • 强制使用公历系统(与 XMLGregorianCalendar 一样)

更新 请注意,Java Date和Calendar API的设计不是很好,有时可能会(并且确实)令人困惑。这也是Java
8包含完全重做的日期时间库JSR-310(顺便基于JodaTime)的原因。

现在,您必须意识到,您可以通过两种截然不同的方法来存储和使用特定的 即时 (日历独立关键字):

  • 存储与定义良好的称为epoch的 瞬间 的偏移量(例如毫秒)(例如unix epoch 1970-01-01)
  • 按日历字段存储日期(例如1970年1月1日)

第一种方法是在引擎盖下使用的方法

java.util.Date
。但是,这种表示通常是非人类友好的。人类使用日历日期,而不是时间戳。Calendar将介入将时间戳转换为日期字段。这也是有趣的部分开始的地方…如果要通过其字段表示日期,则需要意识到总是有多种方法来实现。一些国家可以决定使用阴历月份,而其他国家则可以说0年只是10年前。阳历只是将实际时间转换为实际日期字段的一种方法。

关于 XMLGregorianCalendarGregorianCalendar的一些知识

  • XML规范明确指出人类可读的日期是 公历 日期
  • Java的 GregorianCalendar 包含此 “ magic” ,如果该时刻早于定义的转换日期,则将在后台转换为Julian系统
  • 这就是为什么 XMLGregorianCalendar 在初始化期间修改 GregorianCalendar 以禁用此魔术开关的原因(请参见上述JavaDoc的摘录)

现在有趣的部分:

如果不会禁用Julian开关, GregorianCalendar
会假定日历字段来自Julian系统,并且将其转换3天。您以为日期已改了3天,肯定出了点问题,对吧? 不,日期实际上一直都是正确的
,并且包含正确的时间戳记!仅日历向您提供了朱利安字段而不是格里高利字段。我会说这很令人困惑:) [JSR-310在后台笑]。

所以,如果你想用纯阳历工作(即使用所谓的 proleptic阳历 旧日期),你需要初始化日历是这样的:

Calendar calendar = Calendar.getInstance();((GregorianCalendar) calendar).setGregorianChange(new Date(Long.MIN_VALUE));

您可能会说:

calendar.getTime()
仍然给我错误的日期。好吧,这是因为
java.util.Date.toString()
(由调用
System.out.println
)使用的是default
Calendar
,它将为较旧的日期切换到Julian系统。困惑?也许生气(我知道我是:))?


更新2

// Get XML gregorian calendarXMLGregorianCalendar xmlCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar();xmlCalendar.setYear(1); // Watch for octal number representations (you had there 0001)xmlCalendar.setMonth(1);xmlCalendar.setDay(1);// Convert to Calendar as it is easier to work with itCalendar calendar = xmlCalendar.toGregorianCalendar(); // Proleptic for old dates// Convert to default calendar (will misinterpret proleptic for Julian, but it is a workaround)Calendar result = Calendar.getInstance();result.setTimeZone(calendar.getTimeZone());result.set(Calendar.YEAR, calendar.get(Calendar.YEAR));result.set(Calendar.MONTH, calendar.get(Calendar.MONTH));result.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH));result.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));result.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE));result.set(Calendar.SECOND, calendar.get(Calendar.SECOND));result.set(Calendar.MILLISECOND, calendar.get(Calendar.MILLISECOND));System.out.println(result.getTime());

Disclamer: 此代码是错误的 (结果即时与XML文件中的即时不同),但是OP理解了问题及其后果(请参见此答案下的讨论)。



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5426940.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-11
下一篇 2022-12-11

发表评论

登录后才能评论

评论列表(0条)

保存