首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java OffsetDateTime <-> MYSQL时间戳问题

Java OffsetDateTime <-> MYSQL时间戳问题
EN

Stack Overflow用户
提问于 2021-03-27 00:16:24
回答 1查看 246关注 0票数 0

我在处理OffsetDateTime与MYSQL时间戳之间的转换时遇到了一些麻烦。我的JVM时区是GMT+1,我的数据库时区是UTC,我可以确认是因为now()返回一个小时前的时间戳。

下面是我的代码:

代码语言:javascript
复制
public class TestDBTime {
    
    public static void main(String[] args) throws SQLException, InterruptedException{
        testOffsetDateTime();
    }
    
    private static void testOffsetDateTime() throws SQLException {
        Connection connection = DriverManager.getConnection(DB_Connection.url, DB_Connection.user, DB_Connection.password);

        Instant instant = Instant.now();
        OffsetDateTime offsetDateTime = OffsetDateTime.ofInstant(instant, ZoneId.systemDefault());
        System.out.println("Default offset date time from instant: " +offsetDateTime.toString());
        
        OffsetDateTime offsetDateTimeUTC = instant.atOffset(ZoneOffset.UTC);
        System.out.println("UTC.... offset date time from instant: " +offsetDateTimeUTC.toString());
        
        String update = "update schedule set timestamp = ? where id = 1";
        try (PreparedStatement preparedStatement = connection.prepareStatement(update)){
            preparedStatement.setObject(1, offsetDateTimeUTC);
            preparedStatement.executeUpdate();
        }
        
        String query = "SELECT s.*, now() as now from schedule s where id = 1";
        try (PreparedStatement preparedStatement = connection.prepareStatement(query)){
            ResultSet resultSet = preparedStatement.executeQuery();
            resultSet.next();
            
            OffsetDateTime retrievedDateTime = resultSet.getObject("timestamp", OffsetDateTime.class);
            System.out.println("Offset date time retrieved: " +retrievedDateTime);
            System.out.println("Retrieved odt is equal to original UTC odt: " +retrievedDateTime.equals(offsetDateTimeUTC));
            
            OffsetDateTime retrievedNow = resultSet.getObject("now", OffsetDateTime.class);
            System.out.println("Now: " +retrievedNow);
            
            Timestamp timestamp = resultSet.getTimestamp("timestamp");
            System.out.println("Retrieved timestamp instant is equal to original instant: " +timestamp.toInstant().equals(instant));
        }
    }
}

我执行代码,我的控制台输出是:

代码语言:javascript
复制
Default offset date time from instant: 2021-03-26T17:05:11.856+01:00
UTC.... offset date time from instant: 2021-03-26T16:05:11.856Z
Offset date time retrieved: 2021-03-26T17:05:11.856+01:00
Retrieved odt is equal to original UTC odt: false
Now: 2021-03-26T16:05:12+01:00
Retrieved timestamp instant is equal to original instant: true

问题是,数据库中的时间戳保存在我的本地时间,而不是UTC,因为我可以在MYSQL工作台中使用查询进行测试。

另一个奇怪的问题是now()值,你可以看到它应该是过去的1小时,因为数据库是UTC,它被检索为+01:00时间戳,而它应该是UTC。

最后,如果我使用java timestamp类检索时间戳(我知道不应该使用这个类),它会报告与我在方法开始时声明的时刻完全相同的时刻。

Java版本为8,mysql连接器为8.0.23,mysql版本为5.7

EN

回答 1

Stack Overflow用户

发布于 2021-03-27 00:31:58

你的比较是不正确的。2021-03-26T16:05:11.856Z2021-03-26T17:05:11.856+01:00代表同一时刻。您应该将InstantOffsetDateTime与相同的Instant进行比较。

代码语言:javascript
复制
import java.time.OffsetDateTime;
import java.time.ZoneOffset;

public class Main {
    public static void main(String[] args) {
        OffsetDateTime offsetDateTimeUTC = OffsetDateTime.parse("2021-03-26T16:05:11.856Z");
        OffsetDateTime retrievedDateTime = OffsetDateTime.parse("2021-03-26T17:05:11.856+01:00");
        System.out.println(retrievedDateTime.withOffsetSameInstant(ZoneOffset.UTC).equals(offsetDateTimeUTC));
    }
}

输出:

代码语言:javascript
复制
true

有关更多详细信息,请查看documentation。为了避免获取不同的日期-时间,您应该按照this answer中的说明设置serverTimezone=UTC

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66820574

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档