java 4位数_java – 如何解析只有4位数的年份

我正在使用Joda-Time解析这样的年代:

private DateTime attemptParse(String pattern, String date) {

DateTimeFormatter parser = DateTimeFormat.forPattern(pattern).withLocale(Locale.ENGLISH);

DateTime parsedDateTime = parser.parseLocalDateTime(date).toDateTime(WET);

return parsedDateTime;

}

我正在尝试解析多种格式:“yyyy-MM-dd”,“yyyy-MMM-dd”,“yyyy MMM dd-dd”,“yyyy MMM”,(等),“yyyy”.当一个人不工作时,我会尝试下一个.

当字符串确实只有4位数时(例如:“2016”),它就像一个魅力.问题是我有时会收到这样的信息:“201400”.而Joda-Time将其与“yyyy”模式相匹配,并返回201400年的日期.

我想避免丑陋如果检查年份> 9999.使用Joda-Time有什么办法吗?

解决方法:

要解析多种格式,您可以创建许多DateTimeParser实例并将所有实例连接在一个格式化程序中(而不是一个接一个地尝试).

这将需要一个DateTimeFormatterBuilder,它也将用于在输入中强制执行特定数量的数字(遗憾的是,没有办法像使用DateTimeFormat.forPattern()那样强制执行特定数量的数字).

首先,您创建了许多org.joda.time.format.DateTimeParser实例(每个可能的模式一个):

// only yyyy

DateTimeParser p1 = new DateTimeFormatterBuilder()

// year with exactly 4 digits

.appendYear(4, 4).toParser();

// yyyy-MM-dd

DateTimeParser p2 = new DateTimeFormatterBuilder()

// year with exactly 4 digits

.appendYear(4, 4)

// rest of the pattern

.appendPattern("-MM-dd").toParser();

// yyyy MMM

DateTimeParser p3 = new DateTimeFormatterBuilder()

// year with exactly 4 digits

.appendYear(4, 4)

// rest of the pattern

.appendPattern(" MMM").toParser();

然后创建一个包含所有这些模式的数组,并用它创建一个DateTimeFormatter:

// create array with all the possible patterns

DateTimeParser[] possiblePatterns = new DateTimeParser[] { p1, p2, p3 };

DateTimeFormatter parser = new DateTimeFormatterBuilder()

// append all the possible patterns

.append(null, possiblePatterns)

// use the locale you want (in case of month names and other locale sensitive data)

.toFormatter().withLocale(Locale.ENGLISH);

我也使用了Locale.ENGLISH(因为你也在你的问题代码中使用它).此区域设置表示月份名称将为英语(因此MMM可以解析Jan和Sep等值).有了这个,你可以解析输入:

System.out.println(parser.parseLocalDateTime("2014")); // OK

System.out.println(parser.parseLocalDateTime("201400")); // exception

System.out.println(parser.parseLocalDateTime("2014-10-10")); // OK

System.out.println(parser.parseLocalDateTime("201400-10-10")); // exception

System.out.println(parser.parseLocalDateTime("2014 Jul")); // OK

System.out.println(parser.parseLocalDateTime("201400 Jul")); // exception

当年是2014年,代码工作正常.当它是201400时,它会抛出一个java.lang.IllegalArgumentException,例如:

java.lang.IllegalArgumentException: Invalid format: “201400” is malformed at “00”

DateTimeFormatter是不可变且线程安全的,因此每次调用验证方法时都不需要创建它.您可以在方法之外创建它(例如在静态最终字段中).

这比每次执行验证时创建一个格式化程序更好,并在发生异常时转到下一个格式化程序.创建的格式化程序已经在内部执行,转到下一个模式,直到找到一个有效的模式(或者如果所有模式都失败则抛出异常).

Java新的日期/时间API

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

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

如果您使用的是Java 6或7,则可以使用ThreeTen Backport,它是Java 8新日期/时间类的优秀后端.而对于Android,你还需要ThreeTenABP(更多关于如何使用它here).

以下代码适用于两者.

唯一的区别是包名称(在Java 8中是java.time,在ThreeTen Backport(或Android的ThreeTenABP)中是org.threeten.bp),但类和方法名称是相同的.

这个新API比以前的API严格得多,因此格式化程序只能使用确切的位数(请注意,某些类与Joda-Time非常相似):

// 4 digits in year

DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy", Locale.ENGLISH);

fmt.parse("2014"); // OK

fmt.parse("201400"); // exception

fmt.parse("201"); // exception

此代码适用于2014年,但是对于201400或201(或任何其他没有正好4位数的值),它会引发异常:

java.time.format.DateTimeParseException: Text ‘201400’ could not be parsed at index 0

有了这个,您的验证代码可以使用字符串数组.

只有一个细节:当解析为日期时,Joda-Time在输入没有某些字段时设置默认值(例如月份变为1月,日变为1,小时/分钟/秒设置为零等).

如果您只是验证输入,那么您不需要返回任何内容.只需检查是否抛出异常,您就会知道输入是否有效.

但是,如果您只需要年份值,则可以使用Year class:

DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy", Locale.ENGLISH);

System.out.println(Year.parse("2014", parser)); // ok

System.out.println(Year.parse("201400", parser)); // exception

如果您希望年份值为int:

Year year = Year.parse("2014", parser);

int yearValue = year.getValue(); // 2014

但是如果你想获得一个日期对象,你需要手动设置默认值 – 新API非常严格,不要自动设置这些值.在这种情况下,您必须使用DateTimeFormatterBuilder设置默认值.

我还将它解析为LocalDateTime,就像示例:

DateTimeFormatter fmt = new DateTimeFormatterBuilder()

// string pattern

.appendPattern("yyyy")

// default month is January

.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)

// default day is 1

.parseDefaulting(ChronoField.DAY_OF_MONTH, 1)

// default hour is zero

.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)

// default minute is zero

.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)

// set locale

.toFormatter(Locale.ENGLISH);

// create LocalDateTime

System.out.println(LocalDateTime.parse("2014", fmt)); // 2014-01-01T00:00

System.out.println(LocalDateTime.parse("201400", fmt)); // exception

您可以选择所需的任何值作为字段的默认值,并使用任何new available date types.

标签:java,jodatime,date-parsing

来源: https://codeday.me/bug/20190622/1264154.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值