我想将MM-dd格式的字符串解析为java date。由于未指定年份,因此解析日期应为当前年份。应该只解析有效的日期字符串,因此我应该在setLenient(false)
中使用SimpleDateFormat
。
public static Date parseDate(String ds) throws ParseException {
SimpleDateFormat df = new SimpleDateFormat("MM-dd");
df.setLenient(false);
Date d = df.parse(ds);
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
cal.setTime(d);
cal.set(Calendar.YEAR, year);
return cal.getTime();
}
这似乎很有效,直到我传递参数“ 02-29”。今年(2012)是leap年,2012-02-29是有效日期,应该成功解析“ 02-29”。
[我发现,当我没有在SimpleDateFormat
中指定年份部分时,它将解析为1970年。而1970年不是a年,则“ 02-29”将无法解析。因此,解析日期到1970年并在解析策略后设置当前年份并不完美。
用Java解析MM-dd格式的字符串到日期(日期应该设置为当前年份)的最佳方法是什么?
PS1:我搜索了此主题,并在此站点中找到许多问题和答案,但是找不到满意的答案。PS2:df.setLenient(false);
很重要,因为只有有效的日期字符串才能成功解析。无效的日期字符串,例如“ 01-32”,“ 02-30”等,不应被解析。
提前感谢。
Date d = df.parse(ds + "-" + year);
public static Date parseDate(String ds) throws ParseException {
SimpleDateFormat fullFormat = new SimpleDateFormat("MM-dd-yyyy");
fullFormat.setLenient(false);
try {
return fullFormat.parse(ds);
} catch (ParseException e) {}
// Full format unsuccessful. Attempt short format.
SimpleDateFormat shortFormat = new SimpleDateFormat("MM-dd");
shortFormat.setLenient(false);
Date d = shortFormat.parse(ds);
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
cal.setTime(d);
cal.set(Calendar.YEAR, year);
return cal.getTime();
}
奖励:如果出于某种原因需要“全部捕获”解析器,请定义一堆非宽容日期格式,并逐一检查。注意顺序很重要;第一个匹配的将返回。如果要设置默认年份,则必须更进一步,并检查输入中是否引用了默认的1970年:
public static Date parseDate(String ds) throws ParseException {
Calendar cal = Calendar.getInstance();
int currentYear = cal.get(Calendar.YEAR);
for (DateFormat knownFormat : knownFormats) {
try {
Date d = knownFormat.parse(ds);
cal.setTime(d);
if (cal.get(Calendar.YEAR) == 1970 && !ds.contains("70")) {
cal.set(Calendar.YEAR, currentYear);
}
return cal.getTime();
} catch (ParseException e) {}
}
throw new ParseException("Unknown date format for String: " + ds);
}
MonthDay
.parse (
"--" + "02-29"
)
java.time
MonthDay
每月以适当命名的MonthDay
类表示。
MonthDay
,其中第一个破折号是年份的占位符。默认情况下,java.time类中使用ISO 8601格式来解析/生成字符串。
您的输入几乎合规。您可以使用--MM-DD
对象定义格式设置模式。但是我只需在输入上添加DateTimeFormatter
。
--
然后默认解析。
String input = "02-29" ;
String inputModified = "--" + input ;
参见此MonthDay md = MonthDay.parse( inputModified ) ;
。
md.toString():--02-29
Le年请注意,您的code run live at IdeOne.com问题已消失。通过使用真正代表一个月而不是一瞬间的适当类型,我们不必担心leap年。
要获取该月日的日期,只需调用leap year以获取
MonthDay::atYear
对象。通过一年数。
MonthDay::atYear
leapYear2012.toString():2012-02-29本年度获得当年的日期可能会令您感到意外。请注意,获取当前年份需要获取当前日期。并且获取
当前日期需要一个时区。
时区对于确定日期至关重要。在任何给定时刻,日期都会在全球范围内变化。例如,在
如果未指定时区,则JVM隐式应用其当前的默认时区。该默认值可能在运行时(!)期间为Paris France,因此您的结果可能会有所不同。最好将您的期望/期望时区明确指定为参数。如果要使用JVM的当前默认时区,请致电Montréal Québec来表明您的意图。如果紧急,请与用户确认区域。LocalDate
中午夜之后的几分钟是新的一天,而在LocalDate leapYear2012 = md.atYear( 2012 ) ;
中仍是“昨天”。以change at any moment的格式指定
ZoneId.systemDefault()
,例如proper time zone name,Continent/Region
或America/Montreal
。切勿使用2-4个字母的缩写,例如Africa/Casablanca
或Pacific/Auckland
,因为它们是真正的时区,不是标准化的,甚至不是唯一的(!)。
EST
就我们而言,我们只关心年份。因此,我们可以使用IST
类而不是ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
。但是对于时区也是如此。如果当前时刻恰好是除夕/天转换,那么该年份将在全球各地按时区变化。Year
currentYear.toString():2019-02-28
关于该leap年以上结果的通知会自动处理。 2019年2月29日没有,因此java.time调整为28日。关于java.time
LocalDate
框架内置于Java 8及更高版本中。这些类取代了麻烦的旧ZoneId z = ZoneId.of( "Africa/Tunis" ) ; Year y = Year.now( z ) ; LocalDate currentYear = md.atYear( y.getValue() ) ;
日期时间类,例如java.time,legacy和java.util.Date
。要了解更多信息,请参见
java.util.Date
。并在Stack Overflow中搜索许多示例和说明。规格为Calendar
。Calendar
项目现在位于SimpleDateFormat
中,建议迁移到SimpleDateFormat
类。您可以直接与数据库交换
java.time
对象。使用兼容Oracle Tutorial或更高版本的JSR 310。不需要字符串,不需要Joda-Time类。从哪里获取java.time类?
maintenance mode,java.time,JDBC driver,JDBC 4.2和更高版本-具有捆绑实施的标准Java API的一部分。
Java 9添加了一些次要功能和修复。
java.sql.*
和Java SE 8