[英]Parse ISO8601 date string to date with UTC Timezone
我正在嘗試從/到 JavaScript 應用程序序列化/反序列化日期。
服務器端,我用的是Java,上面安裝了JodaTime。 我發現了如何使用 UTC 時區序列化為 ISO,但不知道如何進行反向操作。
這是我的代碼
public static String getIsoDate( Date date )
{
SimpleDateFormat dateToIsoDateString = new SimpleDateFormat( ISO_8601_DATE_FORMAT );
TimeZone tz = TimeZone.getTimeZone("UTC");
dateToIsoDateString.setTimeZone( tz );
return dateToIsoDateString.format( date );
}
// this will return a date with GMT timezone
public static Date getDateFromIsoDateString( String iso8601date )
{
DateTimeFormatter jodaParser = ISODateTimeFormat.dateTimeNoMillis();
return jodaParser.parseDateTime( iso8601date ).toDate();
}
我不介意使用或不使用 Joda,只需要一個快速有效的解決方案,
如果您使用的是 Java 7 或更早版本,您可以參考這篇文章。
如果您使用的是 Java 8,您可以這樣做:
DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME;
TemporalAccessor accessor = timeFormatter.parse("2015-10-27T16:22:27.605-07:00");
Date date = Date.from(Instant.from(accessor));
System.out.println(date);
正如@BasilBourque 在評論中指出的那樣, TemporalAccessor是java框架級別的接口,不建議在應用程序代碼中使用,建議使用具體類而不是接口。
該接口是框架級接口,不應在應用程序代碼中廣泛使用。 相反,應用程序應該創建和傳遞具體類型的實例,例如 LocalDate。 造成這種情況的原因有很多,其中一部分是該接口的實現可能在 ISO 以外的日歷系統中。 有關這些問題的更全面討論,請參閱 ChronoLocalDate。
有一些具體的類可供使用,如LocalDate 、 LocalDateTime 、 OffsetDateTime 、 ZonedDateTime等。
DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_DATE_TIME;
OffsetDateTime offsetDateTime = OffsetDateTime.parse("2015-10-27T16:22:27.605-07:00", timeFormatter);
Date date = Date.from(Instant.from(offsetDateTime));
System.out.println(date);
OffsetDateTime.parse( "2015-10-27T16:22:27.605-07:00" )
.toInstant()
.toString()
2015-10-27T23:22:27.605Z
你的問題不明確和具體。 也許這些小例子會有所幫助。 將舊的 java.util.Date 和 .Calendar 類與 Joda-Time 混合使用可能會讓您感到困惑。 Joda-Time 完全取代了這些類,而不是增加。
現代java.time類取代了 Java 中遺留的日期時間類以及提供靈感的 Joda-Time 庫。
OffsetDateTime
OffsetDateTime
類表示時間軸上的一個時刻,其與 UTC 的特定偏移確定其掛鍾時間。
java.time類在解析/生成字符串時默認使用標准ISO 8601格式。 所以不需要指定格式模式。
OffsetDateTime odt = OffsetDateTime.parse( "2015-10-27T16:22:27.605-07:00" ) ;
Instant
要從 UTC 后 7 小時的偏移量調整到 UTC 本身,我們需要在時間上增加 7 小時並在需要時翻轉日期。 OffsetDateTime
類可以為我們完成這項工作。 使用ZoneOffset.UTC
常量指定 UTC。
OffsetDateTime odtUtc = odt.withOffsetSameInstant( ZoneOffset.UTC ) ;
odtUtc.toString(): 2015-10-27T23:22:27.605Z
如果您在代碼中大量使用此 UTC 值,並且通常應該如此,那么您可能會發現使用Instant
對象更清楚。 根據定義, Instant
始終采用 UTC。 我們可以從OffsetDateTime
中提取Instant
。
Instant instant = odt.toInstant() ;
即時.toString(): 2015-10-27T23:22:27.605Z
請注意,我們上面的所有三個對象( odt
、 odtUtc
、 instant
)都代表相同的同時時刻,時間軸上的相同點。 唯一不同的是他們的掛鍾時間。
ZonedDateTime
順便說一句,如果您想看到同一時刻調整到某個地區的人們使用的掛鍾時間,請通過ZoneId
指定時區以獲取ZonedDateTime
對象。
ZoneId z = ZoneId.of( "America/Montreal" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
zdt.toString(): 2015-10-27T19:22:27.605-04:00[美國/蒙特利爾]
always_a_rookie_to_learn 的答案類似於上述方法,但使用接口TemporalAccessor
。 通常,在 Java 中使用更高的接口和超類是一個好主意。 但不是在這里。 java.time文檔解釋說,他們的設計旨在讓我們在我們的應用程序中使用較低的更具體的類。 通常,這些抽象僅供框架內部使用。
在這個問題的具體情況下,類OffsetDateTime
是合適的,而不是TemporalAccessor
。
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-Extra項目通過附加類擴展了 java.time。 該項目是未來可能添加到 java.time 的試驗場。 您可以在這里找到一些有用的類,例如Interval
、 YearWeek
、 YearQuarter
等等。
更新:Joda-Time 項目處於維護模式,它建議遷移到java.time類。 本節保留完整的歷史記錄。
Joda-Time 對字符串的解析和生成默認為ISO 8601 。 Joda-Time內置了 ISO 8601 的默認解析器,因此只需將您的兼容字符串傳遞給構造函數或靜態parse
方法。
java.util.Date date = new DateTime( "2010-01-01T12:00:00+01:00Z" ).toDate();
如果可能,請避免使用 java.util.Date 和 .Calendar,並堅持使用 Joda-Time和它的類,例如DateTime
。 僅在其他類需要時使用 .Date。
DateTime dateTimeUtc = new DateTime( someJavaDotUtilDotDate, DateTimeZone.UTC ); // Joda-Time can convert from java.util.Date type which has no time zone.
String output = dateTime.toString(); // Defaults to ISO 8601 format.
DateTime dateTimeUtc2 = new DateTime( output, DateTimeZone.UTC ); // Joda-Time can parse ISO 8601 strings.
對於演示,請調整到用戶期望的時區。
DateTime dateTimeMontréal = dateTimeUtc.withZone( DateTimeZone.forID( "America/Montreal" ) );
Java8中的原生解決方案
Date.from(ZonedDateTime.parse("1994-11-05T08:15:30+05:30").toInstant())
Date.from(ZonedDateTime.parse("1994-11-05T13:15:30Z").toInstant())
如果您的日期采用ISO 8601 UTC格式(例如: 2022-06-04T10:50:27Z
),那么您可以直接使用Instant
來解析它:
Instant.parse("2022-06-04T10:50:27Z")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.