java.text.SimpleDateFormat中的奇怪的行为,期望yyyyMMdd给出yyyy-MM-dd

当使用SimpleDateFormat解析字符串到日期时,我遇到了一个非常奇怪的行为.考虑以下单元测试:
@Test
public void testParse() throws ParseException
{
    DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");

    String dateStr = "2012-12-21";
    Date parsedDate = dateFormat.parse(dateStr);
    Calendar date = Calendar.getInstance();
    date.setTime(parsedDate);

    Assert.assertEquals(2012,date.get(Calendar.YEAR));
    Assert.assertEquals(11,date.get(Calendar.MONTH)); // yeah,Calendar sucks
    Assert.assertEquals(21,date.get(Calendar.DAY_OF_MONTH));
}

可以看出,上述代码中有一个有意的错误:SimpleDateFormat使用“yyyyMMdd”初始化,但要解析的字符串格式为“yyyy-MM-dd”.我会期望这样的事情会导致ParseException,或者至少在尽力而为的基础上正确解析.相反,由于某些奇怪的原因,日期被解析为2011-11-02.嗯?

这是不能接受的,因为一个单一的错误,而处理输入将导致一些完全意外/毁灭性的事情.在此期间切换到JodaTime,但要了解这里出了什么问题,那将是很好的.

解决方法

那么输入将被分为3个组件:年,月,日,你会得到月份= -12和日= -21(修正见下文).尝试解析2012/12/21,你会得到例外:)

编辑:摘自JavaDoc:

Month: If the number of pattern letters is 3 or more,the month is interpreted as text; otherwise,it is interpreted as a number.

编辑2:修正

看看SimpleDateFormat的源头,似乎2012-12-21实际上是分为:

year = "2012"
month = "-1"
day = "2-"

源注释表示a – 跟随一个数字可能表示一个负数(取决于语言环境)或是一个分隔符.在你的情况下,它似乎被视为一个分隔符,因此day =“2-”结果在day = 2,因此是11月的第二个.

相关文章

最近看了一下学习资料,感觉进制转换其实还是挺有意思的,尤...
/*HashSet 基本操作 * --set:元素是无序的,存入和取出顺序不...
/*list 基本操作 * * List a=new List(); * 增 * a.add(inde...
/* * 内部类 * */ 1 class OutClass{ 2 //定义外部类的成员变...
集合的操作Iterator、Collection、Set和HashSet关系Iterator...
接口中常量的修饰关键字:public,static,final(常量)函数...