Android时区和DST问题

时间:2013-03-16 15:56:23

标签: android dst timezone-offset

我有一个使用时间表的应用程序。用户选择计划应该开始/结束的时间,并且我将该开始/结束时间显示给用户。问题是,自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();

我该怎么做呢???

2 个答案:

答案 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/AnchorageEtc/GMT+9America/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,因为它可以让您将结果与应该的结果进行比较。