2016-09-24 267 views
-1

如何在Java/Scala中將時間戳(以微秒爲單位)字符串轉換爲日期。 我的目標是比較兩個時間戳並找出它們之間的差異。 我正在使用java 8和示例Timestamp字符串是1474457086337977. 我想將其轉換爲Date或Timestamp實例。在Java或Scala中將微秒字符串轉換爲日期

+0

爲什麼你只是得到當前的日期和時間? – Kaushal28

+1

@NoOne因爲當前的日期和時間不會幫助您獲得兩個時間戳之間的差異,就像問題清楚地解釋:/ – Gimby

+0

實際上,我將從外部資源獲取這個時間戳,作爲我的數據的一部分,我需要比較這個時間戳,並做一些邏輯。 – BDR

回答

1

好了,關於如何將那些微秒什麼到毫秒,然後創建一個時間戳對象?

long microsecs = 1474457086337977L; 
long millis = TimeUnit.MILLISECONDS.convert(microsecs, TimeUnit.MICROSECONDS); 
Timestamp time = new Timestamp(millis); 

這不行嗎?

- 編輯

爲了解決留在答案的評論:

幫助Java 8新的日期時間API

首先,既然你提到你使用的是Java 8我完全同意,更好的方法是使用新的Java 8 Date/Time API。但是,即使在使用Java 8時,這也是一種奢侈,因爲您仍然可能仍在使用舊的Java Date/Time類與舊的API進行交互,或者僅僅因爲其餘的API仍然使用它們並且你不想開始混合東西。

這不是你的問題清楚,如果你已經知道這一點,你似乎是肯定要爲使用java.util.Datejava.sql.Timestamp,我沒問題,我就在你的問題的參數工作。

很明顯,新的Java日期/時間API比舊的API要好得多,但仍有數百萬行代碼仍在使用舊的API並且它們可以工作。再一次,我認爲這已經超出了答案的範圍,看來你已經有了其他好的答案來解決這個問題。

關於可能造成數據丟失

一條意見提到,答案可能會遇到數據丟失。我認爲在Java中,所有整數算術都有可能發生下溢或溢出。我的錯誤可能沒有提到它。

確實TimeUnit.convert方法可能最終會在某些情況下導致上溢或下溢。它在該方法中記錄。

  • 納秒是第二(1000000000分之1)十億分之一
  • 甲微秒是第二(1/1000000)百萬分之一。
  • 甲毫秒是第二(1/1000)

千分之一這意味着,一旦表達爲長,一毫秒數量應多於一個微秒一個小得多的數目,是嗎?

通過TimeUnit.convert使用的公式如下

final long MICROS = 1000000L; 
final long MILLIS = 1000L; 

long microsecs = 1474457086337977L; 
long millisecs = microsecs/(MICROS/MILLIS) 

這意味着你會遇到數據丟失,只有當您的微秒真的是小數目例如如果你的時間少於1000微秒。你應該驗證你的代碼永遠不會進入這樣的場景。

此答案中留下的一條評論認爲正確的答案應該可能使用納秒,但是接下來納秒長的值會比微秒長得多,所以在轉換爲納秒時,您可能仍會遇到溢出。

例如,想想如果你有Long.MAX_VALUE微秒會發生什麼,你怎麼可以將其轉換成使用純Java長算法,而不溢出納秒考慮到納秒應該是比你的Long.MAX_VALUE微秒一個更大的數字?

我的觀點的存在,不管你使用Java 8日期時間或遺留Java日期時間的API,你需要代表在時間線的瞬間long值,但long有關於限制多遠過去還是怎麼的在不遠的將來,你可以走了,當你這樣做單位之間的轉換,算術是受下溢和溢出,有沒有辦法解決它,你應該知道的是,爲了避免非常討厭的錯誤。

再次,我認爲這是一個給定的,問題的範圍之內,我把它僅僅是因爲我得到了這個遺漏一些downvotes。

+0

這就是我想要的。謝謝 – BDR

+0

知道['java.sql.Timestamp'](https://docs.oracle.com/javase/8/docs/api/java/sql/Timestamp.html)是一類錯誤的破解, java.util.Date「,但假裝沒有。推薦用於必要時將數據傳入/傳出數據庫,但不推薦用於業務邏輯。這個類是現在被java.time類取代的麻煩的舊日期時間類的一部分。 java.time類可以處理[納秒](https://en.wikipedia.org/wiki/Nanosecond)(甚至比微秒更好)。 –

+0

此答案的代碼**導致數據丟失**,將微秒截斷爲毫秒。儘管使用java.time是一條更好的路線,但如果堅持這種方法,那麼您可能需要通過調用['setNanos'](http://docs.oracle.com)來設置此Timestamp對象的納米字段,的.com/JavaSE的/ 7 /文檔/ API/JAVA/SQL/Timestamp.html#setNanos(INT))。 –

0

你可以試試下面的代碼,這將需要時間標記爲一個字符串:

BigInteger b = new BigInteger("1474457086337977"); 
b=b.divide(new BigInteger("1000")); 

String x =b.toString(); 



DateFormat formatter = new SimpleDateFormat("dd/MM/yyyy"); 

long milliSeconds= Long.parseLong(x); 
System.out.println(milliSeconds); 

Calendar calendar = Calendar.getInstance(); 
calendar.setTimeInMillis(milliSeconds); 
System.out.println(formatter.format(calendar.getTime())); 

還是爲了更準確,你可以使用的BigDecimal:

BigDecimal b = new BigDecimal("1474457086337977"); 
b=b.divide(new BigDecimal("1000")); 
String x =b.toString(); 
+0

感謝您的回覆。讓我試試看。 – BDR

+0

你的毫秒數太大。給出如下輸入:1474717464404 – Kaushal28

+0

哦你的字符串是在微秒內,然後將其轉換爲毫秒。 – Kaushal28

4

TL;博士

Instant.EPOCH.plus( 
    Duration.ofNanos( 
     TimeUnit.MICROSECONDS.toNanos( 
      Long.parse("1474457086337977")))) 

java.time

java.time類支持分辨率爲nanoseconds,綽綽有餘爲您microseconds

解析數

的字符串解析字符串作爲long擺脫時代微秒的計數。

long micros = Long.parse("1474457086337977"); 

當然,您始終可以使用整數字面量。請注意0​​附加到整數文字。

long micros = 1_474_457_086_337_977L ; 

轉換長成Instant

我們希望在UTC(1970-01-01T00:00:00Z)改造微秒是計數從1970年開始的epochInstant。該Instant類表示UTC時間軸與nanoseconds分辨率上一會兒。這意味着最多九位數的小數部分。

Instant類具有方便的靜態方法,用於從count of whole secondscount of whole seconds plus a fractional second in nanosecondscount of milliseconds轉換。但不幸的是沒有這樣的方法計數微秒或納秒。

作爲一種解決方法,我們可以定義一個Duration並將其添加到已定義爲常量的時期參考日期。我們可以將一個Duration實例化爲幾納秒。爲了得到納秒,我們將你的微秒乘以一千。請注意使用64位long而不是32位int

Duration duration = Duration.ofNanos(micros * 1_000L); 
Instant instant = Instant.EPOCH.plus(duration); 

instant.toString():2016-09-21T11:24:46.337977Z

或者,您可以使用TimeUnit枚舉微秒轉換爲納秒沒有硬編碼「幻數「。

Duration duration = Duration.ofNanos(TimeUnit.MICROSECONDS.toNanos(micros)); 

要調整到其他偏移或時區,搜索StackOverflow的Java類OffsetDateTimeZonedDateTime

轉換成傳統的日期 - 時間類型

你應該避免使用Java的早期版本中捆綁的舊日期 - 時間類型。事實證明,它們設計不佳,混亂且麻煩。現在由java.time類型取代。

但是,如果您必須與尚未更新爲java.time類型的舊代碼進行交互,則可以將其轉換爲/ from java.time。尋找新的方法添加到舊的類。

java.sql.Timestamp ts = java.sql.Timestamp.from(instant); 

從java.time類型轉換爲java.util.Datejava.util.Calendar時當心數據的丟失。這些類型只解析爲milliseconds。截止從納秒到毫秒的過程默默地進行,將最後六個(九個)可能的小數秒數字截掉。

java.util.Date utilDate = java.util.Date.from(instant); // Caution: Data loss in truncating nanoseconds to milliseconds. 

關於java.time

java.time框架是建立在Java 8和更高版本。這些類代替了令人討厭的舊日期時間類,例如java.util.Date,.Calendar,& java.text.SimpleDateFormat

Joda-Time項目現在位於maintenance mode,建議遷移到java.time。請參閱Oracle Tutorial。並搜索堆棧溢出了很多例子和解釋。

大部分的java.time功能後移植到Java 6 和ThreeTenABP還適於Android(見How to use…)。

ThreeTen-Extra項目擴展java.time與其他類。這個項目是未來可能增加java.time的一個試驗場。

+0

有趣的是,在你的回答中,'TimeUnit.MICROSECONDS.toNanos'受制於'TimeUnit.MICROSECONDS.toMillis'的相同問題。就在相反的方向。 toMillis轉換可能會下溢,在您的回答中,toNanos轉換可能會發生溢出。例如,如果你有'microsecs = Long.MAX_VALUE'。 –

+0

@EdwinDalorzo爲什麼任何人都有一個日期時間值作爲「Long.MAX_VALUE」微秒的計數時間? –

+0

您在使用'TimeUnit.convert'時在我的答案中留下了關於可能的數據丟失的評論。我認爲強調這個解決方案也不能解決問題是公平的。我以'Long.MAX_VALUE'爲例,但不需要達到該數字就可以獲得溢出。在哪些情況下才有意義?有關係嗎?當你突出顯示它時,我可以在我的答案中提出同樣的問題。但僅舉一個例子,天體計算可能很容易超過這個數字。 –