2017-07-27 68 views
1

问候堆栈溢出,为什么Java SimpleDateFormat在某些服务器上而不是其他服务器上工作?

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

只是为了一些背景信息,这同一个应用程序成功地工作在几个不同的操作系统(Ubuntu的12.04,在Windows Server 2012 R2等),无论是在美国和其他国家不同的Java/Tomcat的配置。

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

一切工作正常,除了我提交日期字段到我的控制器方法的任何地方的应用程序。当试图日期字符串提交给我的控制器在整个应用程序的不同部分,我得到以下信息:

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转换的字符串到日期:

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”

+1

难道是部署问题?像一些jar的旧版本? – talex

+0

我正在调查,但奇怪的事情是相同的.war文件将在其他服务器上工作没有问题。 – MotoDave452

+2

它可以是日期格式问题吗?在欧洲,日期将采用其他格式,例如“”dd/MM/yyyy ...“”。 –

回答

2

希腊不使用相同的AM/PM与许多其他讲拉丁语言的国家一样。希腊改为使用π.μ。和μ.μ。因此,当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); 

这将使用英语与美国区域设置此服务器上。尽管如此,仍然需要确保这是在每种情况下在输入中传递的格式。

+2

这是正确的答案。 – ReezaCoriza

+0

这对我有用!我会接受这个答案,也可以赞扬Sergei Sirik提出的同样建议。 – MotoDave452

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是短期的和祖鲁装置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") ; 

也许你在一定的时间段,而不是UTC意味着中午25。

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. 
+0

谢谢!我感谢你的时间,这是非常有用的信息。 – MotoDave452

相关问题