Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java DateFormat.parse(字符串)如何处理非日期尾随文本?_Java_Date - Fatal编程技术网

Java DateFormat.parse(字符串)如何处理非日期尾随文本?

Java DateFormat.parse(字符串)如何处理非日期尾随文本?,java,date,Java,Date,如果DateFormat类的Parse方法成功解析字符串开头的日期,则该方法将忽略尾随文本 API是回避的: 解析给定字符串开头的文本以生成日期。 该方法不能使用给定字符串的整个文本 我认为“可能”的意思是——“如果尾随文本存在并且不是日期的一部分(不能解释为这样)”。但看起来这个“五月”更不可预测 给定 此操作不正确(意外): 虽然这工作正常(如预期): 如果其余解析文本是数字,则似乎总是无法正确解析(给出不同的错误结果): 现在,setLenient()的行为如下: 如果(correct)d

如果
DateFormat
类的Parse方法成功解析字符串开头的日期,则该方法将忽略尾随文本

API是回避的:

解析给定字符串开头的文本以生成日期。 该方法不能使用给定字符串的整个文本

我认为“可能”的意思是——“如果尾随文本存在并且不是日期的一部分(不能解释为这样)”。但看起来这个“五月”更不可预测

给定

此操作不正确(意外):

虽然这工作正常(如预期):

如果其余解析文本是数字,则似乎总是无法正确解析(给出不同的错误结果):

现在,
setLenient()
的行为如下:

  • 如果(correct)date后跟空格或字母,则setLenient()设置没有任何区别。对setLenient(真/假)和setLenient都正确解析了所有内容,没有异常
  • 但是如果(正确的)日期后面紧跟着数字,那么setLenient()确实会产生(意外的)差异:默认值(true)不会产生异常和错误的(!)解析结果,但是setLenient(false)会导致
    ParseException:Unparseable date:“2019-12-111”
    ,这也很奇怪(日期是正确的,API承诺忽略尾随文本)
  • Date parse(String-source,ParsePosition-pos)
    在上述所有情况下(包括对setLenient的反应)的行为与
    Date parse(String-source)
    的行为完全相同,只有一个(也是预期的)异常,其中一个arg parse()抛出ParseException,而这两个arg parse()返回null(这是它对要解析的字符串开头不正确的日期格式的反应)

    还值得注意的是,在调用
    mydateFormat.parse(“2019-12-11234”,pos)
    (使用setLenient(true)),之后,
    pos.getIndex()
    返回13-哪个点“超出”234部分,这意味着它将234部分视为
    新SimpleDataFormat(“yyyyy-MM-dd”)中“yyyyy-MM-dd”的“-”部分


    另外,我知道这些都是过时的日期/时间API,我更喜欢java.time而不是日期/日历/日期格式等,但它仍然大量存在于遗留代码中,以支持不可重构的情况。

    当您将islenent设置为true并添加额外的数字时,格式化程序将尝试根据给定的值计算新的日期因此,
    df.parse(“2019-12-1189”)
    将被解析为2019-12-01+1189天(1189/365=3.26),因此3月3日星期五00:00:00 MSK 2023看起来是正确的结果(我不知道这里的确切数学)

    11234年也是如此,大约增加了30年

    您也可以在2019-12-32和2019-13-01中尝试此功能,这两个版本都将转换为2020-01-01

  • 尽管你自己已经说过了,但我想重申,不要使用
    SimpleDateFormat
    。这是出了名的麻烦和过时
  • 您对文档的引用需要与文档中的至少一点结合起来阅读。基本上,
    SimpleDateFormat
    无法完成您希望它完成的任务
  • java.time 输出为:

    2019-12-11

    我认为这是您想要的结果。
    2019-12-11
    已被解析为日期,
    2
    已被忽略为尾随文本,而不是日期的一部分

    使用SimpleDataFormat无法完成此操作 为了说明我的观点,我使用了一个不同的例子:

        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        df.setLenient(false);
        System.out.println(df.parse("2019-12-013"));
    
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    System.out.println(df.parse("2019-12-112"));
    
    2019年东部时间12月13日星期五00:00:00

    此行为已记录在案。除了您的报价,我们还需要阅读:

    • Number:…对于解析,除非需要分隔两个相邻字段,否则将忽略模式字母的数量
    因此,在我的示例中,由于
    dd
    之后没有任何相邻字段,因此我们无法说服
    SimpleDateFormat
    013
    作为数字13以外的任何内容读取

    链接
    • 解释如何使用java.time

    SimpleDateFormat
    在内部使用
    NumberFormat
    的(特定于区域设置)实例来解析给定的日期。在我的例子中,它是
    DecimalFormat
    的实例

    调试
    SimpleDataFormat
    揭示了其中的关键部分是:

    if (obeyCount) {
        if ((start+count) > text.length()) {
            break parsing;
        }
        number = numberFormat.parse(text.substring(0, start+count), pos);
    } else {
        number = numberFormat.parse(text, pos);
    }
    
    给出您的第一个示例:

        DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        df.setLenient(false);
        System.out.println(df.parse("2019-12-013"));
    
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    System.out.println(df.parse("2019-12-112"));
    
    内部设置的
    submissioncount
    false
    ,因此始终对文本的整个部分调用
    numberFormat.parse()
    。此示例也会发生同样的情况:

    DateFormat df = new SimpleDateFormat("yyyyMMdd");
    System.out.println(df.parse("201912112"));
    

    我至少把后一个例子看作是一个可能的bug。但是设置<代码> Obje> < /C> >的逻辑是如此复杂,以至于我觉得它不值得深入探索(因为这个API有点过时)。


    还要注意的是,
    setLenient(boolean)
    不修改内部的
    NumberFormat
    解析器,而只修改解析完成后发挥作用的
    Calendar
    实例。其余内容,请参阅Joakim Danielson的答案。

    尝试调用
    setLenient(false)
    ,请参阅:我建议您不要使用
    SimpleDateFormat
    。该类是出了名的麻烦和过时很久的类。相反,请使用
    DateTimeFormatter
    和来自的其他类。我认为问题更多的是如何强制
    SimpleDateFormat
    遵守提供的模式,即使输入的是尾随数字,正如-显然-
    setLenient(false)
    没有。是的,这个问题似乎已经更新了几次。回答这个问题时,我可能已经加载了一个旧版本
    if (obeyCount) {
        if ((start+count) > text.length()) {
            break parsing;
        }
        number = numberFormat.parse(text.substring(0, start+count), pos);
    } else {
        number = numberFormat.parse(text, pos);
    }
    
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    System.out.println(df.parse("2019-12-112"));
    
    DateFormat df = new SimpleDateFormat("yyyyMMdd");
    System.out.println(df.parse("201912112"));