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

Java / Spring中带有逗号分隔符的iso-8601解析器

如何解决Java / Spring中带有逗号分隔符的iso-8601解析器

根据 http://apiux.com/2013/03/20/5-laws-api-dates-and-times/ 我们应该使用ISO 8601格式化日期。 我系统上的输出是:

$ date --iso-8601=ns
2020-10-29T10:38:59,112768965+01:00

哪个Java格式化程序可以正确解析此字符串? 我已经尝试过DateTimeFormatter.ISO_OFFSET_DATE_TIME和其他一些,他们不喜欢这种格式。我希望应该立即支持这种格式,就像Oracle在其页面https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html中声称的那样,但不是。

另一件事是Spring宣布广泛支持日期格式: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.3-Release-Notes#date-time-conversion-in-web-applications。然后,我可以将所有属性设置为“ iso”。但是它到底是哪种格式,在哪里使用?

在这里看到两个问题。

我希望在整个应用程序中采用一致的日期格式方法,并且希望使用标准轻松地与世界其他地区集成。我该怎么用?

编辑:最后碰巧要考虑一些事情:

  • Linux控制台中的示例是人为的,因为在现实世界中我没有注意到这种带有“,”的格式。事实证明,Java世界中对它的支持略有不一致
  • ObjectMapper,modelmapper和OffsetDateTime使Date对象转换不同,尤其是转换为ISO格式(“ Z”或“ 00:00”)
  • Java中也存在“ 0000”形式的偏移量定义,我必须修复转换

解决方法

ISO 8601-1允许,.都作为小数点分隔符,尽管实际上这是我第一次看到,实际使用。 JDK 11中的默认格式仅支持解析.(即使文档说十进制分隔符已本地化)。要处理这种格式,您可以选择以下几种方式:

  1. 在解析之前修改字符串:
OffsetDateTime.parse(value.replaceAll(",","."));
  1. 定义自定义格式:
 new DateTimeFormatterBuilder()
         .parseCaseInsensitive()
         .append(ISO_LOCAL_DATE)
         .appendLiteral('T')
         .appendValue(HOUR_OF_DAY,2)
         .appendLiteral(':')
         .appendValue(MINUTE_OF_HOUR,2)
         .optionalStart()
         .appendLiteral(':')
         .appendValue(SECOND_OF_MINUTE,2)
         .optionalStart()
         .appendLiteral(',')
         .appendFraction(NANO_OF_SECOND,9,false)
         .parseLenient()
         .appendOffsetId()
         .toFormatter()
         .parse(value)
  1. 使用使用,分隔符的语言环境(在JDK 15中已确认工作):
DateTimeFormatter.ISO_OFFSET_DATE_TIME.localizedBy(Locale.FRANCE).parse(value);

似乎没有一种方法可以定义允许,.但不允许两者都使用的格式。您将不得不尝试一种捕获异常然后再尝试另一种,或者检测异常所采用的格式(例如value.contains(","))并使用适当的格式化程序。

,

如果您的字符串在逗号后总是有9个小数,只需在格式模式字符串中指定一个逗号即可:

    DateTimeFormatter isoWithCommaFormatter = DateTimeFormatter
            .ofPattern("uuuu-MM-dd'T'HH:mm:ss,SSSSSSSSSXXX");
    String iso = "2020-10-29T10:38:59,112768965+01:00";
    OffsetDateTime odt = OffsetDateTime.parse(iso,isoWithCommaFormatter);
    System.out.println(odt);

输出:

2020-10-29T10:38:59.112768965 + 01:00

如果小数位数可能有所不同,则需要一个DateTimeFormatterBuilder,但基本技巧是相同的简单技巧:在格式模式字符串中放入逗号。

    DateTimeFormatter isoWithCommaFormatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .appendPattern("HH:mm:ss[,")
            .appendFraction(ChronoField.NANO_OF_SECOND,false)
            .appendPattern("]XXX")
            .toFormatter();

ISO 8601格式建议使用点号上的逗号作为小数点分隔符,因此,内置格式化程序和one-arg parse方法仅接受点有点可笑。

,

您可以简单地使用逗号而不是点来分隔纳秒,例如您可以使用DateTimeFormatter.ofPattern("u-M-d'T'H:m:s,nXXX")

演示:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        OffsetDateTime odt = OffsetDateTime.parse("2020-10-29T10:38:59,112768965+01:00",DateTimeFormatter.ofPattern("u-M-d'T'H:m:s,nXXX"));
        System.out.println(odt);
    }
}

输出:

2020-10-29T10:38:59.112768965+01:00

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