我目前遇到 XMLGregorianCalendar 格式问题,想向您的 Java 专家寻求帮助。通过来自其他系统的函数调用,我在网页上显示了一个数据对象,其中“SUBMIT_DATE”:1516032000000 和“SUBMIT_TIME”:36895000(均返回类型为 XMLGregorianCalendar)。在这种情况下,我如何知道正确的人类可读日期和时间?
感谢您的时间和帮助。
我目前遇到 XMLGregorianCalendar 格式问题,想向您的 Java 专家寻求帮助。通过来自其他系统的函数调用,我在网页上显示了一个数据对象,其中“SUBMIT_DATE”:1516032000000 和“SUBMIT_TIME”:36895000(均返回类型为 XMLGregorianCalendar)。在这种情况下,我如何知道正确的人类可读日期和时间?
感谢您的时间和帮助。
// 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秒</p>
我假设submitDate
和submitTime
是XMLGregorianCalendar
您从远程系统收到的复杂对象中获得的对象。我进一步假设您可以要求日期包含 UTC 偏移量。虽然该方法被称为getTimezone
,但它真正返回的不是时区,而是与 UTC(或 GMT)的分钟偏移量。四个if
语句中的广泛检查是必要的,因为XMLGregorianCalendar
对于定义哪些字段和不定义哪些字段非常灵活。
要以适合用户受众的格式显示日期和时间,您需要知道该受众的时区和区域设置。一旦你知道这些,请将它们填写在上面的代码段中。如果您信任 JVM 的设置,您可以使用和ZoneId.systemDefault()
/或Locale.getDefault(Locale.Category.FORMAT)
您也可以在格式样式FULL
、LONG
和.MEDIUM
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);
我得到了与上面相同的结果。
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);
这打印
2018年1月16日上午10时14分55秒</p>
要以适合用户受众的格式显示日期和时间,您需要知道该受众的时区和区域设置。一旦你知道了这些,请将它们填写在上述代码段的前两行中。如果您信任计算机的设置,您可以使用和ZoneId.systemDefault()
/或Locale.getDefault(Locale.Category.FORMAT)
您也可以在格式样式FULL
、LONG
和. 为此,我认为您可以忽略返回类型为 的信息。MEDIUM
SHORT
XMLGregorianCalendar
作为另一个答案中的@user unknown,我假设您可以只添加两个数值。第一个几乎肯定表示自纪元以来的毫秒数,总和也可能如此。那么为什么它们作为两个值而不是一个值传递呢?我最好的猜测是,他们为任何只需要日期而不是一天中的时间的客户分别传递日期。日期值在偏移量 +08:00 的时区中处于午夜,这与中国、菲律宾、马来西亚和其他十几个时区一致。
如果你有两个XMLGregorianCalendar
对象而不是数字,那么获取日期和时间是另一回事,但你仍然可以使用相同的方式来格式化它们。
final GregorianCalendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(date);
return DatatypeFactory.newInstance().newXMLGregorianCalendar(
calendar);
这应该工作..通过你的毫秒
您的输入看起来只是没有时间的日期(以毫秒为单位)和没有日期的时间(以毫秒为单位)。
如果将两个值除以 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 的各种日期/时间格式都有方法,这些方法采用自纪元 (1.1.1970) 以来的秒长参数来设置时间。