我有MonetDB数据库,其中包含包含用户表的表:
CREATE TABLE user
(
birth_date TIMESTAMP NOT NULL
);
birth_date
保存在不带 DST 的 GMT 中。(这是 MonetDB 的默认行为)。所以我应该更改应用程序中的TimeZone
。这是我的代码:
Class.forName("nl.cwi.monetdb.jdbc.MonetDriver");
Connection con = DriverManager.getConnection("jdbc:monetdb://localhost/online", "monetdb", "monetdb");
Statement st = con.createStatement();
ResultSet rs;
rs = st.executeQuery("SELECT * FROM user");
while (rs.next()) {
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"));
c.setTime(rs.getTimestamp("birth_date"));
System.out.println(c.get(Calendar.YEAR) + "-" + c.get(Calendar.MONTH) + "-" + c.get(Calendar.DAY_OF_MONTH) + " " + c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND));
}
但是此代码在数据库中打印相同的TIMESTAMP
。这是转换TimeZone
的错误方法吗?我在 Debian 6 上使用 MonetDB 版本 11.9.5-20120516 和 openjdk 6。这是monetdbd getall /home/dbfarm
:
dbfarm /home/dbfarm/
status monetdbd[4187] 1.6 (Apr2012-SP1) is serving this dbfarm
mserver /usr/bin/mserver5
logfile /home/dbfarm//merovingian.log
pidfile /home/dbfarm//merovingian.pid
sockdir /tmp
port 50000
exittimeout 60
forward proxy
discovery yes
discoveryttl 600
control yes
passphrase {SHA512}ba3253876aed6bc22d4a6ff53d8406c6ad864195ed144ab5c87621b6c233b548baeae6956df346ec8c17f5ea10f35ee3cbc514797ed7ddd3145464e2a0bab413
mapisock /tmp/.s.monetdb.50000
controlsock /tmp/.s.merovingian.50000
终于我得到了答案。
MonetDB 默认以 GMT
运行,并且由于Asia/Tehran
在数据库配置中不可用,因此我需要在应用程序中将时间转换为Asia/Tehran
时区。JVM从操作系统获取其默认TimeZone
,我的操作系统设置为Asia/Tehran
。因此,该程序默认以Asia/Tehran
运行,并且在代码中再次将其更改为"亚洲/德黑兰"没有任何好处。我所做的是这样的:
- 将 JVM 的缺省
TimeZone
更改为应用程序启动时UTC
。 - 从数据库中检索记录
- 将
TimeZone
更改为Asia/Tehran
这是代码:
/* Change the default TimeZone of JVM */
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
Calendar c = Calendar.getInstance();
Class.forName("nl.cwi.monetdb.jdbc.MonetDriver");
Connection con = DriverManager.getConnection("jdbc:monetdb://localhost/online", "monetdb", "monetdb");
Statement st = con.createStatement();
ResultSet rs;
rs = st.executeQuery("SELECT * FROM user");
/* In each iteration:
* 1. set TimeZone to UTC
* 2. fetch record
* 3. convert to Asia/Tehran and so on ... */
while (rs.next()) {
c.setTimeZone(TimeZone.getTimeZone("UTC"));
c.setTime(rs.getTimestamp("birth_date"));
System.out.println(c); /* This is original values in the database */
c.setTimeZone(TimeZone.getTimeZone("Asia/Tehran"));
System.out.println(c); /* This is the values I'm looking for */
}
请注意,如果没有TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
这将不起作用。 因为 JDBC 已连接到数据库并将时间转换为 JVM 的默认TimeZone
(在本例中Asia/Tehran
),然后才能进行任何转换。
您如何确定从 monetdb 返回的时间?
我使用了以下代码,它使用Date
而不是java.sql.Timestamp
,并且它适当地从一个时区转换为另一个时区,那么是否有可能自动为您将时间从 UTC 转换为本地时间?
Date d = new Date();
Calendar c = Calendar.getInstance(TimeZone.getTimeZone("Asia/Tehran"));
c.setTime(d);
System.out.println(c.get(Calendar.YEAR) + "-" + c.get(Calendar.MONTH) + "-" + c.get(Calendar.DAY_OF_MONTH) + " " + c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND));
c.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(c.get(Calendar.YEAR) + "-" + c.get(Calendar.MONTH) + "-" + c.get(Calendar.DAY_OF_MONTH) + " " + c.get(Calendar.HOUR_OF_DAY) + ":" + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND));
编辑 如果您的 java 配置不当,尝试获取时区可能会失败;在与 GMT 相同的时区中生成输出,因此您应该始终确保获得正确的时区
TimeZone tz = TimeZone.getTimeZone("Asia/Tehran");
System.out.println(tz.toString());
为我显示sun.util.calendar.ZoneInfo[id="Asia/Tehran",offset=12600000,dstSavings=3600000,useDaylight=true,transitions=100,lastRule=java.util.SimpleTimeZone[id=Asia/Tehran,offset=12600000,dstSavings=3600000,useDaylight=true,startYear=0,startMode=1,startMonth=2,startDay=21,startDayOfWeek=0,startTime=0,startTimeMode=0,endMode=1,endMonth=8,endDay=21,endDayOfWeek=0,endTime=0,endTimeMode=0]]
;同时:
TimeZone tz = TimeZone.getTimeZone("Asia/fred");
System.out.println(tz.toString());
显示sun.util.calendar.ZoneInfo[id="GMT",offset=0,dstSavings=0,useDaylight=false,transitions=0,lastRule=null]