【问题标题】:How to get the Date with offset taken into account from XmlGregorianCalendar?如何从 XmlGregorianCalendar 中获取考虑到偏移量的日期?
【发布时间】:2019-11-06 14:52:49
【问题描述】:

我有一个这种形式的 XMLGregorianCalendar:2019-06-24T18:18:55.007+02:00

我怎样才能在这样的字符串中获得正确的日期(考虑到偏移量):24/06/2019 16:18

【问题讨论】:

标签: date java-6 xmlgregoriancalendar


【解决方案1】:

我找到的可行解决方案:

 private String getFormattedDate(final XMLGregorianCalendar xmlGregorianCalendar) {

       Date time = xmlGregorianCalendar.toGregorianCalendar().getTime();
       Date rightDate = DateUtils.addMinutes(time, - xmlGregorianCalendar.getTimezone());
       String formatedDate = DateHelper.format(DateHelper.YYYYMMDDHHMMSS_DASH_COLONS, rightDate);

       return formatedDate;}

【讨论】:

    【解决方案2】:

    您标记了您的问题 java-6。然而,我正在使用现代 Java 日期和时间 API java.time 呈现现代答案。这在 Java 6 中通过 ThreeTen Backport 可用(请参阅底部的链接)。

    根据您从哪里获得XMLGregorianCalendar,您可能不需要拥有一个。如果我理解正确的话,这个类用于表示 XML 文档中的日期和时间,它们的格式类似于 2019-06-24T18:18:55.007+02:00。这种格式足够接近 ISO 8601,java.time 的类可以直接解析它,我们更喜欢这样:

        Locale userLocale = Locale.forLanguageTag("mt-MT"); // Maltese Malta
        DateTimeFormatter displayFormatter
                = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
                        .withLocale(userLocale);
    
        String fromXml = "2019-06-24T18:18:55.007+02:00";
        OffsetDateTime dateTime = OffsetDateTime.parse(fromXml);
        String formattedUtcDateTime = dateTime.withOffsetSameInstant(ZoneOffset.UTC)
                .format(displayFormatter);
        System.out.println(formattedUtcDateTime);
    

    此 sn-p 的输出是(在 Java 1.7.0_67 中使用 ThreeTen Backport 版本 1.3.6 测试):

    24/06/2019 16:18

    假设格式是为了向用户显示,我建议使用 Java 的本地化格式。我选择了马耳他语言环境,因为它完全符合您要求的格式。如果您的用户使用不同的语言环境,您仍应考虑该语言环境的格式。

    从 XMLGregorianCalendar 转换

    如果您的 XMLGregorianCalendar 来自您现在无法更改的旧版 API,则有多种转换方法。

    一种是从XMLGregorianCalendar取回字符串:

        XMLGregorianCalendar xmlgc = DatatypeFactory.newInstance()
                .newXMLGregorianCalendar("2019-06-24T18:18:55.007+02:00");
        String fromXml = xmlgc.toString();
    

    现在剩下的和上面一样。 Pro:它很短,我认为它没有任何惊喜。缺点:对我来说,格式化回原始字符串并再次解析它感觉像是绕道而行。

    另一种选择是通过过时的GregorianCalendar 类:

        GregorianCalendar gc = xmlgc.toGregorianCalendar();
        ZonedDateTime zdt = DateTimeUtils.toZonedDateTime(gc);
        String formattedUtcDateTime = zdt.toOffsetDateTime()
                .withOffsetSameInstant(ZoneOffset.UTC)
                .format(displayFormatter);
    

    Pro:我认为这是官方转换。缺点:它长了一行,正如我所说,它使用了设计不佳且早已过时的GregorianCalendar 类。

    链接

    【讨论】:

    • 感谢您的回答先生,但它不对应于 Java 6 解决方案,我实施的解决方案是从 xmlGregorianCalendar 获取 Date 对象:Date date = xmlGregorianCalendar.toGregorianCalendar().getTime(); 然后使用 getTimeZone 方法:int minutesOffset = xmlGregorianCalendar.getTimezone() (产生 120 分钟)然后 Date wantedDate = date.addMinutes(xmlGregorianCalendar.getTimeZone()) 最终格式化得到 24/06/2019 16:18
    • 不明白你用的是哪个addMinutes方法?如果您从 here 下载 ThreeTen Backport 并将 JAR 文件添加到您的项目中,我的答案和代码将适用于 Java 6。
    • 那是org.joda.time.MutableDateTime.addMinutes 吗?如果是这样:(1)那是不正确/误用并且必然会混淆。 (2) Joda-Time 项目处于维护模式,不推荐用于新代码。我更喜欢 ThreeTen Backport。 (3)如果你坚持使用Joda-Time,我相信可以找到更好的Joda-Time解决方案。
    猜你喜欢
    • 2018-12-14
    • 1970-01-01
    • 2021-12-26
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-28
    相关资源
    最近更新 更多