我有一个使用时间表的应用程序。用户选择计划应该开始/结束的时间,并且我将该开始/结束时间显示给用户。问题是,自DST更改以来,显示的时间已关闭。
我可以解决我的时区(东部时间)的问题,或者我可以解决GMT的问题,如果我为GMT设置一个特定的案例,阿拉斯加时间仍然是错误的。有什么建议吗?
这是我的代码:
显示的时间:
long startTimeMillis = (startHour * 1000 * 60 * 60) + (startMin * 1000 * 60) - getTimeOffset();
getTimeOffset:
TimeZone tz = TimeZone.getDefault();
//deal with GMT weirdness
if (tz.getRawOffset() == 0)
return tz.getRawOffset() + tz.getDSTSavings();
else
return tz.getRawOffset();
我认为我需要这样的东西:
else if(tz.inDaylightTime(new Date()))
return tz.getRawOffset() + tz.getDSTSavings();
但如果我这样做,那么东部时间比它应该少1小时,阿拉斯加时间显示少2小时。如果我做相反的事情:( - 而不是+)
else if(tz.inDaylightTime(new Date()))
return tz.getRawOffset() - tz.getDSTSavings();
然后东部时间比它应该多1小时,但阿拉斯加的时间是正确的。
ADDENDUM:
我也尝试在每种情况下使用tz.getOffset(new Date().getTime())
而不是tz.getRawOffset()
。这实际上是我尝试的第一件事,因为根据谷歌的文档,这个功能应该为你处理DST。
END ADDENDUM
我也尝试过使用Calendars,如下所示:
Calendar calendar = GregorianCalendar.getInstance();
return calendar.get(Calendar.ZONE_OFFSET);
这给出了EST时间的正确时间,但GMT提前1小时,阿拉斯加提前1小时。我试过这个:
if(tz.inDaylightTime(new Date()))
return calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
else
return calendar.get(Calendar.ZONE_OFFSET);
但这让EDT短短1小时。
我也试过这个:
return tz.getOffset(calendar.get(Calendar.ERA),
calendar.get(Calendar.YEAR),
calendar.get(Calendar.MONTH),
calendar.get(Calendar.DAY_OF_MONTH),
calendar.get(Calendar.DAY_OF_WEEK),
calendar.get(Calendar.MILLISECOND));
也让EDT短了1小时。
如果我使用
,我会得到相同的结果GregorianCalendar calendar = new GregorianCalendar(tz);
而不是
Calendar calendar = GregorianCalendar.getInstance();
我该怎么做呢???
答案 0 :(得分:5)
好的,我终于想出了如何正确地做到这一点。这就是我的工作方式:
long startTimeMillis = (startHour * 1000 * 60 * 60) + (startMinute * 1000 * 60);
startTimeMillis -= getTimeOffset(startTimeMillis);
getTimeOffset():
public static int getTimeOffset(long time)
{
TimeZone tz = TimeZone.getDefault();
return tz.getOffset(time);
}
答案 1 :(得分:1)
听起来您正在设置模拟器时区,您正通过tz.getDefault()
检索该时区。日历将在内部处理夏令时 - 如果它们设置为TimeZone
,则可以观察到夏令时。一些时区,例如“America / Phoenix”和“MDT”没有观察到节省时间,而“America / Denver”则表示节省时间。
阿拉斯加时区通过从世界协调时间(UTC-9)减去9小时来观察标准时间。在夏令时期间,其时间偏移为8小时(UTC-8)。 https://en.wikipedia.org/wiki/Alaska_Time_Zone
您可以使用TimeZone.getAvailableIDs()
获取所有TimeZone名称/键的列表。查看America/Anchorage
,Etc/GMT+9
,America/Alaska
之间的差异。
编辑:更新代码以下是一些示例代码,您可以通过几种方式使用日期和夏令时:
package com.codeshane.examples;
import java.text.DateFormat;
import java.util.Calendar;
import java.util.TimeZone;
public class Times {
public static final String[] yourZoneKeys =
{"America/Anchorage", "America/Juneau", "America/Nome", "America/Yakutat",
"Etc/GMT+9", "Pacific/Gambier", "SystemV/YST9", "SystemV/YST9YDT","US/Alaska"};
public static void main(String[] args){
for (String timezoneKey: yourZoneKeys){
TimeZone tz = getSelectedTimezone(timezoneKey);
displayTimezoneInfo(tz);
showTimeInNewCalendar(tz);
}
}
static void displayTimezoneInfo(TimeZone tz){
System.out.println(
"\n> TZ ID:" + tz.getID() +
" Display:" + tz.getDisplayName() +
" savings:" + tz.getDSTSavings() +
" offset:" + tz.getRawOffset() +
""
);
}
static void showTimeInNewCalendar(TimeZone tz) {
DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL);
/***** DST US 2013 = Mar 10 - Nov 3
* Daylight Saving Time (United States) 2013
* began at 2:00 AM on Sunday, March 10
* ends at 2:00 AM on Sunday, November 3
**/
//The Calendar method output the same results, but since both
//methods went through the DateFormat, I went ahead and just
//used the DateFormat's internal date via getCalendar().set(..)
//but left the Calendar code (commented out) for you to compare.
//Calendar gc = Calendar.getInstance();
//gc.setTimeZone(tz);
//gc.set(2013, 2, 10, 1, 30, 0);
// Setting the Calendar's date and time
df.getCalendar().set(2013, 2, 10, 1, 30, 0);
// Display some times at 30 minute intervals
for (int i =0;i<3;i++){
df.setTimeZone(tz);
System.out.println(
"\n " + tz.getID() +
" " + df.format(df.getCalendar().getTime()) +// sdf. .format(myDateFormat, gc) +
//" gc date:" + df.format(gc.getTime()) +
" " + tz.inDaylightTime(df.getCalendar().getTime()) +
""
);
df.getCalendar().add(Calendar.MINUTE, 30);
//gc.add(Calendar.MINUTE, 30);
}
}
private static TimeZone getSelectedTimezone(String timezoneKey){
if (null==timezoneKey) return TimeZone.getDefault(); // system/network-provided
return TimeZone.getTimeZone(timezoneKey); // Gets specified tz, or "GMT" if tzKey is invalid
}
}
编辑:添加输出你会注意到在我们刚刚在2013年3月3日观察到的“春季前进”时间增加了30分钟时,一些时区正在向前推进,而其他人则不知道吨。如果您选择观察DST的这些时区,您将获得更改;而其他人不会。
TZ ID:美国/安克雷奇显示:阿拉斯加标准时间节省:3600000偏移:-32400000
America / Anchorage 2013年3月10日星期日凌晨1:30:00 AKST false
America / Anchorage 2013年3月10日星期日上午3:00:00 AKDT true
America / Anchorage 2013年3月10日星期日上午3:30:00 AKDT true
TZ ID:America / Juneau Display:阿拉斯加标准时间节省:3600000抵消:-32400000
America / Juneau 2013年3月10日星期日凌晨1:30:00 AKST false
America / Juneau 2013年3月10日星期日凌晨3:00:00 AKDT true
America / Juneau 2013年3月10日星期日凌晨3:30:00 AKDT true
TZ ID:America / Nome Display:阿拉斯加标准时间节省:3600000抵消:-32400000
America / Nome 2013年3月10日星期日凌晨1:30:00 AKST false
America / Nome 2013年3月10日星期日3:00:00 AM AKDT true
America / Nome 2013年3月10日星期日3:30:00 AKDT true
TZ ID:America / Yakutat显示:阿拉斯加标准时间节省:3600000偏移:-32400000
America / Yakutat 2013年3月10日星期日凌晨1:30:00 AKST false
America / Yakutat 2013年3月10日星期日凌晨3:00:00 AKDT true
America / Yakutat 2013年3月10日星期日凌晨3:30:00 AKDT true
TZ ID:Etc / GMT + 9显示:GMT-09:00节省:0抵消:-32400000
Etc / GMT + 9 2013年3月10日星期日凌晨1:30:00 GMT-09:00假
Etc / GMT + 9 2013年3月10日星期日凌晨2点00分GMT-09:00假
Etc / GMT + 9 2013年3月10日星期日凌晨2:30:00 GMT-09:00假
TZ ID:Pacific / Gambier显示:Gambier节省时间:0偏移量:-32400000
Pacific / Gambier 2013年3月10日星期日凌晨1:30:00 GAMT false
Pacific / Gambier 2013年3月10日星期日上午2:00:00 GAMT false
Pacific / Gambier 2013年3月10日星期日凌晨2:30:00 GAMT false
TZ ID:SystemV / YST9显示:阿拉斯加标准时间节省:0偏移:-32400000
SystemV / YST9 2013年3月10日星期日凌晨1:30:00 AKST错误
SystemV / YST9 2013年3月10日星期日上午2:00:00 AKST错误
SystemV / YST9 2013年3月10日星期日上午2:30:00 AKST错误
TZ ID:SystemV / YST9YDT显示:阿拉斯加标准时间节省:3600000偏移量:-32400000
SystemV / YST9YDT 2013年3月10日星期日凌晨1:30:00 AKST错误
SystemV / YST9YDT 2013年3月10日星期日2:00:00 AM AKST false
SystemV / YST9YDT 2013年3月10日星期日上午2:30:00 AKST错误
TZ ID:美国/阿拉斯加州显示:阿拉斯加标准时间节省:3600000抵消:-32400000
美国/阿拉斯加2013年3月10日星期日凌晨1:30:00 AKST错误
美国/阿拉斯加2013年3月10日星期日凌晨3:00:00 AKDT真实
美国/阿拉斯加2013年3月10日星期日凌晨3:30:00 AKDT真实
我还建议使用http://www.worldtimeserver.com
,因为它可以让您将结果与应该的结果进行比较。