有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

具有2年日期的java SimpleDateFormat问题

我试图理解两件事:

  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


共 (4) 个答案

  1. # 1 楼答案

    根据JDK1.6的SimpleDateFormat javadoc

    For parsing, the number of pattern letters is ignored unless it's needed to separate two adjacent fields.

    查看执行该工作的方法的源代码SimpleDateFormat.parse(String, ParsePosition)可以证实这一点。如果模式没有分隔符,比如“yyyyMMdd”,则变量obeyCount为true,否则为false。根据您的模式,解析器查找由2个分隔符分隔的3个数字,而不关心每个位置的位数

    您的问题的答案如下:

    1. ^使用分隔符时,{}不是一个因素
    2. 你没有调用^{},那么为什么代码要做你没有告诉它做的事情呢
  2. # 2 楼答案

    SimpleDataFormat API:

    对于解析,如果模式字母的数量超过2,则不管数字的数量如何,都会按字面解释年份。因此,使用模式“MM/dd/yyyy”,“01/11/12”解析为公元12年1月11日

    至于lenient,当设置为false时,parse会抛出无效日期的异常,例如01/32/12,而在lenient模式下,该日期将被视为02/01/12。SimpleDataFormat在内部使用日历,有关宽大处理的详细信息可以在日历API中找到

  3. # 3 楼答案

    爪哇。时间

    使用java。时间、现代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。而是时间

    链接

    解释如何使用java。时间到了

  4. # 4 楼答案

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

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

    问题2仔细查看:输入格式与传递给函数的格式不同

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

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

    要么解析为01/01/2013,要么使用'dd/MM/yy'的日期