草庐IT

java - MySQL选择没有夏令时更改的日期时间

coder 2023-10-22 原文

我有一张表,用于存储来自传感器的数据

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 Workbench 中运行此查询时,它返回正确的日期时间。

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

显然,这与英国 3 月 26 日凌晨 1 点发生的夏令时变化有关。 我认为 JDBC 连接正在将时间更改为 BST,但我不希望这样。

我尝试将 MySQL 服务器全局时区设置为 00:00

SET @@global.time_zone='+00:00';

但是没有成功! 如何在不更改 DST 的情况下获得正确的时间?

编辑: 我正在使用 Java 1.7mysql-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 时,它会返回凌晨 1 点而不是凌晨 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

最佳答案

这里有两个问题:

  1. 我们是否从服务器返回了所需的 java.sql.Timestamp 值?
  2. 当我们要求 Java 将 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 格式的日期时间值与我们使用 CAST(dateTime AS CHAR)<> 在 SQL 查询中。

关于java - MySQL选择没有夏令时更改的日期时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43072071/

有关java - MySQL选择没有夏令时更改的日期时间的更多相关文章

  1. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  2. ruby - 难道Lua没有和Ruby的method_missing相媲美的东西吗? - 2

    我好像记得Lua有类似Ruby的method_missing的东西。还是我记错了? 最佳答案 表的metatable的__index和__newindex可以用于与Ruby的method_missing相同的效果。 关于ruby-难道Lua没有和Ruby的method_missing相媲美的东西吗?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/7732154/

  3. ruby-on-rails - rails 目前在重启后没有安装 - 2

    我有一个奇怪的问题:我在rvm上安装了ruby​​onrails。一切正常,我可以创建项目。但是在我输入“railsnew”时重新启动后,我有“程序'rails'当前未安装。”。SystemUbuntu12.04ruby-v"1.9.3p194"gemlistactionmailer(3.2.5)actionpack(3.2.5)activemodel(3.2.5)activerecord(3.2.5)activeresource(3.2.5)activesupport(3.2.5)arel(3.0.2)builder(3.0.0)bundler(1.1.4)coffee-rails(

  4. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  5. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  6. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  7. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  8. ruby-on-rails - date_field_tag,如何设置默认日期? [ rails 上的 ruby ] - 2

    我想设置一个默认日期,例如实际日期,我该如何设置?还有如何在组合框中设置默认值顺便问一下,date_field_tag和date_field之间有什么区别? 最佳答案 试试这个:将默认日期作为第二个参数传递。youcorrectlysetthedefaultvalueofcomboboxasshowninyourquestion. 关于ruby-on-rails-date_field_tag,如何设置默认日期?[rails上的ruby],我们在StackOverflow上找到一个类似的问

  9. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  10. ruby - 检查日期是否在过去 7 天内 - 2

    我的日期格式如下:"%d-%m-%Y"(例如,今天的日期为07-09-2015),我想看看是不是在过去的七天内。谁能推荐一种方法? 最佳答案 你可以这样做:require"date"Date.today-7 关于ruby-检查日期是否在过去7天内,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/32438063/

随机推荐