首先,我是一名学习Java的C#开发人员。我正在转换我用C#编写的一个程序作为练习,在解析从html表单提交的日期时遇到了问题。该表单以电子邮件的形式发送,java程序读取电子邮件并解析正文。我有一个下拉日历,让我的偷窥者从中选择日期,但总有一些混蛋不得不输入日历,把一切都搞砸了。目前我在我的代码中这样做:
public void SetDatePlayed(String datePlayed)
{
this.datePlayed = LocalDate.parse(datePlayed);
}
传入的datePlayed是一个字符串,通常格式为yyyy-MM-dd,但当然有人输入了3/7,而不是使用表单上的日历下拉菜单。this.datePlayed为LocalDate。在C#中,我最终会选择一个假设2020年为年份的日期——没问题。LocalDate真的希望它是yyyy-MM-dd格式,我不知道Java的最佳实践是什么。我整个上午都在谷歌上搜索,没有发现这是其他人的问题。我不在乎我是否使用LocalDate,但我确实需要它是一个日期数据类型,这样我以后就可以进行日期检查、排序、搜索等。
您可以使用DateTimeFormatterBuilder
和parseDefaulting()
来提供年份的默认值。
基于Sweeper的答案,可以这样做:
static LocalDate parseLoosely(String text) {
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
.appendPattern("[uuuu-M-d][M/d/uuuu][M/d]")
.parseDefaulting(ChronoField.YEAR, Year.now().getValue())
.toFormatter();
return LocalDate.parse(text, fmt);
}
警告:不要将格式化程序缓存在例如static
字段中,因为它会快照年份,如果程序可能在除夕夜运行(网络应用程序会这样做(,除非您添加逻辑使缓存在年份更改时自动刷新
测试
System.out.println(parseLoosely("2019-04-07"));
System.out.println(parseLoosely("2019-4-7"));
System.out.println(parseLoosely("4/7/2019"));
System.out.println(parseLoosely("4/7"));
输出
2019-04-07
2019-04-07
2019-04-07
2020-04-07
我对你的问题有两种可能的解释。我不确定是哪一个,所以我两个都回答。
如何将无年份格式的日期字符串(如
M/d
(3/7
((解析为LocalDate
?
你没有。根据定义,LocalDate
必须具有年、月和日。如果你只有一个月零一天的时间,那就是MonthDay
:
MonthDay md = MonthDay.parse("3/7", DateTimeFormatter.ofPattern("M/d"));
如果你想将当前年份添加到其中,你可以稍后进行:
LocalDate ld = md.atYear(Year.now(/*optionally insert time zone*/).getValue());
如何处理
yyyy-MM-dd
和M/d
模式?
这里有一种方法:创建一个识别两种模式的DateTimeFormatter
,将字符串解析为TemporalAccessor
,检查TemporalAccessor
是否支持"年份"字段:
TemporalAccessor ta = DateTimeFormatter.ofPattern("[M/d][yyyy-MM-dd]").parse("3/7");
if (ta.isSupported(ChronoField.YEAR_OF_ERA)) { // yyyy-MM-dd
LocalDate ld = LocalDate.from(ta);
} else if (ta.isSupported(ChronoField.MONTH_OF_YEAR)) { // M/d
MonthDay md = MonthDay.from(ta);
} else {
// user has entered an empty string, handle error...
}