有沒有一種快速,低垃圾的方式來做到這一點?我不能只做簡單的模數算術,因爲這不能解釋閏秒和其他日期/時間有趣的業務。如何將Java時代以來的秒數轉換爲小時/分鐘/秒?
回答
這是一個快速,零垃圾的解決方案。在每個調用中不要創建Calendar
的新實例是非常重要的,因爲它是一個相當重的對象,需要448個字節的堆並且幾乎需要微妙的初始化(Java 6,64位HotSpot,OS X)。
HmsCalculator
旨在用於單個線程(每個線程必須使用不同的實例)。
public class HmsCalculator
{
private final Calendar c = Calendar.getInstance();
public Hms toHms(long t) { return toHms(t, new Hms()); }
public Hms toHms(long t, Hms hms) {
c.setTimeInMillis(t*1000);
return hms.init(c);
}
public static class Hms {
public int h, m, s;
private Hms init(Calendar c) {
h = c.get(HOUR_OF_DAY); m = c.get(MINUTE); s = c.get(SECOND);
return this;
}
public String toString() { return String.format("%02d:%02d:%02d",h,m,s); }
}
public static void main(String[] args) {
System.out.println(new HmsCalculator().toHms(
System.currentTimeMillis()/1000));
}
}
P.S.我沒有粘貼所有這些靜態導入(無聊)。
我不能只是做簡單的模數算術,因爲它不佔用閏秒和其他日期/時間有趣的業務。
的Java 不佔閏秒一般 - 或者更確切地說,正式這是走上講臺,但我不相信這是在任何的共同生產平臺上實現。你確定你需要來計算閏秒嗎?如果你這樣做,你應該能夠做一個簡單的基於表的查詢秒數來添加或刪除,這取決於你的數據源是什麼以及你希望它反映什麼。
至於「其他日期/時間有趣的業務」 - 我不認爲有是這個特定的計算任何有趣的業務。例如,時區自從時代開始經歷的時間是不相關的。
時區與時代以來秒無關,但轉換爲本地HH:MM:SS時並非無關緊要。不過,這只是一個不變的抵消,所以沒有什麼大不了的。 –
@ user939259:我認爲你的意思是「小時,分鐘,秒」,因爲這個時代......你的問題很不清楚。如果你的意思是你想將時間戳轉換爲本地時間,那麼你可以使用'java.util.Date'和'java.util.Calendar',或者最好是Joda Time。 –
與假設 「劃時代」 你的意思是01-01-1970 00:00:00 GMT:
long secondsSinceEpoch = ...;
// The constructor of Date expects milliseconds
// since 01-01-1970, 00:00:00 GMT
Date date = new Date(secondsSinceEpoch * 1000L);
DateFormat df = new SimpleDateFormat("dd/MM/yyyy");
System.out.println(df.format(date));
低垃圾?我想不是。 –
@MarkoTopolnik解釋?你創建的唯一的東西是一個Date對象(不考慮用SimpleDateFormat格式化)。這不是很貴。 – Jesper
Date,SimpleDateFormat,兩者的內部結構。這並不是那麼簡單,結果仍然是一個字符串而不是數字元組。加上OP說他只想要HMS,也許他的意思是自從時代以來的幾個小時?目前尚不清楚。 –
Calendar = Calendar.getInstance();
calendar.setTimeInMillis(secondsSinceTheEpoch*1000);
我已經想出瞭如何處理整數算術中的閏年,並實現了從時代到日期/時間(儘管它永遠不會超過59秒)的轉換器。下面的C代碼應該很容易移植到Java。
#include <string.h>
#include <time.h>
typedef unsigned uint;
typedef unsigned long long uint64;
struct tm* SecondsSinceEpochToDateTime(struct tm* pTm, uint64 SecondsSinceEpoch)
{
uint64 sec;
uint quadricentennials, centennials, quadrennials, annuals/*1-ennial?*/;
uint year, leap;
uint yday, hour, min;
uint month, mday, wday;
static const uint daysSinceJan1st[2][13]=
{
{0,31,59,90,120,151,181,212,243,273,304,334,365}, // 365 days, non-leap
{0,31,60,91,121,152,182,213,244,274,305,335,366} // 366 days, leap
};
/*
400 years:
1st hundred, starting immediately after a leap year that's a multiple of 400:
n n n l \
n n n l } 24 times
... /
n n n l/
n n n n
2nd hundred:
n n n l \
n n n l } 24 times
... /
n n n l/
n n n n
3rd hundred:
n n n l \
n n n l } 24 times
... /
n n n l/
n n n n
4th hundred:
n n n l \
n n n l } 24 times
... /
n n n l/
n n n L <- 97'th leap year every 400 years
*/
// Re-bias from 1970 to 1601:
// 1970 - 1601 = 369 = 3*100 + 17*4 + 1 years (incl. 89 leap days) =
// (3*100*(365+24/100) + 17*4*(365+1/4) + 1*365)*24*3600 seconds
sec = SecondsSinceEpoch + 11644473600LL;
wday = (uint)((sec/86400 + 1) % 7); // day of week
// Remove multiples of 400 years (incl. 97 leap days)
quadricentennials = (uint)(sec/12622780800ULL); // 400*365.2425*24*3600
sec %= 12622780800ULL;
// Remove multiples of 100 years (incl. 24 leap days), can't be more than 3
// (because multiples of 4*100=400 years (incl. leap days) have been removed)
centennials = (uint)(sec/3155673600ULL); // 100*(365+24/100)*24*3600
if (centennials > 3)
{
centennials = 3;
}
sec -= centennials * 3155673600ULL;
// Remove multiples of 4 years (incl. 1 leap day), can't be more than 24
// (because multiples of 25*4=100 years (incl. leap days) have been removed)
quadrennials = (uint)(sec/126230400); // 4*(365+1/4)*24*3600
if (quadrennials > 24)
{
quadrennials = 24;
}
sec -= quadrennials * 126230400ULL;
// Remove multiples of years (incl. 0 leap days), can't be more than 3
// (because multiples of 4 years (incl. leap days) have been removed)
annuals = (uint)(sec/31536000); // 365*24*3600
if (annuals > 3)
{
annuals = 3;
}
sec -= annuals * 31536000ULL;
// Calculate the year and find out if it's leap
year = 1601 + quadricentennials * 400 + centennials * 100 + quadrennials * 4 + annuals;
leap = !(year % 4) && (year % 100 || !(year % 400));
// Calculate the day of the year and the time
yday = sec/86400;
sec %= 86400;
hour = sec/3600;
sec %= 3600;
min = sec/60;
sec %= 60;
// Calculate the month
for (mday = month = 1; month < 13; month++)
{
if (yday < daysSinceJan1st[leap][month])
{
mday += yday - daysSinceJan1st[leap][month - 1];
break;
}
}
// Fill in C's "struct tm"
memset(pTm, 0, sizeof(*pTm));
pTm->tm_sec = sec; // [0,59]
pTm->tm_min = min; // [0,59]
pTm->tm_hour = hour; // [0,23]
pTm->tm_mday = mday; // [1,31] (day of month)
pTm->tm_mon = month - 1; // [0,11] (month)
pTm->tm_year = year - 1900; // 70+ (year since 1900)
pTm->tm_wday = wday; // [0,6] (day since Sunday AKA day of week)
pTm->tm_yday = yday; // [0,365] (day since January 1st AKA day of year)
pTm->tm_isdst = -1; // daylight saving time flag
return pTm;
}
不錯的工作!這正是我需要的。爲了確認,夾具百歲/四足動物/年度檢查只是爲了您在開發期間的正確性?它在數學上看起來不會發生。同樣,在你每次做'sec - = duration * secs',這相當於使用'%' - 你使用'quadricentennials',只是一個小小的不一致。我會爲他們選擇' - ='或'%='。 – David
@Dave他們是爲了理智,是的,但最重要的是正確性。 :)嘗試刪除它們並重新運行ideone上的小測試代碼。 978307199 =「Sun Dec 31 23:59:59 2000」變爲978307199 =「Sun Jan 1 23:59:59 2001」,但是978307199 + 1 =「Mon Jan 1 00:00:00 2001」保持不變。 2000年的最後一秒距離160年1月1日不到400年(對嗎?只是比較幾年),但距離1/1/1601(即365.24天長的年份)超過4 * 100年, 。通過移除第一個夾具,您將無法正確地解釋每隔400年的第97個閏年,這裏是我們的案例。 –
在我的32位版本,我不得不改變一行。這一行:'sec = SecondsSinceEpoch + 11644473600;'必須是'sec = SecondsSinceEpoch + 11644473600LL;'。注意''LL',因爲它會在32位版本上失敗。如果「long long」類型是64位寬,肯定會起作用。 –
java.time
從Java 8及更高版本,內置類使用的是Instant
從java.time框架。
Instant instant = Instant.ofEpochSecond (1_469_168_058L);
轉儲到控制檯。
System.out.println ("instant: " + instant);
瞬間:2016-07-22T06:14:18Z
性能
我不知道究竟在速度的執行中或方面如何java.time.Instant
執行垃圾生產。但是你應該對這個班級進行考試。在我細讀the source code in Java 9時,它看起來非常簡單和快速。 (a)來自曆元(64位long
)的秒數和(b)作爲秒的分數(a)的秒數(b) 32位int
),在做了幾次快速檢查之後:
首先查找零值,在這種情況下,它會爲紀元本身返回一個靜態實例。
if ((seconds | nanoOfSecond) == 0) {
return EPOCH;
}
其次對與最小/最大常量對的秒數進行完整性檢查。
if (seconds < MIN_SECOND || seconds > MAX_SECOND) {
throw new DateTimeException("Instant exceeds minimum or maximum instant");
}
然後調用構造,其對整數值指派給一對的成員變量(long
和int
原語分別地)的。
this.seconds = epochSecond;
this.nanos = nanos;
當然,這只是施工。詢問諸如時間之類的部分意味着更多的工作。正如通過toString
方法生成一個字符串涉及另一個類,DateTimeFormatter
。 toString
源代碼是一行。
return DateTimeFormatter.ISO_INSTANT.format(this);
請記住,如果你想要的部分,如年,月,日的日,小時,等的不是UTC以外的時區,這意味着涉及ZoneId
和ZonedDateTime
類更多的工作。例如:
ZoneId zoneId = ZoneId.of("America/Montreal");
ZonedDateTime zdt = instant.atZone(zoneId);
- 1. 將秒轉換爲小時和分鐘
- 2. 如何將秒轉換爲小時分鐘和秒?
- 3. 如何將小時,分鐘和秒轉換爲秒
- 4. 如何將秒轉換爲小時:分鐘:秒在php
- 5. 將秒轉換爲分鐘,小時和天的Java代碼
- 6. C++轉換小時,分鐘,秒到秒
- 7. php - 轉換小時:分鐘:秒。秒
- 8. 將負秒轉換爲小時:分:秒
- 9. 將秒轉換爲天:小時:分鐘:秒
- 10. 將毫秒轉換爲小時,分鐘和秒python
- 11. 將秒轉換爲小時,分鐘,seconds.hundreths第二秒
- 12. 如何將毫秒,秒,分鐘,小時轉換爲SQL Server 2005中的天數?
- 13. 如何在JavaScript中將時間毫秒轉換爲小時,分鐘,秒格式?
- 14. 如何將秒分別轉換爲年,月,日,小時,分鐘?
- 15. 以小時,分鐘,秒鐘(以秒爲單位)獲取時間
- 16. 將分鐘轉換爲小時,分鐘和秒
- 17. 將秒數轉換爲總時數:分鐘:秒
- 18. Java/Android:以毫秒爲單位轉換小時,分鐘和秒的本機API
- 19. 將小時,分鐘,秒轉換爲小時字符串
- 20. SQL將秒數轉換爲分鐘數到小時數
- 21. 如何將270921sec轉換爲天+小時+分鐘+秒? (紅寶石)
- 22. 如何在SQL中將分鐘轉換爲小時分鐘和秒鐘?
- 23. Java將秒轉換爲年日小時分秒
- 24. 將十進制表示時間轉換爲小時,分鐘,秒
- 25. 如何將秒數轉換成Bash中的分鐘和秒鐘?
- 26. 將工作秒數轉換爲周,天,小時和分鐘
- 27. 將分鐘轉換爲毫秒Java/android
- 28. 將ISO8601(我認爲)轉換爲小時:分鐘:Powershell中的秒
- 29. NSString如何將小時轉換爲秒
- 30. 自Unix時代以來,將時間戳記轉換爲秒數
該解決方案是非線程安全的。 –
@ChristofferHammarström現在我們都知道你沒有讀過最後一句答案:) –
哦,對。這顯然不明顯,所以我解決了它,我希望你不介意。 –