das*_*eks 4 java parsing date simpledateformat
我正在尝试解析日期字符串,该字符串可以具有不同格式的树.即使String不应该与第二个模式匹配,它也会以某种方式返回错误的日期.
那是我的代码:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Start {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
try{
System.out.println(sdf.format(parseDate("2013-01-31")));
} catch(ParseException ex){
System.out.println("Unable to parse");
}
}
public static Date parseDate(String dateString) throws ParseException{
SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy");
SimpleDateFormat sdf2 = new SimpleDateFormat("dd-MM-yyyy");
SimpleDateFormat sdf3 = new SimpleDateFormat("yyyy-MM-dd");
Date parsedDate;
try {
parsedDate = sdf.parse(dateString);
} catch (ParseException ex) {
try{
parsedDate = sdf2.parse(dateString);
} catch (ParseException ex2){
parsedDate = sdf3.parse(dateString);
}
}
return parsedDate;
}
}
Run Code Online (Sandbox Code Playgroud)
通过输入2013-01-31我得到输出05.07.0036.
如果我试图解析31-01-2013或31.01.2013我得到31.01.2013预期.
我认识到如果我设置这样的模式,程序将给我完全相同的输出:
SimpleDateFormat sdf = new SimpleDateFormat("d.M.y");
SimpleDateFormat sdf2 = new SimpleDateFormat("d-M-y");
SimpleDateFormat sdf3 = new SimpleDateFormat("y-M-d");
Run Code Online (Sandbox Code Playgroud)
为什么它会忽略我模式中的字符数?
Ste*_*ell 12
SimpleDateFormat存在几个严重问题.默认的宽松设置可以产生垃圾答案,我想不出宽松有任何好处的情况.这绝不应该是默认设置.但禁用宽松只是解决方案的一部分.您仍然可能最终得到难以在测试中捕获的垃圾结果.有关示例,请参阅下面代码中的注释.
这是SimpleDateFormat的扩展,强制严格模式匹配.这应该是该类的默认行为.
import java.text.DateFormatSymbols;
import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
/**
* Extension of SimpleDateFormat that implements strict matching.
* parse(text) will only return a Date if text exactly matches the
* pattern.
*
* This is needed because SimpleDateFormat does not enforce strict
* matching. First there is the lenient setting, which is true
* by default. This allows text that does not match the pattern and
* garbage to be interpreted as valid date/time information. For example,
* parsing "2010-09-01" using the format "yyyyMMdd" yields the date
* 2009/12/09! Is this bizarre interpretation the ninth day of the
* zeroth month of 2010? If you are dealing with inputs that are not
* strictly formatted, you WILL get bad results. You can override lenient
* with setLenient(false), but this strangeness should not be the default.
*
* Second, setLenient(false) still does not strictly interpret the pattern.
* For example "2010/01/5" will match "yyyy/MM/dd". And data disagreement like
* "1999/2011" for the pattern "yyyy/yyyy" is tolerated (yielding 2011).
*
* Third, setLenient(false) still allows garbage after the pattern match.
* For example: "20100901" and "20100901andGarbage" will both match "yyyyMMdd".
*
* This class restricts this undesirable behavior, and makes parse() and
* format() functional inverses, which is what you would expect. Thus
* text.equals(format(parse(text))) when parse returns a non-null result.
*
* @author zobell
*
*/
public class StrictSimpleDateFormat extends SimpleDateFormat {
protected boolean strict = true;
public StrictSimpleDateFormat() {
super();
setStrict(true);
}
public StrictSimpleDateFormat(String pattern) {
super(pattern);
setStrict(true);
}
public StrictSimpleDateFormat(String pattern, DateFormatSymbols formatSymbols) {
super(pattern, formatSymbols);
setStrict(true);
}
public StrictSimpleDateFormat(String pattern, Locale locale) {
super(pattern, locale);
setStrict(true);
}
/**
* Set the strict setting. If strict == true (the default)
* then parsing requires an exact match to the pattern. Setting
* strict = false will tolerate text after the pattern match.
* @param strict
*/
public void setStrict(boolean strict) {
this.strict = strict;
// strict with lenient does not make sense. Really lenient does
// not make sense in any case.
if (strict)
setLenient(false);
}
public boolean getStrict() {
return strict;
}
/**
* Parse text to a Date. Exact match of the pattern is required.
* Parse and format are now inverse functions, so this is
* required to be true for valid text date information:
* text.equals(format(parse(text))
* @param text
* @param pos
* @return
*/
@Override
public Date parse(String text, ParsePosition pos) {
int posIndex = pos.getIndex();
Date d = super.parse(text, pos);
if (strict && d != null) {
String format = this.format(d);
if (posIndex + format.length() != text.length() ||
!text.endsWith(format)) {
d = null; // Not exact match
}
}
return d;
}
}
Run Code Online (Sandbox Code Playgroud)