【问题标题】:Java - SimpleDateFormat unexpected parsing behaviourJava - SimpleDateFormat 意外的解析行为
【发布时间】:2015-02-13 17:27:09
【问题描述】:

我正在读取文件 (.csv) 中的信息,该文件将在最终用户验证和批准后插入数据库。读取、验证文本文件并将其信息加载到包含用于检查数据是否已存在于数据库中的表单的列表中。

将字符串解析为日期时会出现问题。即使 SimpleDateFormat 的模式为“yyyy-MM-dd”,SimpleDateFormat.parse() 方法也会返回意外的日期格式。

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);

将加载的值解析到旅行对象:

travel.setDate( dateFormat.parse( form.getTravelDate() ));

在调试器中,表单将日期显示为:

"2012-12-12"

按预期阅读。但是解析后变成:

Wed Dec 12 00:00:00 CST 2012

我已经花了一整天的时间试图解决这个问题,但我现在没有想法。 Afaik 模式没问题,我尝试添加语言环境无济于事。

编辑:问题是当我需要使用 Hibernate 将值插入数据库时​​。不需要的格式也会最终显示在数据库中。

数据显示在 .jsp 页面中使用

 HttpServletRequest("table",travelList);

我不需要的日期格式显示在这里,而在过去这个问题从未发生过。最后,信息被发送到问题仍然存在的数据库。

【问题讨论】:

  • 解析(字符串到日期)与格式化(日期到字符串)没有任何关系。

标签: java spring date


【解决方案1】:

不,它“变成”java.util.Date 值。如果您随后通过调用Date.toString() 将其返回 转换为字符串,您应该查阅Date.toString() 文档以了解预期结果。

Date 中存储的值只是一个时间点 - 自 Unix 纪元以来的毫秒数。那里没有格式,没有时区等。它也不知道它只是一个日期值而不是日期和时间(Date 的命名是 许多不幸的之一API 的各个方面)。

在心理上将“解析操作的结果”与“如果我调用 toString" 时用于表示该结果的字符串值”分开是至关重要的。

我还建议您在解析日期时将 SimpleDateFormat 上的时区设置为 UTC - 这样您就知道您不能可能有任何模棱两可或跳过的时间领先难以预测的行为。 (当然,您需要知道您已经将日期解析为“UTC 日期的开始”并在其他地方适当地处理它。)

【讨论】:

  • 我知道如果我需要显示值是不同的,问题是我不需要显示它。 request.setAttribute("table",dateList) 是我在插入之前做的最后一件事,它也执行同样的问题。无论如何,我会尝试设置 UTC,看看结果如何。
  • @lhuezo:你说的“它也执行同样的问题”是什么意思?你还没有描述问题到底是什么——我们不知道request 是什么。如果您对特定的字符串表示感兴趣,则需要适当地格式化 Date 值。
  • 当插入操作发生时,日期以不希望的格式插入。关于请求,对不起。我的意思是 HttpServletRequest.setAttribute()。我会检查日期表示,希望是这样。
  • @lhuezo:servlet 与插入有什么关系?它被插入了什么?该请求属性是如何使用的?您在这里遗漏了 大量 的上下文。
  • 我认为没有必要深入讨论该部分,因为它严格来说是用于加载文件值的类上发生的问题。我的意思是信息不再需要任何操作,解析后它只显示在一个表格中并等待手动批准。但是表格显示的格式不正确,在数据审核通过时也会对数据库执行。
【解决方案2】:

在打印Date 时也需要使用格式化程序。

dateFormat.format( travel.getDate() );

当您使用DateFormat 解析String 时,您会得到一个完整的Date 对象,其中字符串中缺少的时间单位已初始化为零。在您的示例中,是小时、分钟和秒。

默认情况下,如果您不使用格式化程序,则会打印Date 的默认字符串表示形式(由其toString() 方法提供)。

【讨论】:

    【解决方案3】:

    解析并不意味着它的格式,它只是将它作为文本解析为java.util.Date 对象。见parse method in documentation

    您需要使用format 方法。

    dateFormat.format(travel.getDate())
    

    更多详情请见documentation

    【讨论】:

    • 这意味着我需要返回一个字符串然后返回一个日期对象?
    • @lhuezo 没有,可以直接跳过解析步骤,直接格式化 travel.getDate()
    【解决方案4】:

    如果form.getTravelDate() 返回字符串,则首先Parse 来自字符串的日期

    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    dateFormat.setLenient(false);
    Date parsedDate=dateFormat.parse(form.getTravelDate()); 
    // Here parsedDate is in form Wed Dec 12 00:00:00 CST 2012 
    

    现在使用相同的 SIMpleDateFormat 格式化日期以获得所需的输出

    System.out.println(dateFormat.format(parsedDate));
    

    你想要的输出

    2012-12-12
    

    更新

    假设我们在数据库中插入此数据的列的数据类型是Date 类型不是varchar 然后使用以下语句

    travel.setDate(dateFormat.format(parsedDate));
    

    【讨论】:

    • 问题是我不需要显示值,我实际上需要将它插入到数据库中以所述格式。我发现奇怪的是,在将字符串解析为 Date 之后,我必须将其设置回 String。
    【解决方案5】:

    据我了解parse 方法返回Date。下面是解析方法的语法。

    public Date parse(String source)
               throws ParseException
    

    因此,您需要解析字符串日期并存储到日期变量中。然后使用 SimpleDateFormat 格式化 Date 变量。

    //getTravelDate is "2012-12-12"
    
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
    dateFormat.setLenient(false);
    Date dtObj=new Date(); 
    dtObj=dateFormat.parse(form.getTravelDate());   //Store in date variable    
    System.out.println(dateFormat.format(dtObj)); // Now format the date object
    

    最终输出为2012-12-12。希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-23
      • 1970-01-01
      相关资源
      最近更新 更多