5

我有一个使用时间表的应用程序。用户选择时间表应该开始/结束的时间,然后我将开始/结束时间显示给用户。问题是,显示回来的时间是关闭的,因为 DST 改变了。

我可以解决我的时区(东部时间)的问题,或者我可以解决 GMT 的问题,如果我为 GMT 设置特定情况,阿拉斯加时间仍然是错误的。有什么建议么?

这是我的代码:

显示的时间:

long startTimeMillis = (startHour * 1000 * 60 * 60) + (startMin * 1000 * 60) - 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 小时,但阿拉斯加时间是正确的。

附录:

我也尝试过tz.getOffset(new Date().getTime())在每种情况下使用而不是tz.getRawOffset(). 这实际上是我尝试的第一件事,因为根据谷歌的文档,这个函数应该为你处理 DST。

结束附录

我也尝试过使用日历,如下所示:

Calendar calendar = GregorianCalendar.getInstance();

return calendar.get(Calendar.ZONE_OFFSET);

这给出了美国东部标准时间的正确时间,但格林威治标准时间提前 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();

我该如何正确地做到这一点???

4

2 回答 2

5

好的,我终于想出了如何正确地做到这一点。这就是我使它工作的方式:

long startTimeMillis = (startHour * 1000 * 60 * 60) + (startMinute * 1000 * 60);
startTimeMillis  -= getTimeOffset(startTimeMillis);

获取时间偏移():

public static int getTimeOffset(long time)
{
    TimeZone tz = TimeZone.getDefault();

    return tz.getOffset(time);
}
于 2013-03-18T12:57:18.103 回答
1

听起来您正在设置模拟器时区,您正在通过tz.getDefault(). 日历将在内部处理夏令时 - 如果它们设置为TimeZone完全遵守夏令时。一些 TimeZones,例如“America/Phoenix”和“MDT”不观察节省时间,而“America/Denver”有。

阿拉斯加时区通过从协调世界时 (UTC-9) 中减去九小时来观察标准时间。在夏令时期间,其时间偏移量为八小时 (UTC-8)。https://en.wikipedia.org/wiki/Alaska_Time_Zone

您可以使用TimeZone.getAvailableIDs()获取所有 TimeZone 名称/键的列表。查看 , , 之间America/AnchorageEtc/GMT+9区别America/Alaska

编辑:更新的代码这是一些示例代码,您可以通过几种方式来处理日期和 DST:

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 月 10 日观察到的“春季前进”时间添加 30 分钟时,一些时区会向前跳跃,而其他时区则不会。如果您选择这些遵守 DST 的时区,您将获得更改;而其他人不会。

TZ ID:美国/安克雷奇显示:阿拉斯加标准时间节省:3600000 偏移量:-32400000

美国/安克雷奇 2013 年 3 月 10 日星期日 1:30:00 AM AKST false

美国/安克雷奇 2013 年 3 月 10 日星期日 3:00:00 AM AKDT true

美国/安克雷奇 2013 年 3 月 10 日星期日 3:30:00 AM AKDT true

TZ ID:美国/朱诺显示:阿拉斯加标准时间节省:3600000 偏移量:-32400000

America/Juneau 2013 年 3 月 10 日星期日 1:30:00 AM AKST false

America/Juneau 2013 年 3 月 10 日星期日 3:00:00 AM AKDT true

America/Juneau 2013 年 3 月 10 日星期日 3:30:00 AM AKDT true

TZ ID:美国/Nome 显示:阿拉斯加标准时间节省:3600000 偏移量:-32400000

America/Nome 2013 年 3 月 10 日星期日 1:30:00 AM AKST false

America/Nome 2013 年 3 月 10 日星期日 3:00:00 AM AKDT true

America/Nome 2013 年 3 月 10 日星期日 3:30:00 AM AKDT true

TZ ID:美国/雅库塔特显示:阿拉斯加标准时间节省:3600000 偏移量:-32400000

America/Yakutat 2013 年 3 月 10 日星期日 1:30:00 AM AKST false

America/Yakutat 2013 年 3 月 10 日星期日 3:00:00 AM AKDT true

America/Yakutat 2013 年 3 月 10 日星期日 3:30:00 AM AKDT true

TZ ID:Etc/GMT+9 显示:GMT-09:00 储蓄:0 偏移:-32400000

等/GMT+9 2013 年 3 月 10 日星期日 1:30:00 AM GMT-09:00 false

等/GMT+9 2013 年 3 月 10 日星期日 2:00:00 AM GMT-09:00 false

等/GMT+9 2013 年 3 月 10 日星期日 2:30:00 AM GMT-09:00 false

TZ ID:Pacific/Gambier 显示:Gambier 节省时间:0 偏移量:-32400000

太平洋/甘比尔 2013 年 3 月 10 日星期日 1:30:00 AM GAMT 错误

太平洋/甘比尔 2013 年 3 月 10 日星期日 2:00:00 AM GAMT 错误

太平洋/甘比尔 2013 年 3 月 10 日星期日 2:30:00 AM GAMT 错误

TZ ID:SystemV/YST9 显示:阿拉斯加标准时间节省:0 偏移量:-32400000

SystemV/YST9 2013 年 3 月 10 日星期日 1:30:00 AM AKST 错误

SystemV/YST9 2013 年 3 月 10 日星期日 2:00:00 AM AKST 错误

SystemV/YST9 2013 年 3 月 10 日星期日 2:30:00 AM 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 AM AKST 错误

TZ ID:美国/阿拉斯加显示:阿拉斯加标准时间节省:3600000 偏移量:-32400000

美国/阿拉斯加 2013 年 3 月 10 日星期日 1:30:00 AM AKST false

美国/阿拉斯加 2013 年 3 月 10 日星期日 3:00:00 AM AKDT true

美国/阿拉斯加 2013 年 3 月 10 日星期日 3:30:00 AM AKDT true

我还推荐http://www.worldtimeserver.com,因为它可以让您将结果与应有的结果进行比较。

于 2013-03-16T18:17:06.070 回答