[英]How to tackle daylight savings using TimeZone in Java
我必須在我的 Java 應用程序中打印 EST 時間。 我已使用以下方法將時區設置為 EST:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));
但是當在這個時區遵循夏令時時,我的代碼沒有打印正確的時間(它打印的時間少了 1 小時)。
無論是否遵守夏令時,如何使代碼始終讀取正確的時間?
PS:我嘗試將時區設置為 EDT,但並沒有解決問題。
這是開始的問題:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));
應完全避免使用 3 個字母的縮寫,以支持 TZDB 區域 ID。 EST 是東部標准時間 -標准時間從不遵守 DST; 它並不是一個完整的時區名稱。 它是用於部分時區的名稱。 (不幸的是,我沒有遇到過這個“半時區”概念的好詞。)
您需要完整的時區名稱。 例如, America/New_York
位於東部時區:
TimeZone zone = TimeZone.getTimeZone("America/New_York");
DateFormat format = DateFormat.getDateTimeInstance();
format.setTimeZone(zone);
System.out.println(format.format(new Date()));
其他答案是正確的,尤其是Jon Skeet 的答案,但已過時。
這些舊的日期時間類已被 Java 8 及更高版本中內置的java.time框架所取代。
如果您只需要 UTC 中的當前時間,請使用Instant
類。
Instant now = Instant.now();
EST
不是時區,正如Jon Skeet在正確答案中所解釋的那樣。 這種 3-4 個字母的代碼既不標准化也不唯一,並且進一步混淆了夏令時 (DST)。 使用“大洲/地區”格式的正確時區名稱。
也許您指的是北美東海岸的東部標准時間? 還是埃及標准時間? 還是歐洲標准時間?
ZoneId zoneId = ZoneId.of( "America/New_York" );
ZoneId zoneId = ZoneId.of( "Africa/Cairo" );
ZoneId zoneId = ZoneId.of( "Europe/Lisbon" );
使用任何此類ZoneId
對象將當前時刻調整為特定時區以生成ZonedDateTime
對象。
ZonedDateTime zdt = ZonedDateTime.now( zoneId ) ;
通過從第一個對象生成另一個 ZonedDateTime 對象,將該 ZonedDateTime 調整到不同的時區。 java.time 框架使用不可變對象而不是更改(變異)現有對象。
ZonedDateTime zdtGuam = zdt.withZoneSameInstant( ZoneId.of( "Pacific/Guam" ) ) ;
您可以輸入“EST5EDT”,而不是輸入“EST”作為時區。 正如您所指出的,僅“EDT”不起作用。 這將解釋夏令時問題。 代碼行如下所示:
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST5EDT"));
根據這個答案:
TimeZone tz = TimeZone.getTimeZone("EST");
boolean inDs = tz.inDaylightTime(new Date());
private static Long DateTimeNowTicks(){
long TICKS_AT_EPOCH = 621355968000000000L;
TimeZone timeZone = Calendar.getInstance().getTimeZone();
int offs = timeZone.getRawOffset();
if (timeZone.inDaylightTime(new Date()))
offs += 60 * 60 * 1000;
return (System.currentTimeMillis() + offs) * 10000 + TICKS_AT_EPOCH;
}
public static float calculateTimeZone(String deviceTimeZone) {
float ONE_HOUR_MILLIS = 60 * 60 * 1000;
// Current timezone and date
TimeZone timeZone = TimeZone.getTimeZone(deviceTimeZone);
Date nowDate = new Date();
float offsetFromUtc = timeZone.getOffset(nowDate.getTime()) / ONE_HOUR_MILLIS;
// Daylight Saving time
if (timeZone.useDaylightTime()) {
// DST is used
// I'm saving this is preferences for later use
// save the offset value to use it later
float dstOffset = timeZone.getDSTSavings() / ONE_HOUR_MILLIS;
// DstOffsetValue = dstOffset
// I'm saving this is preferences for later use
// save that now we are in DST mode
if (timeZone.inDaylightTime(nowDate)) {
Log.e(Utility.class.getName(), "in Daylight Time");
return -(ONE_HOUR_MILLIS * dstOffset);
} else {
Log.e(Utility.class.getName(), "not in Daylight Time");
return 0;
}
} else
return 0;
}
在java中,DateFormatter默認使用DST,為了避免夏令時(DST),你需要手動做一個技巧,
首先,您必須獲得 DST 偏移量,即應用了多少毫秒的 DST,例如某處 DST 也是 45 分鍾,而某些地方則是 30 分鍾
但在大多數情況下,夏令時為 1 小時
您必須使用 Timezone 對象並檢查日期是否屬於 DST,然后您必須手動將 DST 的偏移量添加到其中。 例如:
TimeZone tz = TimeZone.getTimeZone("EST");
boolean isDST = tz.inDaylightTime(yourDateObj);
if(isDST){
int sec= tz.getDSTSavings()/1000;// for no. of seconds
Calendar cal= Calendar.getInstance();
cal.setTime(yourDateObj);
cal.add(Calendar.Seconds,sec);
System.out.println(cal.getTime());// your Date with DST neglected
}
實現 TimeZone 類以將時區設置為 Calendar 負責夏令時。
java.util.TimeZone 表示時區偏移量,並計算夏令時。
示例代碼:
TimeZone est_timeZone = TimeZoneIDProvider.getTimeZoneID(TimeZoneID.US_EASTERN).getTimeZone();
Calendar enteredCalendar = Calendar.getInstance();
enteredCalendar.setTimeZone(est_timeZone);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.