Java - SimpleDateFormat 意外的解析行为
Java - SimpleDateFormat unexpected parsing behaviour
我正在从一个文件 (.csv) 中读取信息,该文件将在最终用户验证和批准后插入到数据库中。文本文件被读取、验证并将其信息加载到包含用于检查数据是否已存在于数据库中的表单的列表中。
解析String to Date时出现问题。 SimpleDateFormat.parse() 方法 returns 意外的日期格式,即使 SimpleDateFormat 的模式是 "yyyy-MM-dd"。
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);
我不需要的日期格式显示在这里,而在过去这个问题从未发生过。最后将信息发送到问题仍然存在的数据库。
不,它 "becomes" 一个 java.util.Date
值。如果您随后通过调用 Date.toString()
将其 back 转换为字符串,您应该查阅 Date.toString()
文档以了解预期结果。
存储在 Date
中的值 只是 一个时间点 - 自 Unix 纪元以来的毫秒数。那里没有格式,没有时区等。它也不知道它只是一个日期值而不是日期和时间(Date
的命名是 许多 不幸的方面 API).
在心理上将 "the result of the parse operation" 与 "the string value that is used to represent that result if I call toString"
" 区分开来至关重要。
我还建议您在解析日期时将 SimpleDateFormat
上的时区设置为 UTC - 这样您就知道您不能 可能 有任何模棱两可或跳过的时间导致难以预测的行为。 (当然,您随后需要知道您已将日期解析为 "the start of the UTC date" 并在其他地方适当地处理它。)
打印 Date
时也需要使用格式化程序。
dateFormat.format( travel.getDate() );
当您使用 DateFormat
解析 String
时,您会得到一个完整的 Date
对象,其中字符串中缺少的时间单位被初始化为零。在您的示例中,这是小时、分钟和秒。
默认情况下,如果您不使用格式化程序,则会打印 Date
的默认字符串表示形式(由其 toString()
方法提供)。
解析并不意味着格式化,它只是将其作为文本解析为 java.util.Date
对象。参见 parse method in documentation。
您需要使用format
方法。
dateFormat.format(travel.getDate())
有关详细信息,请参阅 documentation。
如果 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));
据我了解parse
方法returnsDate
。下面是解析方法的语法。
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
。希望对你有所帮助。
我正在从一个文件 (.csv) 中读取信息,该文件将在最终用户验证和批准后插入到数据库中。文本文件被读取、验证并将其信息加载到包含用于检查数据是否已存在于数据库中的表单的列表中。
解析String to Date时出现问题。 SimpleDateFormat.parse() 方法 returns 意外的日期格式,即使 SimpleDateFormat 的模式是 "yyyy-MM-dd"。
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);
我不需要的日期格式显示在这里,而在过去这个问题从未发生过。最后将信息发送到问题仍然存在的数据库。
不,它 "becomes" 一个 java.util.Date
值。如果您随后通过调用 Date.toString()
将其 back 转换为字符串,您应该查阅 Date.toString()
文档以了解预期结果。
存储在 Date
中的值 只是 一个时间点 - 自 Unix 纪元以来的毫秒数。那里没有格式,没有时区等。它也不知道它只是一个日期值而不是日期和时间(Date
的命名是 许多 不幸的方面 API).
在心理上将 "the result of the parse operation" 与 "the string value that is used to represent that result if I call toString"
" 区分开来至关重要。
我还建议您在解析日期时将 SimpleDateFormat
上的时区设置为 UTC - 这样您就知道您不能 可能 有任何模棱两可或跳过的时间导致难以预测的行为。 (当然,您随后需要知道您已将日期解析为 "the start of the UTC date" 并在其他地方适当地处理它。)
打印 Date
时也需要使用格式化程序。
dateFormat.format( travel.getDate() );
当您使用 DateFormat
解析 String
时,您会得到一个完整的 Date
对象,其中字符串中缺少的时间单位被初始化为零。在您的示例中,这是小时、分钟和秒。
默认情况下,如果您不使用格式化程序,则会打印 Date
的默认字符串表示形式(由其 toString()
方法提供)。
解析并不意味着格式化,它只是将其作为文本解析为 java.util.Date
对象。参见 parse method in documentation。
您需要使用format
方法。
dateFormat.format(travel.getDate())
有关详细信息,请参阅 documentation。
如果 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));
据我了解parse
方法returnsDate
。下面是解析方法的语法。
public Date parse(String source)
throws ParseException
因此,您需要解析字符串日期并将其存储到日期变量中。然后使用 SimpleDateFormat
.
//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
。希望对你有所帮助。