为什么Java SimpleDataFormat可以在某些服务器上工作,而不能在其他服务器上工作?

为什么Java SimpleDataFormat可以在某些服务器上工作,而不能在其他服务器上工作?,java,windows,spring-mvc,tomcat,simpledateformat,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使用

堆栈溢出

我遇到了一个奇怪的问题,我正在为位于雅典的一家外交部实施一个应用程序。构建时,应用程序是部署在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

然后,我使用Java SimpleDataFormat将字符串转换为日期:

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配置的测试服务器上测试了这一点,效果非常好。然而,在雅典的Windows2008R2服务器上测试时,我仍然收到一个错误。我不再收到上述错误,但收到了以下信息:

java.text.ParseException: Unparseable date: "11/25/2017 12:00 pm"
我不确定为什么同样的Java代码能够在某些服务器上使用相同的SimpleDataFormat模式解析相同的日期,但在其他服务器上却不能。这对我来说似乎很奇怪

请让我知道,如果你需要任何额外的信息,我将很高兴澄清

谢谢大家!

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


传递给控制器方法的“dateString”希腊不像其他许多使用拉丁语的国家一样使用相同的am/pm名称。希腊则使用π.µ。和µ。µ。因此,当SimpleDataFormat没有收到区域设置时,它会假定该区域设置与运行该程序的计算机相同

要解决此问题,请尝试以下操作:

SimpleDateFormat sdf_date = new SimpleDateFormat("MM/dd/yyyy hh:mm a",  new Locale("en", "US"));
String startDate = dateString;
Date date = sdf_date.parse(startDate);
这将在此服务器上使用英语和US语言环境。不过,您仍然需要确保这是在每个场景中输入中传递的格式

tl;博士 细节 答案是正确的

此外,还有三个问题。解决这些问题将消除您与本地化文本格式之间的矛盾

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

通常最好使用UTC,除非您有特定原因

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

在UTC时间线中的某一时刻,使用YYYY-MM-DDTHH:MM:SS.sssz,其中
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. 

这可能是部署问题吗?就像旧版本的jar一样?会不会是日期格式的问题?在欧洲,日期将采用其他格式,如“dd/MM/yyyy…”。我的意思是,在雅典服务器上,
SimpleDateFormat
是使用默认希腊语言环境创建的。如果您向我们传递格式化日期字符串,您可能希望使用US locale创建
SimpleDateFormat
SimpleDateFormat(字符串模式,locale语言环境)
服务器在哪里并不重要,重要的是这些服务器使用哪种语言和“AM”看起来不是一个有效的希腊语单词/缩写。您打算在25日中午在哪个时区?雅典的正午比纽约的正午早了几个小时。这对我很有效!我会接受这个答案,同时也要感谢Sergei Sirik提出的同样的建议。这也为我工作过!。回答得好!非常感谢。感谢您抽出时间,这是非常有用的信息。
Instant instant = Instant.parse( "2017-01-23T12:34:56Z" ) ;
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.