0

我目前遇到 XMLGregorianCalendar 格式问题,想向您的 Java 专家寻求帮助。通过来自其他系统的函数调用,我在网页上显示了一个数据对象,其中“SUBMIT_DATE”:1516032000000 和“SUBMIT_TIME”:36895000(均返回类型为 XMLGregorianCalendar)。在这种情况下,我如何知道正确的人类可读日期和时间?

感谢您的时间和帮助。

4

3 回答 3

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秒</p>

我假设submitDatesubmitTimeXMLGregorianCalendar您从远程系统收到的复杂对象中获得的对象。我进一步假设您可以要求日期包含 UTC 偏移量。虽然该方法被称为getTimezone,但它真正返回的不是时区,而是与 UTC(或 GMT)的分钟偏移量。四个if语句中的广泛检查是必要的,因为XMLGregorianCalendar对于定义哪些字段和不定义哪些字段非常灵活。

要以适合用户受众的格式显示日期和时间,您需要知道该受众的时区区域设置。一旦你知道这些,请将它们填写在上面的代码段中。如果您信任 JVM 的设置,您可以使用和ZoneId.systemDefault()/或Locale.getDefault(Locale.Category.FORMAT)您也可以在格式样式FULLLONG和.MEDIUMSHORT

如果您没有收到偏移量,您将需要依赖已经在用户偏移量处的日期和时间。一方面它更简单,另一方面它更脆弱,因为如果给定日期和时间的偏移量超出了用户的预期,他/她将收到不正确的信息,这比根本没有收到信息更糟糕。首先检查确实没有偏移:

    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)您也可以在格式样式FULLLONG和. 为此,我认为您可以忽略返回类型为 的信息。MEDIUMSHORTXMLGregorianCalendar

作为另一个答案中的@user unknown,我假设您可以只添加两个数值。第一个几乎肯定表示自纪元以来的毫秒数,总和也可能如此。那么为什么它们作为两个值而不是一个值传递呢?我最好的猜测是,他们为任何只需要日期而不是一天中的时间的客户分别传递日期。日期值在偏移量 +08:00 的时区中处于午夜,这与中国、菲律宾、马来西亚和其他十几个时区一致。

如果你有两个XMLGregorianCalendar对象而不是数字,那么获取日期和时间是另一回事,但你仍然可以使用相同的方式来格式化它们。

于 2018-04-02T06:04:59.277 回答
1
    final GregorianCalendar calendar = new GregorianCalendar();
    calendar.setTimeInMillis(date);
    return DatatypeFactory.newInstance().newXMLGregorianCalendar(
        calendar);

这应该工作..通过你的毫秒

于 2018-04-02T03:54:21.957 回答
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 的各种日期/时间格式都有方法,这些方法采用自纪元 (1.1.1970) 以来的秒长参数来设置时间。

于 2018-04-02T03:44:05.717 回答