解析DateFormat时的Java时区
我有解析日期的代码如下:
String ALT_DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; SimpleDateFormat sdf = new SimpleDateFormat( ALT_DATE_TIME_FORMAT); Date date = sdf.parse(requiredTimeStamp);
它工作正常,突然,这停止了工作。 事实certificate,管理员在服务器上进行了一些配置更改,并且日期当前正在返回为“2010-12-27T10:50:44.000-08:00”,这是上述模式无法解析的。 我有两个问题:
第一个是什么模式将以上述格式解析JVM返回的日期(具体来说,只是’-08:00’作为时区)? 第二,在Linux RHEL 5服务器上究竟会改变这样的设置,以便我们在将来意识到这些变化?
另一个应用程序使用ISO 8601 dateTime格式。 我假设其他应用程序发送的XML响应符合XML Schema的dateTime类型,即ISO 8601.现在,已知的事情是DateFormat无法解析此格式。 您必须使用其他库(如joda-time(joda-time是赢家)或其他响应中指定的FastDateFormat)。 请看这篇文章将符合ISO 8601标准的String转换为java.util.Date
TL;博士
OffsetDateTime.parse( "2010-12-27T10:50:44.000-08:00" )
ISO 8601
输入字符串格式在ISO 8601标准中定义,该标准是一系列日期时间格式。
避免旧的日期时间类
问题和其他答案使用与最早版本的Java捆绑在一起的旧的过时日期时间类。 避免他们。 现在取代了java.time类。
使用java.time
您的输入字符串以UTC的偏移量结束。 所以我们解析为OffsetDateTime
对象。
在解析/生成字符串时,java.time类默认使用ISO 8601格式。 因此无需指定格式化模式。
OffsetDateTime odt = OffsetDateTime.parse( "2010-12-27T10:50:44.000-08:00" );
如果要在UTC时间轴上查看此日期时间值,请提取Instant
。
Instant instant = odt.toInstant();
时区是偏移量加上一组用于处理夏令时(DST)等exception的规则。 如果您有时区,请应用ZoneId
以获取ZonedDateTime
对象。 时间轴上的相同时刻,但通过不同的挂钟时间查看。
ZoneId z = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = odt.atZoneSameInstant( z ); // Same moment on the timeline, but viewed through a different wall-clock time.
关于java.time
java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.Date
, Calendar
和SimpleDateFormat
。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参阅Oracle教程 。 并搜索Stack Overflow以获取许多示例和解释。 规范是JSR 310 。
您可以直接与数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC驱动程序 。 不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
- Java SE 8 , Java SE 9及更高版本
- 内置。
- 带有捆绑实现的标准Java API的一部分。
- Java 9增加了一些小function和修复。
- Java SE 6和Java SE 7
- 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
- Android的
- 更高版本的Android捆绑java.time类的实现。
- 对于早期的Android, ThreeTenABP项目采用ThreeTen-Backport (如上所述)。 请参见如何使用ThreeTenABP ….
ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如Interval
, YearWeek
, YearQuarter
等。
如果你想使用直接JDK解析它,我相信它应该是使用JAXB工具可解析的,请参阅DatatypeFactory.newXMLGregorianCalendar或DatatypeConverter.parseDateTime 。
使用JodaTime
作为@ Pangea建议使用JodaTime的更具体的例子,这是你可以使用的:
String timestamp = "2012-09-17T04:11:46Z"; DateTime date = ISODateTimeFormat.dateTimeParser().parseDateTime(timestamp);
这可以正确识别UTC时区。 我没有在字符串时间戳中用毫秒来尝试它,但我相信它也能正常工作。
希望能帮助别人。
J.P
问题应该是requiredTimeStamp
的来源和格式。 是由用户输入还是从其他程序读取? 哪个组件在String表示中创建日期?
格式“2010-12-27T10:50:44.000-08:00”看起来像标准化格式ISO-8601应该可以解析模式yyyy-MM-dd'T'HH:mm:ss.SSSZ
不确定哪些设置会影响这一点,但有一个关于Java TimeZones的Oracle常见问题解答 。 它可能是用户user.timezone
系统属性或RHEL中的/etc/localtime
符号链接。
SimpleDateFormat仅接受-0800
或GMT-08:00
作为时区。
似乎无法使用SimpleDateFormat
解析ISO 8601格式。 也许你应该看看Apache Commons Lang的FastDateFormat 。 它与SimpleDateFormat
兼容,但接受应该解析所需时区格式的时区的ZZ
模式。 DateFormatUtils包含一些示例常量,看起来像您需要的模式,只是没有毫秒(例如ISO_DATETIME_TIME_ZONE_FORMAT )。
尝试将其更改为小写z。
z处理大多数常见的通用时区语法,而Z使用更严格的RFC 822时区和4位数。
虽然它记录了两者都应解析“常规时区设置”,但它可能会对您的情况产生影响。