SimpleDateFormat 2年的日期问题

时间:2013-08-08 13:51:38

标签: java simpledateformat

我试图理解两件事:

  1. 为什么以下代码不会抛出异常(因为SimpleDateFormat不宽松)
  2. 它没有抛出异常,但为什么它将年份解析为0013(而不是using the rules here从今天开始的+ 80: - 20年规则)
  3. 这是代码

    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.Date;
    
    public class TestDate {
        public static void main(String[] args) throws Exception {
            SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy");
            format.setLenient(false);
            Date date = format.parse("01/01/13"); // Since this only has a 2 digit year, I would expect an exception to be thrown
    
            System.out.println(date); // Prints Sun Jan 01 00:00:00 GMT 13
    
            Calendar cal = Calendar.getInstance();
            cal.setTime(date);
    
            System.out.println(cal.get(Calendar.YEAR)); // Prints 13
        }
    }
    

    如果它有所作为,我在Ubuntu上使用java 1.6.0_38-b05

4 个答案:

答案 0 :(得分:2)

问题1。这是Why Does Java's SimpleDateFormat parse this的部分副本。问题的第二个答案很好地回答了这个问题。关键在于:

数字:对于解析,忽略模式字母的数量,除非需要分隔两个相邻的字段。 年份:在解析过程中,只有包含正好两位数字的字符串才会被解析为默认世纪。字面上解释任何其他数字字符串,例如一位数字符串,三位或更多位数字符串,或不是所有数字的两位数字符串(例如,“ - 1”)。所以使用相同的模式解析“01/02/3”或“01/02/003”

问题2。仔细观察:您的输入格式与传递给该功能的格式不同。

new SimpleDateFormat("dd/MM/yyyy");

VS

format.parse("01/01/13");

解析为01/01/2013或使用日期'dd/MM/yy'

答案 1 :(得分:2)

SimpleDateFormat API:

对于解析,如果模式字母的数量大于2,则无论数字位数如何,都按字面解释年份。所以使用模式" MM / dd / yyyy"," 01/11/12"解析到1月11日,12 A.D。

对于lenient,当它被设置为false parse时会引发无效日期的异常,例如01/32/12,而在宽松模式下,此日期被视为02/01/12。 SimpleDateFormat在内部使用Calendar,可以在Calendar API中找到有关宽大的详细信息。

答案 2 :(得分:1)

根据JDK 1.6的SimpleDateFormat javadoc

  

对于解析,除非是,否则忽略模式字母的数量   需要将两个相邻的区域分开。

查看完成工作的方法的源代码SimpleDateFormat.parse(String, ParsePosition),确认了这一点。如果模式没有分隔符(如“yyyyMMdd”),则变量obeyCount为true,否则为false。使用您的模式,解析器会查找由2个分隔符分隔的3个数字,而不关心每个位置的位数。

您的问题的答案:

  1. Lenient不是使用分隔符的因素。
  2. 你没有打电话给SimpleDateFormat.set2DigitYearStart那么为什么代码会做你没告诉它做的事情呢?

答案 3 :(得分:1)

java.time

使用java.time(现代的Java日期和时间API),您所期望的异常肯定会发生:

    DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
    String strToParse = "01/01/13";
    LocalDate date = LocalDate.parse(strToParse, dateFormatter);

结果:

Exception in thread "main" java.time.format.DateTimeParseException: Text '01/01/13' could not be parsed at index 6
  at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
  at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
  at java.base/java.time.LocalDate.parse(LocalDate.java:428)

如果向右滚动,您将看到异常消息中提到“无法在索引6处解析”。字符串中的索引6是两位数字所在的年份所在的位置,预期是四位数。

将近7年前问这个问题时,可以使用SimpleDateFormatDate。它们的设计总是很差,在被问到问题7个月后就更换了它们,因此现在认为它们已经过时了。我热烈建议改用java.time。

链接

Oracle tutorial: Date Time解释了如何使用java.time。