Java TimeStamp.valueOf()方法

Java TimeStamp.valueOf()方法,java,datetime,timezone,timestamp,Java,Datetime,Timezone,Timestamp,在上面的代码中,最后两行打印不同的值。当前时区是CST,我想将其转换为UTC。当我转换它时,最后两行按一小时打印不同的值,即最后一行打印13 mar 2:45 am和最后一行打印13 mar 3:45 am。为什么它们不同,我如何纠正它。Java8 这张照片 2016-03-13T02:45:00Z 今天,您(通常)不应该需要时间戳对象。java.sql.Timestamp类早已过时。曾经,我们使用它在SQL数据库之间以纳秒精度传输时间戳值。今天我们使用Instant类来实现这一点Instant

在上面的代码中,最后两行打印不同的值。当前时区是CST,我想将其转换为UTC。当我转换它时,最后两行按一小时打印不同的值,即最后一行打印13 mar 2:45 am和最后一行打印13 mar 3:45 am。为什么它们不同,我如何纠正它。

Java8 这张照片

2016-03-13T02:45:00Z

今天,您(通常)不应该需要
时间戳
对象。
java.sql.Timestamp
类早已过时。曾经,我们使用它在SQL数据库之间以纳秒精度传输时间戳值。今天我们使用
Instant
类来实现这一点
Instant
java.time
的一个类,它是现代java日期和时间API(有时我们使用同一API中的
LocalDateTime
,这取决于您的确切需求和数据库列的数据类型)

时间戳
即时
都没有时区。与
时间戳
不同,
即时
始终以UTC打印(由上述输出末尾的
Z
表示)。如您所见,上面的代码片段已正确地将您20:45 CST的时间转换为次日UTC的02:45

如果您确实需要时间戳,通常是对于您现在无法更改或不想更改的遗留API,则转换很容易:

    Instant inst = LocalDateTime.of(2016, Month.MARCH, 12, 20, 45)
            .atZone(ZoneId.of("America/Chicago"))
            .toInstant();
    System.out.println(inst);
2016-03-12 20:45:00.0

Timestamp.toString
使用JVM的时区设置生成字符串,因此您可以识别我们开始的时间。因此,
时间戳
包含正确的时间点。没有必要以任何方式转换它。如果它被错误地插入到数据库中,那么问题就出在JDBC驱动程序、数据库或其他地方,如果可以的话,您应该在那里更正它

Java 6和7 如果向项目中添加三个后端口,则与上述非常类似的代码将在Java7中工作。这是java 6和java 7的
java.time
类的后端口,我在底部包含了一个链接(对于JSR-310,它是三个十,现代API是在这里首次描述的)

您注意到,与Java8的唯一区别在于我们将
即时
转换为
时间戳
的方式。当然,结果是一样的

我不希望依赖于Three-Ten Backport,当然还有一些方法可以获得时间戳。我不会像您在代码中那样使用不推荐使用的构造函数,即使只要没有人篡改JVM的时区设置,它就可以工作。如果您知道希望
时间戳
等于02:45 UTC,则有一个选项

    Instant inst = LocalDateTime.of(2016, Month.MARCH, 12, 20, 45)
            .atZone(ZoneId.of("America/Chicago"))
            .toInstant();
    Timestamp ts = DateTimeUtils.toSqlTimestamp(inst);
不过,这仍然取决于JVM的时区设置

你的代码出了什么问题? 如前所述,
时间戳
中没有时区,因此将
时间戳
转换为UTC没有意义

代码中发生了什么:

  • 不推荐使用的
    时间戳
    构造函数使用JVM的时区设置(我猜是美国/芝加哥)在您的时区(与UTC 3月13日凌晨2:45相同的时间点)中构建对应于2016年3月12日晚上8:45的
    时间戳
  • 您的
    SimpleDateFormat
    将其正确格式化为
    2016-03-13 02:45:00
    (UTC)
  • Timestamp.valueOf()也使用美国/芝加哥时区。然而,在3月12日至13日之间的晚上,夏季(夏令时)在这个时区开始。凌晨2点,时钟向前拨到3点。所以今晚没有2点45分<代码>时间戳
    改为选择3:45
链接
  • 解释如何使用
    java.time
  • ,其中首先描述了
    java.time
  • ,java.time的后端口到Java6和Java7
  • ,Android版Three Ten Backport
  • ,解释得非常透彻

您是否知道
时间戳
构造函数已被弃用?整个
时间戳
类与
日期
以及麻烦的
简化格式
一起过时了?现在,您可以将
即时
本地日期时间
传递到SQL数据库,因此您不再需要使用
时间戳
。正如Ole V.V.所评论的,麻烦的旧日期时间类,例如,
java.text.SimpleDateFormat
java.SQL.Timestamp
,现在,被内置在Java8和更高版本中的类所取代。请参阅。感谢您的解释。它可以解决吗?例如,我可以用Java类保持2:45 UTC吗?谢谢@Ole V。我们在项目中使用Java 7。你能帮我把一个区域的时间戳转换成其他方式吗?如果你能的话,我会很高兴:)。
    Timestamp ts = Timestamp.from(inst);
    System.out.println(ts);
    Instant inst = LocalDateTime.of(2016, Month.MARCH, 12, 20, 45)
            .atZone(ZoneId.of("America/Chicago"))
            .toInstant();
    Timestamp ts = DateTimeUtils.toSqlTimestamp(inst);
    Timestamp ts = Timestamp.valueOf("2016-03-12 20:45:00");