簡體   English   中英

Java:SimpleDateFormat無法在所需的TimeZone中格式化

[英]Java: SimpleDateFormat not formatting in desired TimeZone

我想為特定時區GMT設置日期格式,並且我希望該格式的結果始終相同,無論應用程序在哪個時區運行。

例如,在GMT時區中創建Calendar實例並填充其字段:

TimeZone gmtTimeZone = TimeZone.getTimeZone( "GMT" );

Calendar calendar = Calendar.getInstance();
calendar.setTimeZone( gmtTimeZone );
calendar.set( Calendar.YEAR, 1982 );
calendar.set( Calendar.MONTH, Calendar.JANUARY );
calendar.set( Calendar.DAY_OF_MONTH, 23 );
calendar.set( Calendar.HOUR, 1 );
calendar.set( Calendar.MINUTE, 2 );
calendar.set( Calendar.SECOND, 3 );
calendar.set( Calendar.MILLISECOND, 4 );

從日歷中檢索UTC時間戳:

Date utcDate = calendar.getTime();

據我了解, utcDate現在是January 1, 1970, 00:00:00.000 GMT January 23, 1982, 01:02:03.004 GMT之間的毫秒數。 請參閱Date Javadocs:

    /**
     * Returns the number of milliseconds since January 1, 1970, 00:00:00 GMT
     * represented by this <tt>Date</tt> object.
     *
     * @return the number of milliseconds since January 1, 1970, 00:00:00 GMT
     *          represented by this date.
     */

創建日期格式器並將其時區也設置為GMT:

SimpleDateFormat dateTimeFormat = new SimpleDateFormat( "yyyy-MM-dd' 'HH:mm:ss.SSSZ" );
dateTimeFormat.setTimeZone( gmtTimeZone );

將日期對象格式化為字符串:

String stringDate = dateTimeFormat.format( utcDate );

現在,當我這樣做時:

System.out.println( utcDate.getTime() );
System.out.println( stringDate );

我得到:

> 380638923004
> 1982-01-23 13:02:03.004+0000

但是,我的期望是(注意13小時vs 01小時):

> 1982-01-23 01:02:03.004+0000

即,因為我使用calendar.set( Calendar.HOUR, 1 );將時間設置為1(凌晨calendar.set( Calendar.HOUR, 1 ); ,我希望時間是1點(凌晨1點)而不是13點(下午1點)。

我要去哪里錯了?

SimpleDateFormat dateTimeFormat = new SimpleDateFormat( "yyyy-MM-dd' 'hh:mm:ss.SSSZ" );
dateTimeFormat.setTimeZone( gmtTimeZone );

這將為您提供預期的輸出。

根據JavaDoc for SimpleDateFormat,日期格式字符串中的“ h”將以am / pm(1-12)表示為小時。

編輯:Calendar.HOUR_OF_DAY應該用於設置24小時制的小時。

由於正確答案斯賓塞布雷特說,你應該使用hh如果你的意思是小寫的12小時制 ,而不是24小時。

java.time

使用Java 8及更高版本時,應避免使用這些眾所周知的麻煩的舊日期時間類(java.util.Date/.Calendar等)。 它們已被java.time框架取代。 請參閱教程

Instant

Instant是UTC時間軸上的時刻。

Instant instant = Instant.now();

OffsetDateTime

但是, Instant具有有限的格式和有限的實例化方式。 因此,讓我們看一下OffsetDateTime ,您可以將其視為與從UTC偏移ZoneOffset )結合的Instant 為了指定偏移量,我們可以使用常量java.time.ZoneOffset.UTC 要實例化OffsetDateTime我們首先構建僅日期和僅 時間 ,然后結合偏移量。

納秒分辨率

java.time類具有納秒級的分辨率。 您在問題示例中的預期毫秒數。 因此,我們將使用TimeUnit轉換。 您可以自己進行乘法運算,但是容易出錯。 而且TimeUnit是自我記錄的。

LocalDate localDate = LocalDate.of( 1982 , 1 , 23 );
long nanoseconds = TimeUnit.NANOSECONDS.convert( 4 , TimeUnit.MILLISECONDS );
LocalTime localTime = LocalTime.of( 1 , 2 , 3 , nanoseconds );
OffsetDateTime odt = OffsetDateTime.of( localDate , localTime , ZoneOffset.UTC );

ISO 8601

java.time類的toString方法默認使用ISO 8601標准格式。 因此,您無需指定格式即可,因為它接近您想要的輸出。 與標准格式不太一樣,中間包含一個T而不是一個SPACE。

String output = odt.toString();

1982-01-23T01:02:03.004Z

可以將T替換為SPACE,也可以在Stack Overflow中搜索有關在java.time中使用DateTimeFormatter類的許多示例。

String output = odt.toString().replace( "T" , " " );

暫無
暫無

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

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