DateTimeFormatterBuilder无法选择格式

麦克风

我已经配置了格式化程序:

public static final DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder()
        .append(forPattern("yyyy-MM-dd"))
        .append(forPattern("MM/dd/yy"))
        .append(forPattern("MMM dd, yyyy"))
        .toFormatter();

并尝试解析一个字符串 2017-08-29

LocalDate.parse(dt, DATE_FORMATTER).toDateTimeAtStartOfDay().toLocalDateTime()

我收到错误消息:

IllegalArgumentException:无效格式:“ 2017-08-29”太短

如果我将“ yyyy-MM-dd”保留为构建器中的唯一格式,则错误消失了。

我滥用API吗?如果第一个解析器失败,我希望解析器尝试另一种格式。

用户名

使用该append方法时,您正在创建一个格式化程序,该格式化程序一个接一个地接受所有三个模式(这三个都是必需的)。

如果要接受三种格式中的任何一种(只是其中一种),则必须appendOptional改用:

DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder()
    .appendOptional(DateTimeFormat.forPattern("yyyy-MM-dd").getParser())
    .appendOptional(DateTimeFormat.forPattern("MM/dd/yy").getParser())
    .appendOptional(DateTimeFormat.forPattern("MMM dd, yyyy").getParser())
    .toFormatter();

现在,您可以解析以下三种格式中的任何一种:

System.out.println(LocalDate.parse("2017-08-29", DATE_FORMATTER).toDateTimeAtStartOfDay().toLocalDateTime());
System.out.println(LocalDate.parse("08/29/17", DATE_FORMATTER).toDateTimeAtStartOfDay().toLocalDateTime());
System.out.println(LocalDate.parse("Aug 29, 2017", DATE_FORMATTER).toDateTimeAtStartOfDay().toLocalDateTime());

以上所有输出:

2017-08-29T00:00:00.000


请注意:第三个格式化程序使用的是月份简称(MMM),并且上面的代码假定系统的默认语言环境是英语(创建格式化程序时,默认情况下它使用与系统默认语言环境相对应的语言)。

但这可以在不通知的情况下进行更改,即使在运行时也是如此,因此最好java.util.Locale在格式化程序中指定一个

例如:如果月份名称始终为英文,则使用等效的语言环境:

DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder()
    .appendOptional(DateTimeFormat.forPattern("yyyy-MM-dd").getParser())
    .appendOptional(DateTimeFormat.forPattern("MM/dd/yy").getParser())
    .appendOptional(DateTimeFormat.forPattern("MMM dd, yyyy").getParser())
    // use English locale
    .toFormatter().withLocale(Locale.ENGLISH);

只需将语言环境更改为最适合您的需求的语言环境即可。查看javadoc以获取更多详细信息。


如评论中所提醒,您还可以创建一个解析器数组,并在中使用DateTimeFormatterBuilder

// array with all possible patterns
DateTimeParser[] parsers = new DateTimeParser[] {
    DateTimeFormat.forPattern("yyyy-MM-dd").getParser(),
    DateTimeFormat.forPattern("MM/dd/yy").getParser(),
    DateTimeFormat.forPattern("MMM dd, yyyy").getParser() };

DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder()
    // use array of all possible parsers
    .append(null, parsers)
    // use English locale
    .toFormatter().withLocale(Locale.ENGLISH);

这与上一个相同。


Java新的日期/时间API

Joda-Time处于维护模式,并且已被新的API取代,因此,我不建议使用它来启动新项目。即使在joda的网站上,它也说:“请注意,Joda-Time被认为是一个很大的“完成”项目。没有计划进行重大增强。如果使用Java SE 8,请迁移到java.time(JSR-310)。”

如果您不能(或不想)从Joda-Time迁移到新的API,则可以忽略此部分。

如果您使用的是Java 8,请考虑使用新的java.time API与旧的API相比,它更容易,更易于出错且更不易出错

如果您使用的是Java <= 7,则可以使用ThreeTen Backport,它是Java 8的新日期/时间类的绝佳反向端口对于Android来说,您还需要ThreeTenABP(更多有关如何在此处使用它的信息)。

下面的代码对两者都适用。唯一的区别是程序包名称(在Java 8中为java.time,在ThreeTen Backport(或Android的ThreeTenABP)中为org.threeten.bp),但类和方法的名称相同。

创建格式化程序并对其进行解析时,API非常相似:

DateTimeFormatter DATE_FORMATTER = new DateTimeFormatterBuilder()
    .appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
    .appendOptional(DateTimeFormatter.ofPattern("MM/dd/yy"))
    .appendOptional(DateTimeFormatter.ofPattern("MMM dd, yyyy"))
    // use English locale
    .toFormatter(Locale.ENGLISH);

System.out.println(LocalDate.parse("2017-08-29", DATE_FORMATTER).atStartOfDay());
System.out.println(LocalDate.parse("08/29/17", DATE_FORMATTER).atStartOfDay());
System.out.println(LocalDate.parse("Aug 29, 2017", DATE_FORMATTER).atStartOfDay());

以上所有操作均创建一个LocalDateTime,其值对应于2017-08-29T00:00

您还可以使用可选模式(以分隔[]):

DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("[yyyy-MM-dd][MM/dd/yy][MMM dd, yyyy]", Locale.ENGLISH);

这与上述相同。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章