当前位置: 首页 > 知识库问答 >
问题:

时间戳转换为即时Java增加了不必要的时间偏移

秦永望
2023-03-14

我需要能够将从存储在“日期时间”字段中的MySQL数据库中获取的数据转换为JavaZonedDateTime对象。

ZonedDateTime dt = ZonedDateTime.ofInstant(rs.getTimestamp("Start").toInstant(), UTC_ZONE_ID)

我遇到的问题是toInstant()将本地时间偏移量添加到Timestamp对象,我不需要它,因为日期时间已经以UTC格式存储在数据库中。所以当我运行以下代码时:

ZonedDateTime startDT = 
        ZonedDateTime.ofInstant(rs.getTimestamp("Start").toInstant(),Globals.LOCALZONEID);
System.out.println(rs.getTimestamp("start"));
System.out.println(rs.getTimestamp("start").toInstant());

我得到:

2017-06-08 13:15:00.0
2017-06-08T17:15:00Z

我需要时间部分保持不变。

我找不到任何明显的解决问题的方法,所以我在这里错过了什么吗?

共有3个答案

佟阳飙
2023-03-14

我认为这个代码片段回答了您的问题。这将接收本地时区中的字符串,将其转换为UTC,并将其存储在db中。

    //Getting the LocalDateTime Objects from String values
    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd kk:mm"); 
    String txtStartTime = "2017-03-29 12:00";

    LocalDateTime ldtStart = LocalDateTime.parse(txtStartTime, df);


    //Convert to a ZonedDate Time in UTC
    ZoneId zid = ZoneId.systemDefault();

    ZonedDateTime zdtStart = ldtStart.atZone(zid);
    System.out.println("Local Time: " + zdtStart);
    ZonedDateTime utcStart = zdtStart.withZoneSameInstant(ZoneId.of("UTC"));
    System.out.println("Zoned time: " + utcStart);
    ldtStart = utcStart.toLocalDateTime();
    System.out.println("Zoned time with zone stripped:" + ldtStart);
    //Create Timestamp values from Instants to update database
    Timestamp startsqlts = Timestamp.valueOf(ldtStart); //this value can be inserted into database
    System.out.println("Timestamp to be inserted: " +startsqlts);

    //insertDB(startsqlts);
宋勇
2023-03-14

旧类如java。sql。时间戳的设计有很多问题。经常引起混淆的事情之一是时间戳。toString()打印JVM时区中的时间,即使其中的时间戳只包含一个没有时区的时间点。具体来说,当时间戳等于UTC中的2017-06-08T17:15:00Z,并且您在运行匹兹堡时间的计算机上打印它(在每年的这个时候,它与UTC的偏移量为-4:00)时,时间戳。toString()被隐式调用,它读取JVM的时区并将时间打印为13:15:00.0,因为宾夕法尼亚州的这个时间等于时间戳中的UTC时间。

因此,长话短说,不要担心,您的时间戳和即时都是正确的。

王高超
2023-03-14

我的问题是。toInstant()将本地时间偏移添加到时间戳对象

不,没有。

  • 一个java.sql.Timestamp定义为UTC。
  • 根据定义,Instant在UTC中。

也不能分配任何其他区域。

不要将您的代码堆积成一行。将每个步骤分成单独的行,以便您可以调试它们的值。

java.sql.Timestamp ts = rs.getTimestamp("Start") ;  // Actually in UTC, but it's `toString` method applies JVM’s current default time zone html" target="_blank">while generating string.
Instant instant = ts.toInstant() ;                  // Same moment, also in UTC.
ZoneId z = ZoneId.of( "America/Montreal" ) ;        // Or call your global var: `Globals.LOCALZONEID`.
ZonedDateTime zdt = instant.atZone( z );            // Same moment, same point on timeline, but with wall-clock time seen in a particular zone.

之后,您可能会看到问题(或非问题)。如果没有,请编辑您的问题以显示每个变量的调试值。

重要提示:java.sql.Timestamp::toString方法所在。该方法在生成字符串时应用JVM的当前默认时区。实际值始终以UTC为单位。避免这些麻烦的遗留类的众多原因之一。在您自己的机器上运行以下代码示例,以查看默认时区对Timestamp文本表示的影响。

让我们模拟一下在IdeOne中实时运行的代码。通用域名格式。IdeOne的JVM。com默认为UTC/GMT,因此我们通过任意指定默认值为太平洋/奥克兰来覆盖默认值。

Instant now = Instant.now() ;                       // Simulating fetching a `Timestamp` from database by using current moment in UTC.

TimeZone.setDefault( TimeZone.getTimeZone( "Pacific/Auckland" ) ) ;
ZoneId zoneIdDefault = ZoneId.systemDefault() ;
ZoneOffset zoneOffset = zoneIdDefault.getRules().getOffset( now ) ;

java.sql.Timestamp ts = java.sql.Timestamp.from( now ) ;  // Actually in UTC, but it's `toString` method applies JVM’s current default time zone while generating string.
Instant instant = ts.toInstant() ;                  // Same moment, also in UTC.
ZoneId z = ZoneId.of( "America/Montreal" ) ;        // Or call your global var: `Globals.LOCALZONEID`.
ZonedDateTime zdt = instant.atZone( z );            // Same moment, same point on timeline, but with wall-clock time seen in a particular zone.

当前默认时区:太平洋/奥克兰

当前默认偏移量:太平洋/奥克兰|总秒数:43200

现在toString():2017-06-09T04:41:10.750Z

ts.toString():2017-06-09 16:41:10.75

瞬间toString():2017-06-09T04:41:10.750Z

z、 toString():美国/蒙特利尔

zdt。toString():2017-06-09T00:41:10.750-04:00[美国/蒙特利尔]

java之外的旧日期时间类。时间包是麻烦的、令人困惑的、设计糟糕的和有缺陷的。尽可能避免它们。这包括java。sql。时间戳。

您的JDBC 4.2兼容驱动程序可以通过调用Presared语句::setObjectResultSet::getObject直接解决java.time类型。

myPreparedStatement.setObject( … , instant ) ;

…和…

Instant instant = myResultSet.getObject( … , Instant.class ) ;

如果使用尚未更新到JDBC 4.2和java.time的JDBC驱动程序,请使用添加到旧类的新方法:from(Instant)、toInstant()等简单地转换为java.sql.Timestamp。但是除了与数据库交换数据之外,还要在java.time对象中完成所有实际工作(业务逻辑)。

myPreparedStatement.setTimestamp( … , java.sql.Timestamp.from( instant ) ) ;

…和…

Instant instant = myResultSet.getTimestamp( … ).toInstant() ;

java。时间框架内置于Java 8及更高版本中。这些类取代了麻烦的旧遗留日期时间类,如java。util。日期、日历、,

Joda Time项目现在处于维护模式,建议迁移到java。时间课程。

要了解更多信息,请参阅Oracle教程。和搜索堆栈溢出的许多例子和解释。规范为JSR 310。

你可以交换java。时间对象直接与数据库连接。使用符合JDBC 4.2或更高版本的JDBC驱动程序。不需要字符串,也不需要java。sql* 类。

在哪里获得java.time类?

  • Java SE 8、Java SE 9及更高版本
    • 内置
    • 标准Java API的一部分,带有捆绑实现
    • Java 9添加了一些次要功能和修复
    • 大部分java。时间功能被向后移植到Java 6
    • java.time类的Android捆绑包实现的最新版本。
    • 对于早期的Android(

    ThreeTen额外项目扩展了java。额外上课的时间。该项目是未来可能添加到java的一个试验场。时间您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuarter等等。

 类似资料:
  • 从我的数据库我检索值为: 我想要上面的: 我试着用当前的时间戳跟踪 实际时间戳:2018年6月22日星期五16:07:35 更新了,我不想更新,有没有办法保持原样?

  • 我找不到这个问题的解决方案,我正在从firebase获取数据,其中一个字段是时间戳,看起来像这样- Swift示例(作品): 我的飞镖尝试: 并且它返回的日期/时间是错误的。 更新:

  • 本文向大家介绍sqlite时间戳转时间语句(时间转时间戳),包括了sqlite时间戳转时间语句(时间转时间戳)的使用技巧和注意事项,需要的朋友参考一下 下面是具体的实现代码:

  • 问题内容: 我有一个毫秒本地本地时间戳,我想将其转换为毫秒本地UTC时间戳。快速浏览一下文档,看起来像这样工作: 有一个更好的方法吗? 问题答案: 使用a 来获取本地纪元处的偏移量,然后将其添加到本地纪元时间戳中。

  • 问题内容: 我将时间作为Unix时间戳存储在MySQL数据库中,并将其发送到一些JavaScript代码。我怎么会得到时间呢? 例如,以HH / MM / SS格式。 问题答案: let unix_timestamp = 1549312452 有关Date对象的更多信息,请参考MDN或ECMAScript5规范。

  • 我试图找出如何在Kotlin中将转换为,这在Java中非常简单,但我在Kotlin中找不到任何等效的。 例如:历元时间戳(1970-01-01以来的秒数)== 在Kotlin中是否有解决方案,或者我是否必须在Kotln中使用Java语法?请给我一个简单的例子来说明如何解决这个问题。提前谢谢。 这个链接不是我问题的答案