我有一张表,用于存储来自传感器的数据
CREATE TABLE `testdatabase` (
`dateTime` datetime DEFAULT NULL,
`data` varchar(200) DEFAULT NULL,
`sensorID` varchar(10) DEFAULT NULL
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6918 DEFAULT CHARSET=utf8
这是我正在运行的选择查询
SELECT `dateTime` from testdatabase WHERE sensorID='ABC1234' AND (dateTime BETWEEN '2017-03-26 00:01:00' AND '2017-03-26 00:00:00') order by `dateTime` asc;
在运行此查询的MySQL工作台中,它返回正确的日期时间。
2017-03-26 00:10:00
2017-03-26 00:20:00
2017-03-26 00:30:00
2017-03-26 00:40:00
2017-03-26 00:50:00
2017-03-26 01:00:00
2017-03-26 01:10:00
2017-03-26 01:20:00
2017-03-26 01:30:00
2017-03-26 01:40:00
2017-03-26 01:50:00
2017-03-26 02:00:00
2017-03-26 02:10:00
2017-03-26 02:20:00
2017-03-26 02:30:00
2017-03-26 02:40:00
2017-03-26 02:50:00
2017-03-26 03:00:00
但是当我从我的Java应用程序运行此查询时,它会返回以下日期时间。
2017-03-26 00:10:00
2017-03-26 00:20:00
2017-03-26 00:30:00
2017-03-26 00:40:00
2017-03-26 00:50:00
2017-03-26 02:00:00
2017-03-26 02:10:00
2017-03-26 02:20:00
2017-03-26 02:30:00
2017-03-26 02:40:00
2017-03-26 02:50:00
2017-03-26 02:00:00
2017-03-26 02:10:00
2017-03-26 02:20:00
2017-03-26 02:30:00
2017-03-26 02:40:00
2017-03-26 02:50:00
2017-03-26 03:00:00
显然这与英国的DST变化有关,该变化发生在3月26日凌晨1点。 我认为JDBC连接正在改变BST的时间,但我不想这样做。
我尝试将MySQL服务器全局时区设置为00:00
SET @@global.time_zone='+00:00';
但没有成功! 如何在没有DST更改的情况下获得正确的时间?
编辑:
我正在使用Java 1.7
和mysql-connector-java-5.1.19-bin.jar
我之前将数据作为字符串获取但在Mark Rotteveel
注释之后我尝试PreparedStaement
并将日历对象设置为UTC但两者都返回相同的结果。
try
{
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(query);
while(resultSet.next())
{
System.out.println("Without Calendar Object : "+resultSet.getString(1));
}
}catch (SQLException e){e.printStackTrace();}
try
{
PreparedStatement statement = connection.prepareStatement(query);
ResultSet resultSet = statement.executeQuery();
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
while(resultSet.next())
{
System.out.println("With Calendar Object : "+resultSet.getTimestamp(1, cal));
}
}catch (SQLException e){e.printStackTrace();}
OUTPUT:
Without Calendar Object : 2017-03-26 00:10:00.0
Without Calendar Object : 2017-03-26 00:20:00.0
Without Calendar Object : 2017-03-26 00:30:00.0
Without Calendar Object : 2017-03-26 00:40:00.0
Without Calendar Object : 2017-03-26 00:50:00.0
Without Calendar Object : 2017-03-26 02:00:00.0
Without Calendar Object : 2017-03-26 02:10:00.0
Without Calendar Object : 2017-03-26 02:20:00.0
Without Calendar Object : 2017-03-26 02:30:00.0
Without Calendar Object : 2017-03-26 02:40:00.0
Without Calendar Object : 2017-03-26 02:50:00.0
Without Calendar Object : 2017-03-26 02:00:00.0
Without Calendar Object : 2017-03-26 02:10:00.0
Without Calendar Object : 2017-03-26 02:20:00.0
Without Calendar Object : 2017-03-26 02:30:00.0
Without Calendar Object : 2017-03-26 02:40:00.0
Without Calendar Object : 2017-03-26 02:50:00.0
Without Calendar Object : 2017-03-26 03:00:00.0
With Calendar Object : 2017-03-26 00:10:00.0
With Calendar Object : 2017-03-26 00:20:00.0
With Calendar Object : 2017-03-26 00:30:00.0
With Calendar Object : 2017-03-26 00:40:00.0
With Calendar Object : 2017-03-26 00:50:00.0
With Calendar Object : 2017-03-26 02:00:00.0
With Calendar Object : 2017-03-26 02:10:00.0
With Calendar Object : 2017-03-26 02:20:00.0
With Calendar Object : 2017-03-26 02:30:00.0
With Calendar Object : 2017-03-26 02:40:00.0
With Calendar Object : 2017-03-26 02:50:00.0
With Calendar Object : 2017-03-26 02:00:00.0
With Calendar Object : 2017-03-26 02:10:00.0
With Calendar Object : 2017-03-26 02:20:00.0
With Calendar Object : 2017-03-26 02:30:00.0
With Calendar Object : 2017-03-26 02:40:00.0
With Calendar Object : 2017-03-26 02:50:00.0
With Calendar Object : 2017-03-26 03:00:00.0
编辑2: 还有一件奇怪的事情是,当我将默认时区更改为UTC时,它会返回1am而不是凌晨2点的重复值。
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
输出:
Without Calendar Object : 2017-03-26 00:10:00.0
Without Calendar Object : 2017-03-26 00:20:00.0
Without Calendar Object : 2017-03-26 00:30:00.0
Without Calendar Object : 2017-03-26 00:40:00.0
Without Calendar Object : 2017-03-26 00:50:00.0
Without Calendar Object : 2017-03-26 01:00:00.0
Without Calendar Object : 2017-03-26 01:10:00.0
Without Calendar Object : 2017-03-26 01:20:00.0
Without Calendar Object : 2017-03-26 01:30:00.0
Without Calendar Object : 2017-03-26 01:40:00.0
Without Calendar Object : 2017-03-26 01:50:00.0
Without Calendar Object : 2017-03-26 01:00:00.0
Without Calendar Object : 2017-03-26 01:10:00.0
Without Calendar Object : 2017-03-26 01:20:00.0
Without Calendar Object : 2017-03-26 01:30:00.0
Without Calendar Object : 2017-03-26 01:40:00.0
Without Calendar Object : 2017-03-26 01:50:00.0
Without Calendar Object : 2017-03-26 02:00:00.0
With Calendar Object : 2017-03-26 00:10:00.0
With Calendar Object : 2017-03-26 00:20:00.0
With Calendar Object : 2017-03-26 00:30:00.0
With Calendar Object : 2017-03-26 00:40:00.0
With Calendar Object : 2017-03-26 00:50:00.0
With Calendar Object : 2017-03-26 01:00:00.0
With Calendar Object : 2017-03-26 01:10:00.0
With Calendar Object : 2017-03-26 01:20:00.0
With Calendar Object : 2017-03-26 01:30:00.0
With Calendar Object : 2017-03-26 01:40:00.0
With Calendar Object : 2017-03-26 01:50:00.0
With Calendar Object : 2017-03-26 01:00:00.0
With Calendar Object : 2017-03-26 01:10:00.0
With Calendar Object : 2017-03-26 01:20:00.0
With Calendar Object : 2017-03-26 01:30:00.0
With Calendar Object : 2017-03-26 01:40:00.0
With Calendar Object : 2017-03-26 01:50:00.0
With Calendar Object : 2017-03-26 02:00:00.0
答案 0 :(得分:2)
这里有两个问题:
java.sql.Timestamp
值?Timestamp
值显示为日期/时间字符串时,我们实际看到了什么?为了帮助解决这个问题,我们可以以数字形式显示Timestamp
值。 Timestamp#getTime()
返回自纪元(1970-01-01 00:00:00 UTC)以来的毫秒数,但如果我们将其除以60000以给出自纪元以来的分钟数,我们可以使其更容易阅读
我们还可以使用SimpleDateFormat
个对象以明确的方式格式化Timestamp
值。
因此,对于名为tztest
的示例表,在phpMyAdmin
id dateTime
-- -------------------
1 2017-03-26 00:10:00
2 2017-03-26 01:10:00
3 2017-03-26 02:10:00
当我运行以下Java代码时
connectionUrl = "jdbc:mysql://localhost:3307/mydb";
try (Connection conn = DriverManager.getConnection(connectionUrl, myUid, myPwd)) {
SimpleDateFormat sdfLocal = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
Calendar calUTC = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
SimpleDateFormat sdfUTC = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
sdfUTC.setCalendar(calUTC);
String sql =
"SELECT id, CAST(dateTime AS CHAR) AS datetimeString, dateTime " +
"FROM tztest ORDER BY dateTime";
try ( Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql)) {
while (rs.next()) {
int id = rs.getInt("id");
String datetimeString = rs.getString("datetimeString");
Timestamp timestampValue = rs.getTimestamp("dateTime", calUTC);
long minutesSinceEpoch = timestampValue.getTime() / 60000;
System.out.printf("%d: %s -> %d minutes since epoch -> %s / %s%n",
id,
datetimeString,
minutesSinceEpoch,
sdfLocal.format(timestampValue),
sdfUTC.format(timestampValue)
);
}
}
} catch (Exception e) {
e.printStackTrace(System.err);
}
控制台输出
1: 2017-03-26 00:10:00 -> 24841450 minutes since epoch -> 2017-03-26 00:10:00 GMT / 2017-03-26 00:10:00 UTC
2: 2017-03-26 01:10:00 -> 24841510 minutes since epoch -> 2017-03-26 02:10:00 BST / 2017-03-26 01:10:00 UTC
3: 2017-03-26 02:10:00 -> 24841510 minutes since epoch -> 2017-03-26 02:10:00 BST / 2017-03-26 01:10:00 UTC
显然我没有得到所需的Timestamp
值,因为第2行和第3行都显示“自纪元以来24841510分钟”。
我只需将useLegacyDatetimeCode=false
添加到我的连接字符串
connectionUrl = "jdbc:mysql://localhost:3307/mydb?useLegacyDatetimeCode=false";
之后控制台输出
1: 2017-03-26 00:10:00 -> 24841450 minutes since epoch -> 2017-03-26 00:10:00 GMT / 2017-03-26 00:10:00 UTC
2: 2017-03-26 01:10:00 -> 24841510 minutes since epoch -> 2017-03-26 02:10:00 BST / 2017-03-26 01:10:00 UTC
3: 2017-03-26 02:10:00 -> 24841570 minutes since epoch -> 2017-03-26 03:10:00 BST / 2017-03-26 02:10:00 UTC
请注意,第3行现在显示“自纪元以来的24841570分钟”,比第2行晚60分钟。另请注意,UTC格式的日期时间值与我们在SQL查询中使用CAST(dateTime AS CHAR)
获得的字符串表示形式相匹配。