SimpleDateFormat与2年日期的问题

问题描述 投票:4回答:4

我想了解两件事。

  1. 为什么下面的代码不抛出一个异常(因为... ... SimpleDateFormat 不宽松)
  2. 它没有抛出一个异常,但为什么它将年份解析为0013(而非 照此办理 (+80:-20年后的规则)

下面是代码

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。

java simpledateformat
4个回答
3
投票

SimpleDateFormat API。

对于解析来说,如果模式字母的数量超过2个,那么无论数字多少,年份都会被按字面解释。所以使用模式 "MMddyyyy","011112 "解析为公元12年1月11日。

至于lenient,当它被设置为false时,解析会对无效的日期抛出异常,例如013212,而在lenient模式下,这个日期会被视为020112。SimpleDateFormat在内部使用了Calendar,关于宽大的细节可以在Calendar API中找到。


3
投票

问题1. 这是一个部分重复的 为什么Java的SimpleDateFormat解析这个. 问题的第二个答案很好地回答了这个问题。它的关键是这样的。

数字: 对于解析来说,模式字母的数量是被忽略的,除非需要将两个相邻的字段分开。年:在解析过程中,只有字符串才会被忽略,除非需要分隔两个相邻的字段。 在解析过程中,只有完全由两位数字组成的字符串[...]才会被解析为默认的世纪。任何其他数字字符串,如一位数的字符串,三位数或更多的数字字符串,或不是全部数字的两位数字符串(例如,"-1"),都会按字面解释。因此,"01023 "或 "0102003 "都会被解析,使用相同的模式。

问题2.你的输入格式和你传递给函数的格式不一样。 仔细观察:你的输入格式与你传递给函数的格式是不一样的。

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

与。

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

要么解析为 01/01/2013 或使用日期为at 'dd/MM/yy'.


2
投票

根据《公约》的规定。SimpleDateFormat javadoc 对于JDK 1.6来说,模式字母的数量会被忽略。

对于解析,模式字母的数量被忽略,除非需要将两个相邻的字段分开。

看一下做这个工作的方法的源码。SimpleDateFormat.parse(String, ParsePosition)证实了这一点。 有一个变量 obeyCount 如果模式没有定界符,比如 "yyyyMMdd",则为真,否则为假。对于您的模式,解析器会查找由2个定界符分隔的3个数字,而不关心每个位置上的数字数量。

您的问题的答案。

  1. Lenient 当使用定界符时,不是一个因素。
  2. 你没有调用 SimpleDateFormat.set2DigitYearStart 那么为什么代码要做你没有告诉它做的事情呢?

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);

Result:

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代替。

链接

甲骨文教程。日期时间 解释如何使用java.time。

© www.soinside.com 2019 - 2024. All rights reserved.