我有一个需要了解时区的Java应用程序。当我获取Unix纪元时间并尝试将其转换为用于Oracle SQL调用的时间戳时,它获得了正确的时区,但时区“useDaylightTime”值不正确,即它当前返回“true” ,当我们不在夏令时(我在佛罗里达州的TZ“America / New_York”)。
这是在Red Hat Linux Enterprise 6上运行的,据我所知, 正确设置了时区,例如: 'date'返回: 11月28日星期三12:30:12 2012年
我还可以使用'zdump'实用程序看到'isdst'的当前值为0。
我的Java版本是1.6.0_31。
我已经用Google搜索了这个,并看到了这引起的众多问题,但他们中的许多人只是简单地说要手动设置TZ,但我的问题不是TZ,而是默认TZ将“isDaylight”设置为'真正'。我相信这导致我的查询返回一小时关闭的数据(我可以看到它是。)
这是一个简单的代码片段,我试图以最简单的方式重现这个:
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”,它当然 返回一个TZ,其中'isDaylight'设置为False。但这不是一个好的解决方案。
我想添加一些我一直希望隐藏的细节。
我在Oracle 11g数据库中有记录,它使用TIMESTAMP和TIMEZONE字段。我只是在进行JDBC查询,其中两个参数使用BETWEEN开始时间戳和结束时间戳。
当我查询这个表时,我正在使用一个使用Calendar条目的预准备语句,其唯一目的是尝试操作时区。底线是我在应用“默认”时区后的开始和结束时间使用'getTimeInMillis'方法进行pstmt.setTimestamp()调用。日志输出显示实际上它正在输入正确的毫秒数,但返回的SQL结果显然已经完全关闭了一个小时!
我仍在尝试验证数据插入方面是否存在问题。
但是我有很多调试信息,看起来我在JDBC查询中要求正确的时间。
答案 0 :(得分:10)
时区
useDaylightTime
值不正确,即当我们不在DST时它正在返回“true”
我认为你将useDaylightTime
与inDaylightTime
混为一谈。前者告诉您将来日光时间和标准时间之间是否存在转换,而不是您正在进行的转换的哪一侧。例如,它为中国时区返回false,因为中国不会调整夏令时,但在大多数美国时区都会返回,因为大多数美国州(Arizona除外)确实遵守夏令时。
inDaylightTime
public abstract boolean inDaylightTime(Date date)
查询给定日期是否在此时区的夏令时中。
VS
useDaylightTime
public abstract boolean useDaylightTime()
查询此TimeZone是否使用夏令时。 如果基础TimeZone实现子类支持历史和将来的夏令时计划更改,则此方法引用可以是未来预测的最后一个已知夏令时规则,并且可能与当前规则不同。如果还应考虑当前规则,请考虑致电
observesDaylightTime()
。
答案 1 :(得分: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
答案 2 :(得分:4)
我找到了一种确保忽略夏令时的方法
TimeZone tz = TimeZone.getTimeZone("GMT");
TimeZone.setDefault(tz);
GregorianCalendar calendar;
calendar = new GregorianCalendar();
在创建GregorianCalendar对象之前设置时区
答案 3 :(得分:1)
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));
}
}