微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 BeanIO 解析 RFC3339 日期字符串 'ss.SSSXX'

如何解决使用 BeanIO 解析 RFC3339 日期字符串 'ss.SSSXX'

我正在尝试解析这样的字符串日期:2021-03-19T13:08:32.58600 在我的模板中使用 BeanIO:

<field name="updatedAt" typeHandler="dateTypeHandler" format="yyyy-MM-dd'T'HH:mm:SSSXX"/>

我收到了 Invalid date 错误

我使用 SimpleDateFormat 测试了一些情况,例如,如果我执行以下操作: new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(text) 有效。

问题出在DateTypeHandlerSupport类中,方法解析验证长度:

    protected Date parseDate(String text) throws TypeConversionException {
        if ("".equals(text))
            return null;

        ParsePosition pp = new ParsePosition(0);
        Date date = getFormat().parse(text,pp);
        if (pp.getErrorIndex() >= 0 || pp.getIndex() != text.length()) {
            throw new TypeConversionException("Invalid date");
        }
        return date;
    }

有什么方法可以在不创建自己的 DateTypeHandler 的情况下解析字符串?

解决方法

字符串的尾随 00 不是有效的 UTC 偏移量。我非常确信它从来就不是一个。相反,您的字符串为我们提供了带有 5 位小数的秒数,并且不包括偏移量。

很抱歉,您无法解析它。如果 BeanIO 内部使用 SimpleDateFormat(臭名昭著的类麻烦制造者,幸运的是早已过时),那么它就无法正确解析 2021-03-19T13:08:32.58600SimpleDateFormat 仅支持秒的三位小数,并将 .58600 解析为 58600 毫秒,即 58.6 秒(这是正确的)。请参阅底部相关问题的链接。

您的字符串也不符合 RFC-3339。根据 RFC-3339,时间戳必须包含 time-offset,它必须是 "Z" / time-numoffset 之一,其中 time-numoffset("+" / "-") time-hour ":" time-minute。因此,有效偏移量的示例包括 Z+00:00+11:00-00:00-11:00。如果您从某个地方收到了 RFC-3339 格式的字符串,那么您似乎需要向发布者介绍该格式标准。

在 Java 中解析字符串很容易。

    String yourString = "2021-03-19T13:08:32.58600";
    LocalDateTime ldt = LocalDateTime.parse(yourString);
    System.out.println(ldt);

输出:

2021-03-19T13:08:32.586

java.time 的类将 ISO 8601 格式的最常见变体解析为它们的默认值,即没有任何格式规范。 RFC-3339 基于 ISO 8601 并与之相比进行了简化。由于您的字符串不包含 UTC 偏移量,因此我将其解析为 LocalDateTime,该类用于不带时区或 UTC 偏移量的日期和时间。

链接

,

我知道当前版本 (2.1) 不支持开箱即用的新 java.time 类,但它会在获得新生命的 new BeanIO project 中提供。

虽然我们等待新版本开箱即用地支持 java.time,但您可以通过创建自己的 org.beanio.types.TypeHandler 实现(最有可能通过实现 org.beanio.types.ConfigurableTypeHandler)来相对轻松地实现它。您可以查看 new TemporalAccessorTypeHandler implementation 并暂时使用它来推出您自己的版本,直到您可以升级到最新版本。此 discussion 还展示了如何使用此类型处理程序并对其进行配置。

我不会在这里复制 TemporalAccessorTypeHandler 的代码,但您可以这样配置:

// declare/register your new type handler
<typeHandler name="javaTimeTypeHandler" 
    class="path.to.your.implementation.TemporalAccessorTypeHandler" />


// now use it in your fields
<field name="updatedAt" typeHandler="javaTimeTypeHandler" 
    format="yyyy-MM-dd'T'HH:mm:SSSXX"/>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。