8

我有一个需要了解时区的 Java 应用程序。当我采用 Unix 纪元时间并尝试将其转换为用于 Oracle SQL 调用的时间戳时,它正在获取正确的时区,但时区“useDaylightTime”值不正确,即当前返回“true” ,当我们不在 DST 时(我在佛罗里达州的 TZ“America/New_York”)。

这是在 Red Hat Linux Enterprise 6 上运行的,据我所知,它正确设置为时区,例如“日期”返回:Wed Nov 28 12:30:12 EST 2012

我还可以看到,使用“zdump”实用程序,“isdst”的当前值为 0。

我的 Java 版本是 1.6.0_31。

我已经用谷歌搜索了这个并看到了这导致的许多问题,但他们中的许多人只是说手动设置 TZ,但我的问题不是 TZ,而是默认 TZ 将“isDaylight”设置为“true”这一事实. 我相信这导致我的查询返回一个小时后的数据(我可以看到它是)。

这是我运行的一个简单的代码片段,试图以最简单的方式重现它:

public class TZdefault {

    public static void main(String[] args) throws IOException {

            long startTime = System.currentTimeMillis()/1000;

            Calendar start = Calendar.getInstance();
            start.setTimeInMillis(startTime);

            start.setTimeZone(TimeZone.getDefault());

            System.out.println("Start UTC: " + start + "ms: " + start.getTimeInMillis());
            System.out.println("use daylight: " + start.getTimeZone().useDaylightTime());

    } // end main


}  // end class

最后一件事。如果在我的代码中我将 TZ 设置为“EST”,它当然返回一个将“isDaylight”设置为 False 的 TZ。但这不是一个好的解决方案。

我想添加一些我一直希望隐藏的细节。

我在使用 TIMESTAMP 和 TIMEZONE 字段的 Oracle 11g 数据库中有记录。我只是在做 JDBC 查询,其中两个参数使用 BETWEEN 开始时间戳和结束时间戳。

当我查询此表时,我使用的是使用日历条目的准备好的语句,其唯一目的是尝试和操作时区。最重要的是,在应用“默认”时区后,我正在使用“getTimeInMillis”方法对开始和结束时间进行 pstmt.setTimestamp() 调用。日志输出显示,实际上它输入了正确的毫秒数,但返回的 SQL 结果显然相差一小时!

我仍在尝试验证数据插入方面是否也没有问题。

但是我有很多调试信息,看起来我在 JDBC 查询中要求正确的时间。

4

4 回答 4

13

时区useDaylightTime值不正确,即,当我们不在 DST 时,它当前返回“true”

我认为您useDaylightTimeinDaylightTime. 前者告诉您将来是否在日光时间和标准时间之间存在过渡,而不是您处于过渡的哪一边。例如,对于中国时区,它返回 false,因为中国不针对夏令时进行调整,但对于大多数美国时区,它返回 true,因为大多数美国州(亚利桑那州除外)都遵守夏令时。

inDaylightTime

public abstract boolean inDaylightTime(Date date)

查询给定日期是否在该时区的夏令时。

对比

useDaylightTime

public abstract boolean useDaylightTime()

查询此 TimeZone 是否使用夏令时。如果底层 TimeZone 实现子类支持历史和未来的夏令时时间表更改,则此方法引用最后一个已知的夏令时规则,该规则可以是未来的预测,并且可能与当前规则不同。observesDaylightTime()如果还应考虑当前规则,请考虑调用。

于 2012-11-28T18:10:08.377 回答
5

如果要禁用夏令时计算,则必须将时区设置为 EST。否则时间将根据为 AMERICA/NEW_YORK 设置的默认时区计算

       TimeZone zoneEST = TimeZone.getTimeZone("EST"); 
       System.out.println(zoneEST.getDSTSavings());  //0 hour
       System.out.println(zoneEST.getRawOffset());  //5 hour
       TimeZone.setDefault(zoneEST);
       System.out.println("");

       TimeZone zoneNY = TimeZone.getTimeZone("America/New_York");
       System.out.println(zoneNY.getDSTSavings()); // 1 hour
       System.out.println(zoneNY.getRawOffset()); // 5 hour
于 2012-11-28T18:04:13.800 回答
3

我找到了一种方法来确保忽略夏令时

TimeZone tz = TimeZone.getTimeZone("GMT");
TimeZone.setDefault(tz);
GregorianCalendar calendar;
calendar = new GregorianCalendar();

在创建 GregorianCalendar 对象之前设置时区

于 2014-05-24T23:25:33.980 回答
0
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

public class TimeZoneTest {
    public static void main(String[] argv) throws ParseException {

        SimpleDateFormat formatter = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");

        String dateInString = "22-01-2015 10:15:55 AM";
        Date date = formatter.parse(dateInString);
        TimeZone tz = TimeZone.getDefault();

        // From TimeZone Asia/Singapore
        System.out.println("TimeZone : " + tz.getID() + " - " + tz.getDisplayName());
        System.out.println("TimeZone : " + tz);
        System.out.println("Date : " + formatter.format(date));

        // To TimeZone America/New_York
        SimpleDateFormat sdfAmerica = new SimpleDateFormat("dd-M-yyyy hh:mm:ss a");
        TimeZone tzInAmerica = TimeZone.getTimeZone("America/New_York");
        sdfAmerica.setTimeZone(tzInAmerica);

        String sDateInAmerica = sdfAmerica.format(date); // Convert to String first
        Date dateInAmerica = formatter.parse(sDateInAmerica);

        System.out.println("\nTimeZone : " + tzInAmerica.getID() + 
                                      " - " + tzInAmerica.getDisplayName());
        System.out.println("TimeZone : " + tzInAmerica);
        System.out.println("Date (String) : " + sDateInAmerica);
        System.out.println("Date (Object) : " + formatter.format(dateInAmerica)); 
    }

}
于 2015-04-15T10:39:01.617 回答