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

Java 8 DateTimeFormatter解析可选部分

狄心水
2023-03-14

我需要将日期时间解析为两种不同格式的字符串:

  • 19861221235959Z
  • 1986-12-21T23:59:59Z

以下dateTimeForware模式正确解析第一种日期字符串

DateTimeFormatter.ofPattern ("uuuuMMddHHmmss[,S][.S]X")

但是第二个失败了,因为破折号、冒号和T不是预期的。

我尝试使用以下可选部分:

DateTimeFormatter.ofPattern ("uuuu[-]MM[-]dd['T']HH[:]mm[:]ss[,S][.S]X")

出乎意料的是,这会解析第二种日期字符串(带破折号的),而不是第一种,抛出一个

java.time.format.DateTimeParseException: Text '19861221235959Z' could not be parsed at index 0

这就好像可选部分没有被评估为可选的。。。

共有3个答案

乐正峰
2023-03-14

基于模式的DateTimeFormatter不够智能,无法处理可选部分和两个数字字段不分离的可能性。当您确实需要数字字段不带分隔符时,毫无疑问,模式会理解模式字母从u到M的变化意味着它需要计算数字以知道哪个数字是哪些字段的一部分。但当这不是必然的时候,模式就不会尝试这样做。它看到一个数字字段被完整描述,而不是紧跟着另一个数字字段。因此,没有理由计算数字。所有数字都是此处应该表示的字段的一部分。

要做到这一点,您不应该尝试使用模式构建DateTimeFormatter,而应该使用生成器。从DateTimeFormatter获得灵感。BASIC_ISO_日期和附近的其他日期。

缪朝
2023-03-14

从留档中还不清楚,但我的猜测是,接下来会发生什么。

在格式模式字符串中使用uummddhmmss时,格式化程序可以很容易地看到有几个相邻的数字字段,因此使用字段宽度来分隔字段。前4位表示年份,依此类推。

相反,当您使用uuuu[-]MM[-]dd['T']HH[:]MM[:]ss时,格式化程序不会将其视为相邻的数字字段。我同意Peter Lawrey的评论,即每年需要更长的数字运行,最终溢出最大年份(99999999),并抛出例外。

解决方案是什么?请参考Michael的回答。

霍弘厚
2023-03-14

问题是您的模式将整个字符串视为年份。您可以使用. appendValue(ChronoField. YEAR,4)将其限制为四个字符:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .appendValue(ChronoField.YEAR, 4)
    .appendPattern("[-]MM[-]dd['T']HH[:]mm[:]ss[,S][.S]X")
    .toFormatter();

这可以正确解析您的两个示例。

如果你想说得更详细,你可以:

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .appendValue(ChronoField.YEAR, 4)
    .optionalStart().appendLiteral('-').optionalEnd()
    .appendPattern("MM")
    .optionalStart().appendLiteral('-').optionalEnd()
    .appendPattern("dd")
    .optionalStart().appendLiteral('T').optionalEnd()
    .appendPattern("HH")
    .optionalStart().appendLiteral(':').optionalEnd()
    .appendPattern("mm")
    .optionalStart().appendLiteral(':').optionalEnd()
    .appendPattern("ss")
    .optionalStart().appendPattern("X").optionalEnd()
    .toFormatter();
 类似资料:
  • 我正在寻找一种方法来解析多部分/可选电子邮件的正文部分。目前,我有一个使用Email::Mime模块的perl脚本,它可以正确解析text/plain和text/html。尽管我的问题是,当我解析一个多部分/可选电子邮件时,$part- PERL代码 来源

  • 我有一个简单的问题:我希望严格地以的格式解析Java字符串,以便是有效日期,而不是。假设这些是正常公历的广告日期。 我试图使用JDK8中新的包来解决这个问题,但事实证明它比希望的要复杂。我当前的代码是: 如何使用来解决我的简单用例?

  • 我正在尝试制作一个正则表达式字符串,从报告文件中提取数据。棘手的部分是我需要这个单一的正则表达式字符串来匹配多种报告文件内容格式。我希望正则表达式始终匹配,即使没有找到一些可选的组。 取以下报告文件内容(注意:#2 缺少“val2”部分): 文件#1:“-val1-test-val2-的结果-val3-做-” 预期结果: Val1组:测试 Val2组:结果 Val3组:完成 < li >预期结果:

  • 问题内容: 我有以下代码(使用Python 2.7): 现在,我希望能够调用此程序,例如在普通程序或某些子命令后附加: 基本上,我需要声明可选的子解析器。我知道这并不是真正支持的方法,但是有任何解决方法或替代方法吗? 编辑:我得到的错误信息: 问题答案: 根据文档,带有(而不带有)的会自动打印版本号:

  • 如果仅仅因为想要查找文档中的<a>标签而将整片文档进行解析,实在是浪费内存和时间.最快的方法是从一开始就把<a>标签以外的东西都忽略掉. SoupStrainer 类可以定义文档的某段内容,这样搜索文档时就不必先解析整篇文档,只会解析在 SoupStrainer 中定义过的文档. 创建一个 SoupStrainer 对象并作为 parse_only 参数给 BeautifulSoup 的构造方法即

  • 如果仅仅因为想要查找文档中的<a>标签而将整片文档进行解析,实在是浪费内存和时间.最快的方法是从一开始就把<a>标签以外的东西都忽略掉. SoupStrainer 类可以定义文档的某段内容,这样搜索文档时就不必先解析整篇文档,只会解析在 SoupStrainer 中定义过的文档. 创建一个 SoupStrainer 对象并作为 parse_only 参数给 BeautifulSoup 的构造方法即