为什么Java SimpleDateFormat可以在某些服务器上运行而不在其他服务器上运行?

时间:2017-07-27 17:25:49

标签: java windows spring-mvc tomcat simpledateformat

问候堆栈溢出,

我正在为一个位于雅典的外国办事处实施的应用程序遇到一个奇怪的问题。构建时,应用程序是一个部署在Tomcat实例上的.war文件。

仅针对某些背景信息,此相同的应用程序可在美国和其他具有不同Java / Tomcat配置的国家/地区的多个不同操作系统(Ubuntu 12.04,Windows Server 2012 R2等)上成功运行。

但是我用来安装雅典应用程序的操作系统是Windows Server 2008 R2。安装在此服务器上的是Java JRE 1.8.0_111,Tomcat 8.5.4使用它。此服务器位于雅典。

除了我向控制器方法提交日期字段的任何地方外,应用程序的一切正常。当尝试在应用程序的各个不同部分向我的控制器提交日期字符串时,我收到以下消息:

Failed to convert the value of 'java.lang.String' to required type'java.util.Date'; 
nested exception is java.lang.illegalArgumentException:  Could not parse text 
[7/28/2017 7:00 AM] into any available date input formats.

请记住,当我将此应用程序部署到另一台服务器上的Tomcat实例时,一切正常,我没有收到此错误消息。

为了解决此错误,我决定更改其中一个请求参数的类型:

@RequestParam("date") Date date

@RequestParam("date") String dateString

然后我使用Java SimpleDateFormat将String转换为Date:

SimpleDateFormat sdf_date = new SimpleDateFormat("MM/dd/yyyy hh:mm a");
String startDate = dateString;
Date date = sdf_date.parse(startDate);

传递给上述函数的日期字符串是:

11/25/2017 12:00 pm

我在具有不同OS / Tomcat配置的几个测试服务器上测试了它,它就像一个魅力。但是,在位于雅典的Windows 2008 R2服务器上进行测试时,我仍然收到错误消息。我不再收到上述错误,但我收到了以下错误:

java.text.ParseException: Unparseable date: "11/25/2017 12:00 pm"

我不确定为什么这个相同的Java代码能够在某些服务器上使用相同的SimpleDateFormat模式解析相同的日期,而不是其他服务器。这对我来说似乎很奇怪。

如果您需要任何其他信息,请与我们联系,我们将很乐意澄清。

谢谢!

编辑:雅典服务器端服务器端调试的屏幕截图:

enter image description here

' dateString'正在传递给控制器​​方法

2 个答案:

答案 0 :(得分:3)

希腊并没有像使用拉丁语言的其他国家那样使用相同的上午/下午指定。希腊反而使用π.μ。和μ.μ。因此,当SimpleDateFormat没有收到语言环境时,它假定它与运行该程序的计算机相同。

要解决此问题,请尝试以下内容:

SimpleDateFormat sdf_date = new SimpleDateFormat("MM/dd/yyyy hh:mm a",  new Locale("en", "US"));
String startDate = dateString;
Date date = sdf_date.parse(startDate);

这将在此服务器上使用带有美国语言环境的英语语言。您仍然需要确保这是在每个场景中输入中传递的格式。

答案 1 :(得分:1)

TL;博士

Instant.parse( "2017-11-25T12:00:00Z" ) 

详细

Answer by Smith是正确的。

此外,还有三个问题。解决这些问题将消除您摔跤本地化文本格式的问题。

时区

你忽略了时区的关键问题。如果未指定,则隐式依赖JVM的当前默认时区。即使在运行时(!)期间,该默认值也会有所不同,因此最好明确指定所需/预期的时区。

除非您有特殊原因,否则通常最好使用UTC。

ISO 8601

ISO 8601标准为表示日期时间值的文本定义了实用的明确格式。

在UTC的时间轴中,使用YYYY-MM-DDTHH:MM:SS.SSSSSSSSSZ,T将日期部分与时间部分分开,Z是Zulu的缩写并且表示UTC,时间使用24小时制(无AM / PM)。

将日期时间值序列化为文本时,请使用这些标准格式。

java.time

你正在使用现在遗留的麻烦的旧日期时间类,取而代之的是现代java.time类。

Instant类表示UTC时间轴中的一个时刻,类似于java.time.Date,但分辨率为纳秒而不是毫秒。

Instant instant = Instant.now() ;

在解析/生成字符串时,java.time类默认使用ISO 8601格式。

String output = instant.toString() ;

和...

Instant instant = Instant.parse( "2017-01-23T12:34:56Z" ) ;

也许你指的是25日某个时区而不是UTC。

LocalDateTime.parse( "2017-11-25T12:00:00" )   // LocalDateTime has no concept of time zone or offset-from-UTC. Not on the timeline. Has no real meaning until assigned a time zone. 
             .atZone( ZoneId.of( "America/New_York" ) )   // Assign a time zone to determine a moment on the timeline, a ZonedDateTime.
             .toInstant()  // Extract a Instant, always in UTC by definition.
             .toString()  // Generate a string in standard ISO 8601 format.