我目前无法使用XMLGregorianCalendar格式化问题,并希望从您的java专家那里寻求帮助。通过来自其他系统的函数调用,我得到了一个显示在网页上的数据对象,其中包含" SUBMIT_DATE":1516032000000和" SUBMIT_TIME":36895000(都返回类型为XMLGregorianCalendar)。在这种情况下,如何知道正确的人类可读日期和时间?
感谢您的时间和帮助。
答案 0 :(得分:2)
// We first need to check that the fields we need are defined
if (submitDate.getTimezone() == DatatypeConstants.FIELD_UNDEFINED) {
throw new IllegalStateException("No time zone defined in submit date " + submitDate);
}
if (submitDate.getYear() == DatatypeConstants.FIELD_UNDEFINED
|| submitDate.getMonth() == DatatypeConstants.FIELD_UNDEFINED
|| submitDate.getDay() == DatatypeConstants.FIELD_UNDEFINED) {
throw new IllegalStateException("Date not defined in submit date " + submitDate);
}
if (submitTime.getHour() == DatatypeConstants.FIELD_UNDEFINED
|| submitTime.getMinute() == DatatypeConstants.FIELD_UNDEFINED
|| submitTime.getSecond() == DatatypeConstants.FIELD_UNDEFINED) {
throw new IllegalStateException("Time of day not defined in submit time " + submitTime);
}
if (submitTime.getTimezone() != DatatypeConstants.FIELD_UNDEFINED
&& submitTime.getTimezone() != submitDate.getTimezone()) {
throw new IllegalStateException("Conflicting offsets " + submitDate.getTimezone()
+ " and " + submitTime.getTimezone() + " minutes");
}
// then format into a human readable string
final ZoneId userZone = ZoneId.of("Asia/Taipei");
final Locale userLocale = Locale.forLanguageTag("zh-TW");
DateTimeFormatter localizedFormatter = DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.LONG)
.withLocale(userLocale);
ZonedDateTime dateTime = submitDate.toGregorianCalendar()
.toZonedDateTime()
.with(LocalTime.of(submitTime.getHour(), submitTime.getMinute(), submitTime.getSecond()))
.withZoneSameInstant(userZone);
String humanReadableDateTime = dateTime.format(localizedFormatter);
System.out.println(humanReadableDateTime);
打印:
2018年1月16日上午10时14分55秒
我假设您从远程系统收到的复杂对象中获得了submitDate
和submitTime
个XMLGregorianCalendar
个对象。我进一步假设您可以要求日期包含UTC偏移量。虽然该方法称为getTimezone
,但它实际返回的不是时区,而是以UTC(或GMT)为单位的分钟偏移量。四个if
语句中的大量检查是必要的,因为XMLGregorianCalendar
非常灵活,哪些字段是定义的,哪些不是。
要以适合用户受众的格式显示日期和时间,您需要知道受众群体的时区和区域设置。一旦你知道了这些,请填写上面的代码片段。如果您信任JVM的设置,则可以使用ZoneId.systemDefault()
和/或Locale.getDefault(Locale.Category.FORMAT)
您也可以选择格式样式FULL
,LONG
,MEDIUM
和{{ 1}}。
如果您没有收到偏移量,则需要依赖已经处于用户偏移量的日期和时间。一方面它更简单,另一方面它更脆弱,因为如果日期和时间以另一个偏差给出,而不是用户期望,他/她将收到不正确的信息,这比根本不接收任何信息更糟糕。首先检查确实没有偏移:
SHORT
同时检查是否定义了必填字段,这与以前相同。然后创建一个 if (submitDate.getTimezone() != DatatypeConstants.FIELD_UNDEFINED
|| submitTime.getTimezone() != DatatypeConstants.FIELD_UNDEFINED) {
throw new IllegalStateException("Unexpected offset");
}
对象并对其进行格式化:
LocalDateTime
我得到了与上面相同的结果。
LocalDateTime dateTime = LocalDateTime.of(
submitDate.getYear(), submitDate.getMonth(), submitDate.getDay(),
submitTime.getHour(), submitTime.getMinute(), submitTime.getSecond());
String humanReadableDateTime = dateTime.format(localizedFormatter);
打印
2018年1月16日上午10时14分55秒
要以适合用户受众的格式显示日期和时间,您需要知道受众群体的时区和区域设置。一旦你知道了这些,请填写上面代码段的前两行。如果您信任计算机的设置,则可以使用 final ZoneId userZone = ZoneId.of("Asia/Taipei");
final Locale userLocale = Locale.forLanguageTag("zh-TW");
ZonedDateTime submitDateTime
= Instant.ofEpochMilli(submitDate + submitTime).atZone(userZone);
DateTimeFormatter localizedFormatter = DateTimeFormatter
.ofLocalizedDateTime(FormatStyle.LONG)
.withLocale(userLocale);
String humanReadableDateTime = submitDateTime.format(localizedFormatter);
System.out.println(humanReadableDateTime);
和/或ZoneId.systemDefault()
您还可以选择格式样式Locale.getDefault(Locale.Category.FORMAT)
,FULL
,LONG
和{{ 1}}。为此,我认为您可以忽略返回类型为MEDIUM
的信息。
作为another answer中的@user unknown,我假设您只需添加两个数值即可。第一个几乎可以肯定地表示自纪元以来的毫秒数,也就是总和。那么为什么他们作为两个值传递而不仅仅是一个?我最好的猜测是,他们分别为任何只需要日期而不是一天中的时间的客户传递日期。日期值在时区的午夜时间偏移+08:00,这与中国,菲律宾,马来西亚和其他十几个时区一致。
如果您有两个SHORT
个对象而不是数字,那么获取日期和时间是一个不同的故事,但您仍然可以使用相同的方式对它们进行格式化。
答案 1 :(得分:1)
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(date);
return DatatypeFactory.newInstance().newXMLGregorianCalendar(
calendar);
这应该有用.. 通过你的毫秒
答案 2 :(得分:0)
您的输入看起来就像是没有时间的日期(以毫秒为单位)和没有日期的时间(以毫秒为单位)。
如果将两个值除以1000:
date -d @1516032000
Mo 15. Jan 17:00:00 CET 2018
date -d @36895
Do 1. Jan 11:14:55 CET 1970
嗯 - 但为什么17:00:00?也许是时区问题。
以下是聚合:
date -d @$((1516032000+36895))
Di 16. Jan 03:14:55 CET 2018
Java的各种日期/时间格式都有方法,从epoch(1.1.1970)起设置时间需要一个很长的参数秒。