当前位置: 首页 > 知识库问答 >
问题:

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

相诚
2023-03-14

根据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”。但是它究竟是哪种格式,它在哪里使用?

我在这里看到了两个问题。

  • 一个是 https://github.com/FasterXML/jackson-databind/issues/2643(带或不带分号的偏移量)
  • 第二个是纳米/毫秒的存在(我想使用它们)

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

编辑:最后发生了一些事情需要考虑:

  • 来自Linux控制台的示例是人为的,因为我在现实世界中没有注意到这种带有“,”的格式。事实证明,它在Java世界中的支持略有不一致
  • 对象映射器、模型映射器和偏移日期时间使日期对象转换不同,特别是转换为 ISO 格式(“Z”或“00:00”)
  • “0000”形式的偏移定义也存在于Java中,我必须修复我的转换

共有3个答案

杜霍英
2023-03-14

您可以将.作为可选模式,方法是将它们放在方括号中。

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter isoFormatter = new DateTimeFormatterBuilder()
                .appendPattern("u-M-d'T'H:m:s[.][,]")
                .appendFraction(ChronoField.NANO_OF_SECOND, 0, 9, false)
                .appendPattern("[XXX][XX][X]")
                .toFormatter(Locale.ENGLISH);

        // Test
        System.out.println(OffsetDateTime.parse("2021-05-21T10:20:30,123456789+02:00", isoFormatter));
        System.out.println(OffsetDateTime.parse("2021-05-21T10:20:30,123456789+0200", isoFormatter));
        System.out.println(OffsetDateTime.parse("2021-05-21T10:20:30,123456789+02", isoFormatter));
        System.out.println(OffsetDateTime.parse("2021-05-21T10:20:30.123456789+02:00", isoFormatter));
        System.out.println(OffsetDateTime.parse("2021-05-21T10:20:30+02:00", isoFormatter));
    }
}

输出:

2021-05-21T10:20:30.123456789+02:00
2021-05-21T10:20:30.123456789+02:00
2021-05-21T10:20:30.123456789+02:00
2021-05-21T10:20:30.123456789+02:00
2021-05-21T10:20:30+02:00

或者,

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

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter isoFormatter = DateTimeFormatter.ofPattern(
                "u[-M[-d]]['T'H[:m[:s[.][,][SSSSSSSSS][SSSSSSSS][SSSSSSS][SSSSSS][SSSSS][SSSS][SSS][SS][S]]]][XXX][XX][X]",
                Locale.ENGLISH);

        // Test
        System.out.println(OffsetDateTime.parse("2021-05-21T10:20:30,123456789+02:00", isoFormatter));
        System.out.println(OffsetDateTime.parse("2021-05-21T10:20:30,123456789+0200", isoFormatter));
        System.out.println(OffsetDateTime.parse("2021-05-21T10:20:30,123456789+02", isoFormatter));
        System.out.println(OffsetDateTime.parse("2021-05-21T10:20:30.123456789+02:00", isoFormatter));
        System.out.println(OffsetDateTime.parse("2021-05-21T10:20:30+02:00", isoFormatter));
    }
}

输出是一样的。

匡晟
2023-03-14
匿名用户

如果字符串的逗号后面总是有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

如果小数位数可能不同,您需要一个< code > DateTimeFormatterBuilder ,但基本技巧还是一样简单:在格式模式字符串中放一个逗号。

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

ISO 8601格式建议将逗号作为小数分隔符,因此内置格式化程序和one-argparse方法只接受点有点有趣。

谭志用
2023-03-14

ISO 8601-1 允许 作为小数分隔符,尽管在实践中这是我第一次看到 实际使用。JDK 11 中的默认格式仅支持解析 即使文档说小数分隔符已本地化)。要处理此格式,您有一些选择:

  1. 在解析之前修改字符串:
OffsetDateTime.parse(value.replaceAll(",", "."));
 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, 0, 9, false)
         .parseLenient()
         .appendOffsetId()
         .toFormatter()
         .parse(value)
DateTimeFormatter.ISO_OFFSET_DATE_TIME.localizedBy(Locale.FRANCE).parse(value);

似乎没有一种方法可以定义允许的格式。但不能两者兼而有之。您必须尝试一个捕获异常并尝试另一个,或者检测它是哪种格式(例如value.contains (",") )并使用适当的格式化程序。

 类似资料:
  • 问题内容: 我有一些特殊字符的字符串。目的是检索每行的String [](分隔)。您可以使用特殊字符“,在其中可以使用/ n和, 您会看到“ /”中有您/ n。 任何可以帮助我解析此。 谢谢 __更多说明 与主刺我需要分开这些 问题是:对于Julie,KameL,Titi ,在KameL和Titi之间存在换行符/ n,或者在Time,tomy,tony,tini之间存在类似的换行问题,或者 在to

  • 问题内容: 我有一个字符串,我正在尝试将其解析为一个数字。我尝试使用,结果为2。我猜逗号是问题所在,但我将如何以正确的方式解决此问题?只需删除逗号? 问题答案: 是的,删除逗号:

  • 问题内容: 我有一个模糊的字符串,像这样: 我想按逗号分割-但我需要忽略引号中的逗号。我怎样才能做到这一点?似乎正则表达式方法失败了;我想我可以在看到报价时手动扫描并进入其他模式,但是使用预先存在的库会很好。(编辑:我想我的意思是那些已经属于JDK或已经属于诸如Apache Commons之类的常用库的库。) 上面的字符串应分为: 注意:这不是CSV文件,它是文件中包含的单个字符串,具有较大的整体

  • 问题内容: 我有这样一个字符串: 我想按逗号分割-但我需要忽略引号中的逗号。我怎样才能做到这一点?似乎正则表达式方法失败了;我想我可以在看到报价时手动扫描并进入其他模式,但是使用预先存在的库会很好。 上面的字符串应分为: 问题答案: 可以使用正则表达式 输出:

  • 问题内容: 我有一个像 我想把它分成那些字符串 如果我简单地打电话给我,那么在修剪之后我会得到不同的结果,因为在某些字符串中,例如,仍然有一个逗号。但我不想放在方括号中。有解决这个问题的优雅方法吗? 问题答案: 假设和没有嵌套和未转义。您可以使用以下方式进行拆分: 正则演示 如果逗号后面没有非圆括号和,则将匹配逗号,从而忽略和中的逗号。

  • 问题内容: 我有一个像这样的字符串: 上面的字符串应分为: 问题答案: 我认为最简单的解决方案是处理输入字符串char-by-char: 例: 作为免费赠品,此解决方案还根据需要计算嵌套括号: 它还检查括号是否平衡(每个开放的括号都有相应的结束符)。