簡體   English   中英

如何將 UTC 日期/時間(字符串)解析為更具可讀性的內容?

[英]How can I parse UTC date/time (String) into something more readable?

我有一個這樣的日期和時間字符串: 2011-04-15T20:08:18Z 我對日期/時間格式了解不多,但我認為,如果我錯了,請糾正我,這就是它的 UTC 格式。

我的問題:在 Java 中,將其解析為更正常格式的最簡單方法是什么?

使用喬達時間

使用格式末尾帶有Z的其他解決方案時,我不斷收到解析錯誤。

相反,我選擇利用JodaTime出色的解析功能,並且能夠非常輕松地執行以下操作:

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

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

這可以正確識別 UTC 時區,然后允許您使用 JodaTime 的廣泛操作方法來獲取您想要的內容。

希望這對其他人有幫助。

您擁有的是ISO-8601日期格式,這意味着您可以使用SimpleDateFormat

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

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

更新:

在使用此解決方案之前,請閱讀以下評論。

tl;博士

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

2011 年 4 月 15 日 16 時 08 月 EDT

細節

Josh Pinter 的答案是正確的,但可能更簡單。

java.time

在 Java 8 及更高版本中,捆綁的 java.util.Date/Calendar 類被JSR 3 定義的 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,並進一步適應ThreeTen- Backport 項目中的ZE84E30B9390CDB64DB6DB2C9AB87846D項目。

上面 Joda-Time 代碼的等效代碼非常相似。 概念相似。 和 Joda-Time 一樣,java.time 類在解析/生成日期時間值的文本表示時默認使用ISO 8601格式。

InstantUTC時間線上的一個時刻,分辨率為納秒(相對於 Joda-Time 和 java.util.Date 使用的毫秒)。

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) 翻譯月份/星期幾的名稱時使用的人類語言,以及 (b) 句號與逗號、部分順序等的文化規范指定Locale

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 及更高版本中。 這些類取代了麻煩的日期時間類,例如java.util.DateCalendarSimpleDateFormat

現在處於維護模式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 SE 10及更高版本
    • 內置。
    • 標准 Java API 的一部分,帶有捆綁實現。
    • Java 9 添加了一些小功能和修復。
  • Java SE 6Java SE 7
    • java.time 的大部分功能都向后移植到 ThreeTen - Backport 中的 Java 6 和 7。
  • Android

ThreeTen-Extra項目通過附加類擴展了 java.time。 該項目是未來可能添加到 java.time 的試驗場。 您可以在這里找到一些有用的類,例如IntervalYearWeekYearQuarter等等


喬達時間

更新: Joda-Time項目現在處於維護模式,團隊建議遷移到java.time類。 本節原封不動地留給歷史。

將字符串傳遞給構造函數

Joda-Time可以直接使用該字符串。 只需傳遞給DateTime class 上的構造函數。

Joda-Time 理解標准的ISO 8601 日期時間格式,並使用該格式作為默認格式。

示例代碼

以下是在 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

Java 7 版本的 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 的答案是一個安全的選擇。

已經有很多答案,但只是想用java 8進行更新,以防任何人在解析字符串日期時遇到問題。

通常我們面臨兩個日期問題

  1. 將字符串解析為日期
  2. 以所需的字符串格式顯示日期

Java 8 中的DateTimeFormatter class 可用於這兩個目的。 以下方法試圖為這些問題提供解決方案。

方法 1:將您的 UTC 字符串轉換為Instant 使用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));

方法二:

使用內置常量的DateTimeFormatter例如ISO_INSTANT將字符串解析為LocalDate ISO_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));

方法三:

如果您的日期字符串具有很高的時間精度,例如它捕獲秒的分數以及在這種情況下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"));

摘自我寫的博客鏈接

您必須提供以下格式:

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

我在 Andrew White 解決方案中遇到了解析錯誤。 在 Z 周圍添加單引號解決了這個問題

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

@khmarbaise 答案中的模式對我有用,這是我提取的實用方法(請注意,模式字符串中省略了 Z):

/**
 * Converts an ISO-8601 formatted UTC timestamp.
 *
 * @return The parsed {@link Date}, or null.
 */
@Nullable
public static Date fromIsoUtcString(String isoUtcString) {
    DateFormat isoUtcFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault());
    isoUtcFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
    try {
        return isoUtcFormat.parse(isoUtcString);
    } catch (ParseException e) {
        e.printStackTrace();
        return null;
    }
}

對於所有舊版本的 JDK(6 下),它可能很有用。

擺脫尾隨的“Z”並將其替換為“UTC”時區顯示名稱 - 然后使用適當的簡單日期格式化程序解析整個字符串。

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

喬達時間

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM