如何使用Scala在DateTimeFormatter中传递多个Date格式

问题描述 投票:0回答:2

我有三种日期格式: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 scala date-parsing java-date
2个回答
0
投票

你不能同时使用格式化程序[yyyyMMdd]和[MMddyyyy]。我的想法是规范化,所以你有[yyyy-MM-dd]和[MM-dd-yyyy],而不是3种格式。

希望这有帮助

编辑:

如果你没有机会可以做这样的事情,但它不是很漂亮。

val formatter1 = DateTimeFormatter.ofPattern("[yyyy-MM-dd][MMddyyyy]")
val formatter2 = DateTimeFormatter.ofPattern("[yyyy-MM-dd][yyyyMMdd]")

val time = "20190529"

if (time.matches("2+\\d*")) LocalDate.parse(time,formatter2) else 
LocalDate.parse(time,formatter1)

0
投票

只有问题中的信息,这是不可能的。字符串10111213可以表示1211年12月13日或1213年10月11日。但是,假设你的日期总是在1300年之后,你很幸运,因为那时字符串的YYYY部分无法解析为MMDD因为这个月将是13或者更大,也就是说,无效。您可以使用它来确定哪种格式是正确的格式。

我会使用三个格式化程序并依次尝试它们:

private static final DateTimeFormatter[] DATE_FORMATTERS = {
        DateTimeFormatter.ofPattern("uuuuMMdd"),
        DateTimeFormatter.ofPattern("MMdduuuu"),
        DateTimeFormatter.ofPattern("uuuu-MM-dd")
};

有了这些只是做:

    String dateString = "20190529";

    LocalDate result = null;
    for (DateTimeFormatter df : DATE_FORMATTERS) {
        try {
            result = LocalDate.parse(dateString, df);
            break;
        } catch (DateTimeParseException dtpe) {
            // Ignore; try next formatter
        }
    }
    System.out.println("" + dateString + " was parsed to " + result);

输出是:

20190529被解析为2019-05-29

我们也尝试其他两种格式:

10062019被解析为2019-10-06

2019-06-20被解析为2019-06-20

我建议你添加一个空检查来捕获任何不可解析的日期字符串和一个范围检查解析日期,以便10111213不会作为有效的漏洞。例如:

    if (result == null) {
        System.out.println(dateString + " could not be parsed");
    }
    else if (result.isBefore(LocalDate.now(ZoneId.of("Asia/Aden")))) {
        System.out.println("Date should be in the future, was " + result);
    }

PS我在你的问题的第一句中假设一个拼写错误:

我有三种日期格式:YYYY-MM-DD,DDMMYYYY,MMDDYYYY这是我在Spark中传递日期格式以解析的方式。

中间格式应该是YYYYMMDD(否则你没有机会)。

© www.soinside.com 2019 - 2024. All rights reserved.