解析日期时间字符串中的日期序号指示符 ( st, nd, rd, th )

2022-09-02 09:27:47

我检查了SimpleDateFormat javadoc,但我无法找到一种方法来解析日期格式的序号指示器,如下所示:

 Feb 13th 2015 9:00AM

我试过了,但是日子必须数到一半才能正确吗?"MMM dd yyyy hh:mma"

是否可以使用 解析 “13th” 日期而不必截断字符串?SimpleDateFormat


答案 1

Java的SimpleDateFormat不支持序号后缀,但序号后缀只是眼睛糖果 - 它是多余的,可以很容易地删除以允许直接解析:

Date date = new SimpleDateFormat("MMM dd yyyy hh:mma")
    .parse(str.replaceAll("(?<=\\d)(st|nd|rd|th)", ""));

替换正则表达式非常简单,因为这些序列不会出现在有效日期的任何其他位置。


要处理将任何语言中任意长度的序号指示符追加为后缀的任何语言,

Date date = new SimpleDateFormat("MMM dd yyyy hh:mma")
    .parse(str.replaceAll("(?<=\\d)(?=\\D* \\d+ )\\p{L}+", ""));

有些语言,例如普通话,在序号指示器之前附加,但这也可以使用交替来处理 - 留给读者作为练习:)


答案 2

Java 8的答案(以及Java 6和7)(因为当2015年提出这个问题时,替代品已经出来了):SimpleDateFormat

    DateTimeFormatter parseFormatter = DateTimeFormatter
            .ofPattern("MMM d['st']['nd']['rd']['th'] uuuu h:mma", Locale.ENGLISH);
    LocalDateTime dateTime = LocalDateTime.parse(dateTimeString, parseFormatter);

使用问题的示例日期,这个yedls:

2015-02-13T09:00

在格式模式中,表示可选部件并表示文本部件。因此,该模式表示该数字后面可能跟有 、 、 或 。[]''stndrdth

要在Java 6或7中使用它,您需要ThreeTen Backport。或者对于Android ThreeTenABP

由于这些后缀对于英语是特殊的,并且其他语言/区域设置在编写日期和时间方面具有完全不同的用法(它们也不使用AM / PM),因此我相信除非您有其他要求,否则您应该尝试仅针对英语日期和时间实现此功能。此外,您应该明确地提供一个讲英语的区域设置,以便它将独立于计算机或JVM的区域设置工作。

我试图将雨果我自己回答的最佳部分组合成一个重复的问题。在那个重复的问题下,还有更多的java 8答案。上述代码的一个限制是它没有非常严格的验证:您将逃脱甚至.Feb 13rdFeb 13stndrdth

编辑:我自己最喜欢的是关于序数指标的答案是这个。这是关于格式化的,但我在那里介绍的格式化程序也适用于解析。


推荐