Java XMLGregorianCalendar格式

时间:2018-04-02 03:13:34

标签: java xml date xmlgregoriancalendar

我目前无法使用XMLGregorianCalendar格式化问题,并希望从您的java专家那里寻求帮助。通过来自其他系统的函数调用,我得到了一个显示在网页上的数据对象,其中包含" SUBMIT_DATE":1516032000000和" SUBMIT_TIME":36895000(都返回类型为XMLGregorianCalendar)。在这种情况下,如何知道正确的人类可读日期和时间?

感谢您的时间和帮助。

3 个答案:

答案 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秒

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

要以适合用户受众的格式显示日期和时间,您需要知道受众群体的时区区域设置。一旦你知道了这些,请填写上面的代码片段。如果您信任JVM的设置,则可以使用ZoneId.systemDefault()和/或Locale.getDefault(Locale.Category.FORMAT)您也可以选择格式样式FULLLONGMEDIUM和{{ 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)FULLLONG和{{ 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)起设置时间需要一个很长的参数秒。