Java 或 Scala 使用 java.time 快速解析具有多种不同格式的日期

标签 java scala date parsing

我想要一个通用且快速的解析器来解析随机格式的日期,例如:

  • 2018
  • 2018-12-31
  • 2018/12/31
  • 2018 年 12 月 31 日
  • 20181231151617
  • 2018-12-31T15:16:17
  • 2018-12-31T15:16:17.123456
  • 2018-12-31T15:16:17.123456Z
  • 2018-12-31T15:16:17.123456 UTC
  • 2018-12-31T15:16:17.123456+01:00
  • ... 这么多的可能性

有没有一种好的方法或“魔术”函数可以做到这一点?

目前我打算使用这样的东西:

val formatter = new DateTimeFormatterBuilder()
  .appendPattern("[yyyy-MM-dd'T'HH:mm:ss]")
  .appendPattern("[yyyy-MM-dd]")
  .appendPattern("[yyyy]")
  // add so many things here
  .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)
  .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
  .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
  .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
  .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
  .parseDefaulting(ChronoField.MICRO_OF_SECOND, 0)
  .toFormatter()


val temporalAccessor = formatter.parse("2018")
val localDateTime = LocalDateTime.from(temporalAccessor)
localDateTime.getHour
val zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.systemDefault)
val result = Instant.from(zonedDateTime)

但是有比指定数百种格式更聪明的方法吗?

我找到的大多数答案都已过时(Java8 之前)或不关注性能和许多不同的格式。

最佳答案

不,没有好的/神奇的方法来做到这一点,主要有两个原因:

  1. 数据格式的变化和歧义使得通用解析器非常困难。例如11/11/11

  2. 您正在寻找非常高的性能,这排除了任何暴力方法。每个日期 1us 意味着只需几千条指令即可完成完整解析。

在某种程度上,您将不得不指定哪些格式有效以及如何解释它们。执行此操作的最佳方法可能是一个或多个正则表达式,从可能构成日期的所有允许的字符组合中提取适当的字段,然后对各个字段进行更简单的验证。

这是一个处理您列出的所有日期的示例:

val DateMatch = """(\d\d\d\d)[-/ ]?((?:\d\d)|(?:\w\w\w))?[-/ ]?(\d\d)?T?(\d\d)?:?(\d\d)?:?(\d\d)?[\.]*(\d+)?(.*)?""".r

date match {
  case DateMatch(year, month, day, hour, min, sec, usec, timezone) =>
    (year, Option(month).getOrElse("1"), Option(day).getOrElse(1), Option(hour).getOrElse(0), Option(min).getOrElse(0), Option(sec).getOrElse(0), Option(usec).getOrElse(0), Option(timezone).getOrElse(""))
  case _ =>
    throw InvalidDateException
}

如您所见,一旦包含所有可能的日期,它就会变得非常棘手。但是,如果正则表达式引擎可以处理它,那么它应该是高效的,因为正则表达式应该编译成一个状态机,它只查看每个字符一次。

关于Java 或 Scala 使用 java.time 快速解析具有多种不同格式的日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54497978/

相关文章:

java - 如何传递包含带空格的目录的 bash 参数作为 Java 参数?

java - 如果从服务器 : Gets called successfully if invoked from Junit(locally) 调用 Web 服务客户端失败

java - OWLOntologyManager.addAxioms() 操作的成本有多高?

java - 将java序列化对象反序列化为Scala类

Javascript String to Date 适用于 Chrome,不适用于 FF 或 Safari

java - 将 Assets 文件夹子目录复制到外部存储中的特定文件夹

scala - 测试递归数据结构

scala - 在 sbt 中手动调用 sourceGenerators

sql-server - SQL - 如何使用 ISO 周获取年-周?

javascript - 创建日期验证器