【问题标题】:Why Does Java's SimpleDateFormat parse this为什么 Java 的 SimpleDateFormat 会解析这个
【发布时间】:2011-04-06 10:01:33
【问题描述】:

您好,我使用自定义格式字符串设置了一个简单的日期格式: MMddyy

我给它下面的值来解析: 4 1 01

我认为它不应该因为空格而解析这个,但简单日期格式正在返回日期

0001 年 4 月 4 日

任何想法为什么?

【问题讨论】:

  • 建议使用 DateFormat 而不是 SimpleDateFormat,我建议您阅读 JavaDoc 以了解此行为。
  • SimpleDateFormat extends DateFormat 直接用SimpleDateFormat也没什么问题

标签: java date-format simpledateformat


【解决方案1】:

这是预期的行为 - 您告诉 DateFormat 对象需要一个 6 个字符的字符串表示日期,这就是您传入的内容。空格解析正常。但是,如果您使用“4x1x01”,则会出现错误。请注意,解析时,leniency 默认为 true,例如

DateFormat df = new SimpleDateFormat("MMddyy");
Date date = df.parse("4 1 01"); // runs successfully (as you know)

DateFormat df = new SimpleDateFormat("MMddyy");
Date date = df.parse("41 01"); // 5 character String - runs successfully

DateFormat df = new SimpleDateFormat("MMddyy");
df.setLenient(false);
Date date = df.parse("41 01"); // 5 character String - causes exception

DateFormat df = new SimpleDateFormat("MMddyy");
Date date = df.parse("999999"); // 6 character String - runs successfully

DateFormat df = new SimpleDateFormat("MMddyy");
df.setLenient(false);
Date date = df.parse("999999"); // 6 character String - causes exception

当 leniency 设置为 true(默认行为)时,解析会努力破译无效输入,例如31 天月份的第 35 天成为下个月的第 4 天。

【讨论】:

  • Lenient 设置为 false,我已将 SimpleDateFormats 2DigitYearStart 设置为 1950,但它仍将“4 1 01”视为 april first 0001
  • 好吧,我已经将 2digityearstart 设置为 1950 年 1 月 1 日,所以我希望它在规则之前使用 20 之后的 80 来确定 01 应该被视为 2001
  • 我认为它正在读取 1 之后的空格作为年份的第一个字符,因此它将年份视为 3 位数。您可以在 DateFormat 对象中包含空格,即“new SimpleDateFormat("MM dd yy") - 这应该可以工作。或者更好的是,完全从字符串中删除空格。
  • 你的权利,它将空格解释为年份的第一个字符。
  • 注意:DateFormat 并不真正需要 6 个字符。模式的大小(重复字母的数量)控制格式/解析,但它不是生成/预期文本的长度。它是仅在 formatting 数字表示(周、天、小时、...)中的最小长度,对于 parsing 表示它被“忽略,除非需要分隔相邻的字段。”
【解决方案2】:

对于解析,模式的大小(重复字符的数量)不是相应文本的预期大小。来自 javadoc,对于不同的相关演示类型:

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

空格会导致解析器停止解析实际的字段(尾随空格对数字无效)并从下一个开始。由于模式在这两个字段之间没有空格,因此它不会被消耗并且是第二个字段的一部分(前导空格有效)。所以得到的年份不是“正好两位数”,也不会被解析为默认世纪。

解析测试(lenient 设置为false):

FORMAT   TEXT     RESULT (ISO yyyy-MM-dd)
-------------------------------------------------
dddyy    01011    2011-01-10  
dddyy    10 11    0011-01-10  (year is 3 chars: " 11")
dddyy    10 1     0001-01-10  (year is 2 char but not 2 digits: " 1")

dddy     01011    2011-01-10  ("y" same as "yy")

dd yy    10 11    2011-01-10  (ok, whitespace is consumed, year: "11")

d/y      3/4      0004-01-03  (year is not 2 digits)
d/y      3/04     2004-01-03  

M/d/y    4/6/11   2011-04-06

【讨论】:

    【解决方案3】:

    2 位数的年份不明确 - 因此假设 0001 - 第一年将以 01 结束。您可以转换为 4 位数的年份 - 可能使用字符串操作吗?

    【讨论】:

    • 我只使用了两位数的年份,这样用户就不必输入特定的年份,如果他们只输入 2 位数字,我将 2 digitYearStart 设置为 1950,但我仍然得到 0001 作为年
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-14
    相关资源
    最近更新 更多