我有简单的测试用例:
public static void main(String[] args) {
String pattern = "yyyy-MM-dd HH:mm:ss.SSS";
String date = "2017-01-15 15:15:15.5";
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
FastDateFormat fastDateFormat = FastDateFormat.getInstance(pattern);
try {
System.out.println("SFD: " + simpleDateFormat.parse(date));
}catch (Exception e) {
System.err.println("SDF failed");
}
try {
System.out.println("DTF: " + dateTimeFormatter.parse(date));
}catch (Exception e) {
System.err.println("DTF failed");
}
try {
System.out.println("FDF: " + fastDateFormat.parse(date));
}catch (Exception e) {
System.err.println("FDF failed");
}
}
输出是这样的:
SFD: Thu Jan 15 15:15:15 CET 1970
DTF failed
FDF: Thu Jan 15 15:15:15 CET 1970
根据结果,Java的8 DateTimeFormatter比SimpleDateFormat更严格。我的问题是为什么以及在这种情况下,接受.S
作为millis或.SSS
的两个日期的最佳方法是什么,比如使用try / catch多次解析?
答案 0 :(得分:3)
SimpleDateFormat
默认情况下不严格,因为默认情况下属性lenient
为true
。但是您可以将属性lenient
设置为false以使其严格。
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
simpleDateFormat.setLenient(false);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
try {
System.out.println("SFD: " + simpleDateFormat.parse(date));
} catch (Exception e) {
System.err.println("SDF failed");
}
try {
System.out.println("DTF: " + dateTimeFormatter.parse(date));
} catch (Exception e) {
System.err.println("DTF failed");
}
结果将是
SDF failed
DTF failed
请参阅DateFormat.parse(String, ParsePosition)
默认情况下,解析是宽松的:如果输入不是此对象的格式方法使用的形式,但仍可以解析为日期,则解析成功。客户可以通过调用setLenient(false)坚持严格遵守格式。
答案 1 :(得分:2)
你基本上问为什么SimpleDateFormat
接受一个数字毫秒的值,当模式显示" .SSS"。
原因在于SimpleDateFormat
的javadoc:
模式字母通常会重复,因为它们的数字决定了确切的呈现方式:
...
数字:对于格式化,模式字母的数量是最小位数,较短的数字是零填充到此数量。对于解析,忽略模式字母的数量,除非需要分隔两个相邻的字段。
显然,您可以通过拨打setLenient(false)
来更改此设置。但是,javadocs没有具体说明宽大的实际效果。
相比之下,DateTimeFormatter
的javadoc简单地说"模式字母的数量决定格式",格式化和解析没有区别。
为什么他们不一样?您需要询问设计DateTimeFormatter
API的人员,但我想是设计师考虑了{em> ad hoc 和SimpleDateFormat
(默认)宽松解析的未指定性质模式是有害的。
如何让DateTimeFormatter
接受一位或三位数毫秒值的日期?
一种方法是使用DateTimeFormatterBuilder
创建格式化程序。这允许您为格式中的任何字段指定最小和最大宽度。