[英]Java Converting 19-digit Unix Timestamp to a Readable Date
我正在嘗試將19位Unix時間戳(例如1558439504711000000
(一個五分之五 ))轉換為可讀的日期/時間格式。 我的時間戳以6個零結尾,這表明時間以納秒為單位。
我遇到了一些示例,其中人們使用了我不需要的時區。 另一個示例使用ofEpochSecond像這樣:
Instant instant = Instant.ofEpochSecond(seconds, nanos);
但是我不確定是否需要使用EpochSecond。
下面的代碼提供了我最新的實現方法:
String timeStamp = "1558439504711000000";
long unixNanoSeconds = Long.parseLong(timeStamp);
Date date = new java.util.Date(timeStamp*1000L);
// My preferred date format
SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
String formattedDate = sdf.format(date);
System.out.println("The timestamp in your preferred format is: " + formattedDate);
但是我得到的輸出是這樣的:
// The timestamp in your preferred format is: 11-12-49386951 11:43:20
它不以例如2019格式顯示年份格式。
永遠不要使用遺留類java.util.Date
。 而是使用modern java.time.Instant
。
Instant // The modern way to represent a moment in UTC with a resolution of nanoseconds. Supplants the terrible `java.util.Date` class.
.ofEpochSecond( // Parse a count since epoch reference of 1970-01-01T00:00:00Z.
0L , // Passing zero for the count of whole seconds, to let the class determine this number from the 2nd argument.
Long.parse( "1558439504711000000" ) // Count of nanoseconds since the epoch reference of 1970-01-01T00:00:00Z.
) // Returns a `Instant` object.
.atZone( // Adjust from UTC to the wall-clock time used by the people of a specific region (a time zone).
ZoneId.of( "Europe/London" )
) // Returns a `ZonedDateTime` object. Same moment as the `Instant`, same point on the timeline, different wall-clock time.
.format( // Generate text to communicate the value of the moment as seen through this time zone.
DateTimeFormatter.ofPattern( // Define how to format our generated text.
"dd-MM-uuuu HH:mm:ss" , // Specify your desired formatting pattern.
Locale.UK // Pass a `Locale` to be used in localizing, to (a) determine human language used in translating name of day-of-week and such, and (b) determine cultural norms to decide issues of capitalization, abbreviation, etc. Not really needed for this particular formatting pattern, but a good habit to specify `Locale`.
) // Returns a `DateTimeFormatter` object.
) // Returns a `String` object containing our text.
21-05-2019 12:51:44
…要么…
Instant
.ofEpochSecond (
TimeUnit.NANOSECONDS.toSeconds(
Long.parse( "1558439504711000000" )
) ,
( 1_558_439_504_711_000_000L % 1_000_000_000L )
)
.toString()
2019-05-21T11:51:44.711Z
注意時差,因為時區比UTC早一小時。
java.util.Date
類很糟糕 。 連同它的Calendar
和SimpleDateFormat
,真是一團糟。 避免他們。 Sun,Oracle和JCP社區在采用JSR 310時放棄了它們。
Instant
一個java.util.Date
對象用UTC表示一個時刻,分辨率為毫秒 。 它的替換內容是java.time.Instant
,也是UTC中的一刻,但分辨率為納秒 。 從UTC 1970年第一時刻的紀元參考開始,兩者在內部都進行計數。
為了避免處理巨大的數字, Instant
在內部跟蹤自1970年以來的整數秒, 外加小數秒(以納秒為單位)。 兩個單獨的數字。 這些就是您需要提供Instant.ofEpochSecond
。
使用Long
類將輸入字符串解析為long
。 順便說一句,請注意您的值正在逼近64位整數的限制 。
long totalNanos = Long.parse( "1558439504711000000" ) ;
long secondsPortion = TimeUnit.NANOSECONDS.toSeconds( totalNanos ) ;
模為十億分之一,其余為小數秒的納秒。
long nanosPortion = ( totalNanos % 1_000_000_000L ) ;
實例化一個Instant
。
Instant instant = Instant.ofEpochSecond( secondsPortion , nanosPortion ) ;
我的時間戳以6個零結尾,這表明時間以納秒為單位。
實際上,納秒的計數高達十億,因此九(9)位數字不是六(6)位。 從紀元開始711000000
是711000000
,即711,000,000納秒。 您的總秒數為1558439504
或1,558,439,504(十億分之一)。 作為小數點:
自1970-01-01T00:00Z起1,558,439,504.711000000秒
我遇到了一些示例,其中人們使用了我不需要的時區。
為了表示一個時刻,即時間軸上的特定點, 您始終需要一個時區 (或從UTC偏移小時-分鍾-秒)。
要查看特定區域(時區)的人們在牆上時鍾所用的同一時刻,請應用ZoneId
來獲取ZonedDateTime
。
以Continent/Region
的格式指定正確的時區名稱 ,例如America/Montreal
, Africa/Casablanca
或Pacific/Auckland
。 切勿使用2-4個字母的縮寫,例如BST
或EST
或IST
因為它們不是真實的時區,不是標准化的,甚至不是唯一的(!)。
ZoneId z = ZoneId.of( "Europe/London" ) ;
ZonedDateTime zdt = instant.atZone( z ) ; // Same moment, same point on the timeline, different wall-clock time.
2019-05-21T12:51:44.711 + 01:00 [歐洲/倫敦]
請注意一天中的時間調整,從11點到12點。這很有意義,因為Europe/London
地區比該日期的UTC早一個小時。 同一時刻,時間軸上的同一點,不同的時鍾時間。
正如Ole VV在評論中指出的,您可以跳過上面討論的數學。 將完整的納秒數作為ofEpochSecond
的第二個參數。 該類在內部進行數學運算,以將整秒與小數秒分開。
Instant instant = Instant.ofEpochSecond( 0L , 1_558_439_504_711_000_000L ) ;
以標准ISO 8601格式生成表示該ZonedDateTime
值的文本,該格式已擴展為將時區的名稱附加在方括號中。
String output = zdt.toString() ;
2019-05-21T12:51:44.711 + 01:00 [歐洲/倫敦]
或者讓java.time自動為您本地化。
Locale locale = Locale.UK;
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime( FormatStyle.SHORT ).withLocale( locale );
String output = zdt.format( f );
21/05/2019,12:51
或指定自定義格式。
Locale locale = Locale.UK;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd-MM-uuuu HH:mm:ss" , locale ) ;
String output = zdt.format( f );
21-05-2019 12:51:44
提示:在提供日期時間時要非常小心,不要顯式指定區域。 這會產生歧義,用戶可能會假設正在玩一個不同的區域/偏移。
我認為這沒什么不對,您正在處理一個表示FUTURE(未來)中某個日期的時間戳(將來的日期非常遙遠)。
如果您考慮以下情況:
String timeStamp = "1558439504";
這應該給你:05/21/2019 @ 11:51 am(UTC)
然后,我想一種簡單的方法來獲取日期。 只需首先根據該時間戳創建即時消息,然后執行以下操作:
Date myDate = Date.from(instant);
試試這個
Date date = new java.util.Date(timeStamp/1000000);
而不是乘以1000 ,除以1000000
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.