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

时间:2011-07-01 03:04:02

标签: java

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

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

9 个答案:

答案 0 :(得分:33)

使用JodaTime

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

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

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

DateTime dateTime = ISODateTimeFormat.dateTimeParser().parseDateTime(timestamp);

这正确识别UTC时区,然后允许您使用JodaTime的广泛操作方法来获取您想要的内容。

希望这有助于其他人。

JP

答案 1 :(得分:32)

您所拥有的是ISO-8601日期格式,这意味着您只需使用SimpleDateFormat

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

然后你可以使用SimpleDateFormat.parse()。此外,这里有一个blog post,其中包含一些可能有用的示例。

<强>更新

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

答案 2 :(得分:27)

TL;博士

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

vendredi 15 avril 2011 16 h 08 EDT

详细

answer by 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不断更新和调整,但只有在ThreeTen-Extra项目中的java.time及其扩展中才能进行进一步的创新。

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

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

InstantUTC中时间轴上的一个时刻,其分辨率为nanoseconds(与Joda-Time&amp; java.util.Date使用的milliseconds相对)

Instant instant = Instant.parse( "2011-04-15T20:08:18Z" );

应用时区(ZoneId)以获得ZonedDateTime

ZoneId zoneId = ZoneId.of( "Asia/Kolkata" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );

调整到另一个时区。

ZoneId zoneId_NewYork = ZoneId.of( "America/New_York" );
ZonedDateTime zdt_NewYork = zdt.withZoneSameInstant( zoneId_NewYork );

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

DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.FULL );
formatter = formatter.withLocale( Locale.US );
String output = zdt_NewYork.format( formatter );
  

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


关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和&amp; SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore


约达时间

更新 Joda-Time项目现在位于maintenance mode,团队建议迁移到java.time课程。这部分保留了完整的历史记录。

将字符串传递给构造函数

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

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

示例代码

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

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

我还展示了如何使用内置常量DateTimeZone.UTC指定无时区偏移(UTC / GMT)。这就是最后的ZZulu时间的缩写,意思是:没有时区偏移(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 );

转储到控制台...

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 );

跑步时......

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

答案 3 :(得分:7)

The Java 7 version of SimpleDateFormat使用大写字母X支持ISO-8601时区。

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

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

答案 4 :(得分:5)

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

一般来说,我们面临两个日期问题

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

    DateTimeFormatter类可用于这两个目的。 下面的方法试图为这些问题提供解决方案。

    方法1: 将您的UTC字符串转换为即时。使用即时,您可以通过提供时区字符串为所有时区创建日期,并使用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));
    

    方法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));
    

    方法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"));
    

    取自我写的blog link

答案 5 :(得分:2)

您必须提供以下格式:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
Date parse = simpleDateFormat.parse( "2011-04-15T20:08:18Z" );

答案 6 :(得分:1)

我在Andrew White解决方案中遇到了解析错误。 在Z周围添加单引号解决了问题

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

答案 7 :(得分:0)

对于所有旧版本的JDK(6 down),它可能很有用。

摆脱拖尾&#39; Z&#39;并用&#39; UTC&#39;替换它。时区显示名称 - 然后使用适当的简单日期格式化程序解析整个字符串。

String timeZuluVal = "2011-04-15T20:08:18Z";
timeZuluVal = timeZuluVal.substring( 0, timeZuluVal.length() - 2 ); // strip 'Z';
timeZuluVal += " " + TimeZone.getTimeZone( "UTC" ).getDisplayName();
DateFormat simpleDateFormat = new SimpleDateFormat( "yyyy-MM-dd'T'HH:mm:ss zzzz" );
Date dateVal = simpleDateFormat.parse( timeZuluVal );

答案 8 :(得分:0)

乔达时间

public static final String SERVER_TIME_FORMAT = "yyyy-MM-dd  HH:mm:ss";

public static DateTime getDateTimeFromUTC(String time) {
    try {
        DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(SERVER_TIME_FORMAT).withZoneUTC();

        Calendar localTime = Calendar.getInstance();
        DateTimeZone currentTimeZone = DateTimeZone.forTimeZone(localTime.getTimeZone());
        return dateTimeFormatter.parseDateTime(time).toDateTime().withZone(currentTimeZone);
    } catch (Exception e) {
        return DateTime.now();
    }
}