Java 为什么 SimpleDateFormat("MM/dd/yyyy") 将日期解析为 10/20/20128?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18534343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 08:51:06  来源:igfitidea点击:

Why SimpleDateFormat("MM/dd/yyyy") parses date to 10/20/20128?

javadatesimpledateformatdate-parsing

提问by goe

I have this code:

我有这个代码:

  DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy");
  dateFormat.setLenient(false);
  Date date = dateFormat.parse("10/20/20128");

and I would expect the dateFormat.parse call to throw ParseException since the year I'm providing is 5 characters long instead of 4 like in the format I defined. But for some reason even with the lenient set to false this call returns a Date object of 10/20/20128.

我希望 dateFormat.parse 调用抛出 ParseException ,因为我提供的年份是 5 个字符,而不是我定义的格式中的 4 个字符。但出于某种原因,即使将 lenient 设置为 false,此调用也会返回 10/20/20128 的 Date 对象。

Why is that? It doesn't make much sense to me. Is there another setting to make it even more strict?

这是为什么?这对我来说没有多大意义。是否有其他设置使其更加严格?

采纳答案by Sajal Dutta

20128 is a valid year and Java hopes the world to live that long I guess.

20128 是一个有效的年份,我猜 Java 希望世界能活那么久。

if the number of pattern letters is more than 2, the year is interpreted literally, regardless of the number of digits.

如果模式字母的数量超过 2,则无论数字的位数如何,都按字面解释年份。

Reference.

参考。

If you want to validate if a date is in limit, you can define one and check-

如果您想验证日期是否在限制范围内,您可以定义一个并检查-

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
Date maxDate = sdf.parse("01/01/2099");  // This is the limit

if(someDate.after(maxDate)){            
    System.out.println("Invalid date");            
}

回答by Evgeniy Dorofeev

See java.text.SimpleDateFormatAPI, pattern letter y: For parsing, if the number of pattern letters is more than 2, the year is interpreted literally, regardless of the number of digits.

参见java.text.SimpleDateFormatAPI, pattern letter y: 解析,如果模式字母的个数大于2,则按字面解释年份,不考虑位数。

回答by Sotirios Delimanolis

See the javadoc

请参阅javadoc

Year: If the formatter's Calendar is the Gregorian calendar, the following rules are applied.

  • For formatting, if the number of pattern letters is 2, the year is truncated to 2 digits; otherwise it is interpreted as a number.
  • For parsing, if the number of pattern letters is more than 2, the year is interpreted literally, regardless of the number of digits. So using the pattern "MM/dd/yyyy", "01/11/12" parses to Jan 11, 12 A.D.
  • For parsing with the abbreviated year pattern ("y" or "yy"), SimpleDateFormat must interpret the abbreviated year relative to some century. It does this by adjusting dates to be within 80 years before and 20 years after the time the SimpleDateFormat instance is created. For example, using a pattern of "MM/dd/yy" and a SimpleDateFormat
    instance created on Jan 1, 1997, the string "01/11/12" would be
    interpreted as Jan 11, 2012 while the string "05/04/64" would be
    interpreted as May 4, 1964. During parsing, only strings consisting
    of exactly two digits, as defined by Character.isDigit(char), will be parsed into the default century. Any other numeric string, such as a
    one digit string, a three or more digit string, or a two digit string that isn't all digits (for example, "-1"), is interpreted literally.
    So "01/02/3" or "01/02/003" are parsed, using the same pattern, as
    Jan 2, 3 AD. Likewise, "01/02/-3" is parsed as Jan 2, 4 BC.
  • Otherwise, calendar system specific forms are applied. For both formatting and parsing, if the number of pattern letters is 4 or
    more, a calendar specific long form is used. Otherwise, a calendar
    specific short or abbreviated form is used.

年:如果格式化程序的日历是公历,则应用以下规则。

  • 对于格式化,如果模式字母的个数为2,则年份被截断为2位;否则它被解释为一个数字。
  • 对于解析,如果模式字母的数量大于 2,无论数字的位数如何,都按字面解释年份。因此,使用模式“MM/dd/yyyy”,“01/11/12”解析为公元 12 年 1 月 11 日
  • 为了使用缩写年份模式(“y”或“yy”)进行解析,SimpleDateFormat 必须解释相对于某个世纪的缩写年份。它通过将日期调整为在创建 SimpleDateFormat 实例之前 80 年和之后 20 年内实现这一点。例如,使用模式“MM/dd/yy”和
    创建于 1997 年 1 月 1 日的 SimpleDateFormat实例,字符串“01/11/12”将被
    解释为 2012 年 1 月 11 日,而字符串“05/04/ 64" 将被
    解释为 1964 年 5 月 4 日。在解析过程中,只有
    由 Character.isDigit(char) 定义的恰好由两位数字组成的字符串将被解析为默认世纪。任何其他数字字符串,例如
    一位数字字符串、三位或更多位数字字符串或不是所有数字的两位数字字符串(例如,“-1”)按字面解释。
    因此,“01/02/3”或“01/02/003”使用与
    公元 1 月 2 日、3 日相同的模式进行解析。同样,“01/02/-3”被解析为公元前 4 年 1 月 2 日。
  • 否则,将应用日历系统特定的表格。对于格式化和解析,如果模式字母的数量是 4 个或
    更多,则使用日历特定的长格式。否则,将使用日历
    特定的简短或缩写形式。

Therefore, it will read all the characters that come after the last /as the year.

因此,它将读取最后一个之后的所有字符/作为年份。

回答by Vishal Kumar

Using SimpleDateFormat in java, you can achieve a number of human readable formats. Consider this code snippet:

在java中使用SimpleDateFormat,可以实现多种人类可读的格式。考虑这个代码片段:

        Date curDate = new Date();

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

        String DateToStr = format.format(curDate);
        System.out.println(DateToStr);

        format = new SimpleDateFormat("dd-M-yyyy hh:mm:ss");
        DateToStr = format.format(curDate);
        System.out.println(DateToStr);

        format = new SimpleDateFormat("dd MMMM yyyy zzzz", Locale.ENGLISH);
        DateToStr = format.format(curDate);
        System.out.println(DateToStr);

        format = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z");
        DateToStr = format.format(curDate);
        System.out.println(DateToStr);

Look at the various outputs generated by the various formats:

查看各种格式生成的各种输出:

2014/05/11

2014/05/11

11-5-2014 11:11:51

11-5-2014 11:11:51

11 May 2014 Eastern European Summer Time

2014 年 5 月 11 日东欧夏令时

Sun, 11 May 2014 23:11:51 EEST

2014 年 5 月 11 日星期日 23:11:51 EEST

Feel free to modify the format string and you might get the desired result.

随意修改格式字符串,您可能会得到所需的结果。