java - 如何使用 Scala 在 DateTimeFormatter 中传递多种日期格式
问题描述
我有三种日期格式:YYYY-MM-DD、DDMMYYYY、MMDDYYYY 这就是我在 Spark 中传递日期格式以进行解析的方式。
scala> val formatter = DateTimeFormatter.ofPattern("[MMddyyyy][yyyy-MM-dd][yyyyMMdd]")
formatter: java.time.format.DateTimeFormatter = [Value(MonthOfYear,2)Value(DayOfMonth,2)Value(YearOfEra,4,19,EXCEEDS_PAD)][Value(YearOfEra,4,19,EXCEEDS_PAD)'-'Value(MonthOfYear,2)'-'Value(DayOfMonth,2)][Value(YearOfEra,4,19,EXCEEDS_PAD)Value(MonthOfYear,2)Value(DayOfMonth,2)]
对于格式 MMddyyyy 它正在工作
scala> LocalDate.parse("10062019",formatter)
res2: java.time.LocalDate = 2019-10-06
对于格式 yyyyMMdd 它正在工作
scala> LocalDate.parse("2019-06-20",formatter)
res3: java.time.LocalDate = 2019-06-20
对于格式 yyyyMMdd,它给了我一个错误
scala> LocalDate.parse("20190529",formatter)
java.time.format.DateTimeParseException: Text '20190529' could not be parsed: Invalid value for MonthOfYear (valid values 1 - 12): 20
at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1920)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1855)
at java.time.LocalDate.parse(LocalDate.java:400)
... 66 elided
Caused by: java.time.DateTimeException: Invalid value for MonthOfYear (valid values 1 - 12): 20
at java.time.temporal.ValueRange.checkValidIntValue(ValueRange.java:330)
at java.time.temporal.ChronoField.checkValidIntValue(ChronoField.java:722)
at java.time.chrono.IsoChronology.resolveYMD(IsoChronology.java:550)
at java.time.chrono.IsoChronology.resolveYMD(IsoChronology.java:123)
at java.time.chrono.AbstractChronology.resolveDate(AbstractChronology.java:472)
at java.time.chrono.IsoChronology.resolveDate(IsoChronology.java:492)
at java.time.chrono.IsoChronology.resolveDate(IsoChronology.java:123)
at java.time.format.Parsed.resolveDateFields(Parsed.java:351)
at java.time.format.Parsed.resolveFields(Parsed.java:257)
at java.time.format.Parsed.resolve(Parsed.java:244)
at java.time.format.DateTimeParseContext.toResolved(DateTimeParseContext.java:331)
at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1955)
at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
... 67 more
如果我通过 2 格式 yyyyMMdd, yyyy-MM-dd 它工作正常
scala> val formatter = DateTimeFormatter.ofPattern("[yyyy-MM-dd][yyyyMMdd]")
scala> LocalDate.parse("20190529",formatter)
res5: java.time.LocalDate = 2019-05-29
scala> LocalDate.parse("2019-06-20",formatter)
res6: java.time.LocalDate = 2019-06-20
同 yyyy-MM-dd, mmddyyy 日期格式
scala> val formatter = DateTimeFormatter.ofPattern("[yyyy-MM-dd][MMddyyyy]")
scala> LocalDate.parse("10062019",formatter)
res7: java.time.LocalDate = 2019-10-06
scala> LocalDate.parse("2019-06-20",formatter)
res8: java.time.LocalDate = 2019-06-20
有什么办法可以通过三种不同的格式?
解决方案
Java 自己的DateTimeFormatterBuilder#appendOptional
可以不依赖异常处理来处理它。从文档中:
如果数据可用于其中包含的所有字段,则格式化程序将格式化。如果字符串匹配,格式化程序将解析,否则不返回错误。
这意味着您不必处理多个例外情况。
这是一个来自真实代码库的示例,我必须在其中进行此处理:
def dtf: DateTimeFormatter =
new DateTimeFormatterBuilder()
.appendOptional(DateTimeFormatter.ofPattern("dd/MM/yy"))
.appendOptional(DateTimeFormatter.ofPattern("dd/MM/yyyy"))
.toFormatter()
这里有两个单元测试(在 ScalaTest 中)展示了用法:
"Short form is parsed" in {
assert(LocalDate.parse("28/08/20", dtf) == LocalDate.of(2020, 8, 28))
}
"Long form is parsed" in {
assert(LocalDate.parse("02/10/2020", dtf) == LocalDate.of(2020, 10, 2))
}
推荐阅读
- python - Web Scraping:试图检索所有歌曲,但它只返回一首歌词
- python - 用于识别 NumPy 数组中的数组的方法
- android - React-native Axios 在 iOS 中工作,但在 Android 中不调用
- keras - 增强 keras 模型输出并作为第二个模型的输入
- php - 我在 Laravel 中的搜索功能有问题
- python - python 和 celery:覆盖硬超时以与 gevent 池一起使用
- azure-cognitive-search - 如何获取至少包含一个完整单词的 Azure 搜索结果?
- r - 带有 qwraps2 summary_table 函数的“错误:`x` 必须是公式”
- r - R和bioconductor,为什么getGEO()函数会产生错误“open.connection(x,“rb”)中的错误:HTTP错误404?
- python - 在后台更新 tkinter 窗口