Java或Scala是一种使用Java.time以多种不同格式解析日期的快速方法

Java或Scala是一种使用Java.time以多种不同格式解析日期的快速方法,java,scala,date,parsing,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 。。。这么多的可能性 有没有一种很好的方法可以让一个或“

我想为随机格式的日期提供一个通用的快速解析器,如:

  • 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之前的版本),或者不关注性能和许多不同的格式。

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

  • 数据格式中存在各种变化和歧义,这使得通用解析器非常困难。e、 g.
    11/11/11

  • 您正在寻找非常高的性能,这排除了任何暴力方法。1U/日期意味着只有几千条指令可以完成完整的解析

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

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

    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
    }
    

    正如你所看到的,一旦把所有可能的日期都包括在内,事情就会变得非常棘手。但是,如果正则表达式引擎能够处理它,那么它应该是有效的,因为正则表达式应该编译到一个状态机,该状态机只会查看每个字符一次。

    更聪明的方法是——你的意思是使用一些预配置的日期格式,这样就不需要预先指定不同的日期格式了?是的,我会尽可能多地寻找NLP领域的一些库。不确定,如果您已经看到了这个答案的话:乍一看,Natty解析单个日期看起来不错,但我不确定这个NLP库能否在几秒钟内处理数百万个日期。此外,该项目自3年以来一直停滞不前。不管怎样,我都会测试它。TY@alexeynovakov当解析为
    LocalDateTime
    时,您似乎丢失了重要的偏移量信息。最后两个示例表示不同的时间点,但将解析为相等的
    LocalDateTime
    对象。我认为你不应该想要那个。