为什么Java SimpleDataFormat可以在某些服务器上工作,而不能在其他服务器上工作?
堆栈溢出 我遇到了一个奇怪的问题,我正在为位于雅典的一家外交部实施一个应用程序。构建时,应用程序是部署在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使用它。此服务器位于雅典 除了我向控制器方法提交日期字段的任何地方之外,应用程序的所有功能都很好。当尝试在应用程序的各个不同部分向控制器提交日期字符串时,我收到以下消息:为什么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使用
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.