如何将UTC日期/时间(字符串)解析为更具可读性的内容?

Lux*_*ode 40 java

我有这样一个日期和时间的字符串:2011-04-15T20:08:18Z.我不太了解日期/时间格式,但我认为,如果我错了,请纠正我,这是它的UTC格式.

我的问题:在Java中,将这种解析为更正常的格式的最简单方法是什么?

And*_*ite 35

你所拥有的是ISO-8601日期格式,这意味着你可以使用SimpleDateFormat

DateFormat m_ISO8601Local = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
Run Code Online (Sandbox Code Playgroud)

然后你可以使用SimpleDateFormat.parse().此外,这是一篇博客文章,其中包含一些可能有用的示例.

更新:

使用此解决方案之前,请阅读以下注释.

  • 我希望我可以删除我的答案,支持Josh Pinter的答案,但是因为它被接受所以不会让我这么做.所以,如果你感觉很亲切,并且不想将答案推向地面,请考虑投票评论和Josh的回答.谢谢... (23认同)
  • 这对其他人有用吗?在我的情况下,它无法解析. (5认同)
  • 以上是有效的.但我们必须设置时区m_ISO8601Local.setTimeZone(TimeZone.getTimeZone("UTC")); (3认同)
  • 请删除“在使用此解决方案之前阅读下面的评论。”并修复您的解决方案。像这样,很多人(包括我)在浏览答案时都会错过它。 (3认同)

Jos*_*ter 35

使用JodaTime

我一直使用Z格式末尾的其他解决方案来解析错误.

相反,我选择利用JodaTime优秀的解析功能,并且能够非常轻松地执行以下操作:

String timestamp = "2011-04-15T20:08:18Z";

DateTime dateTime = ISODateTimeFormat.dateTimeParser().parseDateTime(timestamp);
Run Code Online (Sandbox Code Playgroud)

这可以正确识别UTC时区,然后允许您使用JodaTime的大量操作方法来获取您想要的内容.

希望这有助于其他人.

J.P

  • @AndrewWhite首先,我同意你关于使用Java本地的问题,但是一旦我开始深入研究它,JodaTime的好处似乎超过了本机."Z"允许时区,这非常重要,但是,它似乎并不"理解"ISO-8601时间戳中的"Z"(代表UTC时区).JodaTime只做"正确的事". (2认同)

Bas*_*que 31

TL;博士

String output = 
    Instant.parse ( "2011-04-15T20:08:18Z" )
           .atZone ( ZoneId.of ( "America/Montreal" ) )
           .format ( 
               DateTimeFormatter.ofLocalizedDateTime ( FormatStyle.FULL )
                                .withLocale ( Locale.CANADA_FRENCH ) 
           )
;
Run Code Online (Sandbox Code Playgroud)

vendredi 15 avril 2011 16 h 08 EDT

细节

Josh Pinter答案是正确的,但可能更简单.

java.time

在Java 8及更高版本中,捆绑的java.util.Date/Calendar类被JSR 310定义的java.time框架取代.这些课程的灵感来自Joda-Time,但完全是重新设计的.

java.time框架是Joda-Time的官方继承者.Joda-Time的创建者建议我们应该尽快迁移到java.time.Joda-Time不断更新和调整,但进一步的创新只能在java.time及其在ThreeTen-Extra项目中的扩展中完成.

大部分java.time功能已经在ThreeTen- Backport项目中反向移植到Java 6和7 ,并在ThreeTenABP项目中进一步适应Android .

上面的Joda-Time代码的等价物非常相似.概念类似.和Joda-Time一样,java.time类在解析/生成日期时间值的文本表示时默认使用ISO 8601格式.

An InstantUTC时间轴上的一个时刻,分辨率为纳秒(相对于Joda-Time和java.util.Date使用的毫秒数).

Instant instant = Instant.parse( "2011-04-15T20:08:18Z" );
Run Code Online (Sandbox Code Playgroud)

应用时区(ZoneId)来获得ZonedDateTime.

ZoneId zoneId = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
Run Code Online (Sandbox Code Playgroud)

调整到另一个时区.

ZoneId zoneId_NewYork = ZoneId.of( "America/New_York" );
ZonedDateTime zdt_NewYork = zdt.withZoneSameInstant( zoneId_NewYork );
Run Code Online (Sandbox Code Playgroud)

要创建除toString方法之外的其他格式的字符串,请使用java.time.format类.您可以指定自己的格式设置模式,也可以让java.time自动进行本地化.指定Locale(a)用于翻译月份/星期几的人类语言,以及(b)时期与逗号的文化规范,部分的顺序等.

DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL );
formatter = formatter.withLocale( Locale.US );
String output = zdt_NewYork.format( formatter );
Run Code Online (Sandbox Code Playgroud)

美国东部时间2011年4月15日星期五下午4:08:18


关于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类?

ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval,YearWeek,YearQuarter,和更多.


乔达时间

UPDATE:乔达时间的项目现在处于维护模式,与团队的建议迁移java.time类.此部分保留完整的历史记录.

将字符串传递给构造函数

Joda-Time可以直接使用该字符串.只需传递给DateTime类的构造函数.

Joda-Time了解日期时间的标准ISO 8601格式,并将该格式用作默认格式.

示例代码

以下是在Mac上用Java 7运行的Joda-Time 2.3中的示例代码.

我将以两种方式展示如何将字符串传递给DateTime构造函数:有和没有时区.指定时区解决了人们在进行日期工作时遇到的许多问题.如果未指定,您将获得默认时区,这可能会在投入生产时带来意外.

我还展示了如何使用内置常量指定无时区偏移(UTC/GMT)DateTimeZone.UTC.这就是Z最后的,Zulu时间短,意味着:没有时区偏移(00:00).

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;

// Default time zone.
DateTime dateTime = new DateTime( "2011-04-15T20:08:18Z" );

// Specified time zone.
DateTime dateTimeInKolkata = new DateTime( "2011-04-15T20:08:18Z", DateTimeZone.forID( "Asia/Kolkata" ) );
DateTime dateTimeInNewYork = new DateTime( "2011-04-15T20:08:18Z", DateTimeZone.forID( "America/New_York" ) );

// In UTC/GMT (no time zone offset).
DateTime dateTimeUtc = dateTimeInKolkata.toDateTime( DateTimeZone.UTC );

// Output in localized format.
DateTimeFormatter formatter = DateTimeFormat.shortDateTime().withLocale( Locale.US );
String output_US = formatter.print( dateTimeInNewYork );
Run Code Online (Sandbox Code Playgroud)

转储到控制台......

System.out.println("dateTime: " + dateTime );
System.out.println("dateTimeInKolkata: " + dateTimeInKolkata );
System.out.println("dateTimeInNewYork: " + dateTimeInNewYork );
System.out.println("dateTimeUtc: " + dateTimeUtc );
System.out.println("dateTime in US format: " + output_US );
Run Code Online (Sandbox Code Playgroud)

跑的时候......

dateTime: 2011-04-15T13:08:18.000-07:00
dateTimeInKolkata: 2011-04-16T01:38:18.000+05:30
dateTimeInNewYork: 2011-04-15T16:08:18.000-04:00
dateTimeUtc: 2011-04-15T20:08:18.000Z
dateTime in US format: 4/15/11 4:08 PM
Run Code Online (Sandbox Code Playgroud)


jst*_*ker 7

SimpleDateFormat的Java 7版本使用大写字母支持ISO-8601时区X.

String string = "2011-04-15T20:08:18Z";
DateFormat iso8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
Date date = iso8601.parse(string);
Run Code Online (Sandbox Code Playgroud)

如果你坚持使用Java 6或更早版本,推荐JodaTime的答案是一个安全的选择.


Wit*_*ult 6

已经有很多答案,但只是想用Java 8更新,以防任何人在解析字符串日期时遇到问题。

通常我们在日期方面面临两个问题

  1. 解析字符串到日期
  2. 以所需的字符串格式显示日期

DateTimeFormatterJava 8中的class可以用于这两个目的。下面的方法试图为这些问题提供解决方案。

方法1: 将您的UTC字符串转换为Instant。使用“ 即时”,您可以通过提供时区字符串DateTimeFormatter来为任何时区创建日期,并根据需要设置日期的格式。

String dateString = "2016-07-13T18:08:50.118Z";
String tz = "America/Mexico_City";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MMM d yyyy hh:mm a");
ZoneId zoneId = ZoneId.of(tz);

Instant instant = Instant.parse(dateString);

ZonedDateTime dateTimeInTz =ZonedDateTime.ofInstant(instant, zoneId);

System.out.println(dateTimeInTz.format(dtf));
Run Code Online (Sandbox Code Playgroud)

方法2:

使用DateTimeFormatter内置常量,例如ISO_INSTANT将字符串解析为LocalDateISO_INSTANT可以解析模式的日期

yyyy-MM-dd'T'HH:mm:ssX例如'2011-12-03T10:15:30Z'

LocalDate parsedDate
  = LocalDate.parse(dateString, DateTimeFormatter.ISO_INSTANT);

DateTimeFormatter displayFormatter = DateTimeFormatter.ofPattern("yyyy MM dd");
System.out.println(parsedDate.format(displayFormatter));
Run Code Online (Sandbox Code Playgroud)

方法3:

如果您的日期字符串具有很高的时间精度,例如它捕获秒的分数以及在这种情况下2016-07-13T18:08:50.118Z则方法1将起作用而方法2将不起作用。如果尝试解析,它将抛出错误,DateTimeException因为ISO_INSTANT格式化程序将无法解析几分之一秒,正如您从其模式中看到的那样。在这种情况下,您将必须通过提供以下日期模式来创建自定义 DateTimeFormatter

LocalDate localDate 
= LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX"));
Run Code Online (Sandbox Code Playgroud)

摘自我写的博客链接