我希望有一个通用的快速解析器来处理随机格式的日期:
某个功能或“魔术”功能能做到这一点吗?
目前,我正计划使用类似这样的内容:
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之前的版本),或者不专注于性能和许多不同的格式。
答案 0 :(得分:1)
不,没有很好的/神奇的方法,主要有两个原因:
数据格式存在变化和模棱两可,这使得通用解析器非常困难。例如11/11/11
您正在寻找非常高的性能,该性能排除了任何强力方法。每个日期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
}
如您所见,一旦包含所有可能的日期,它将变得非常毛茸茸。但是,如果正则表达式引擎可以处理它,那它应该是高效的,因为正则表达式应该编译为一个状态机,该状态机只看一次每个字符。