TimeStamp.valueOf() method


public static void main(String[] args) {
Timestamp ts = new Timestamp(116, 02, 12, 20, 45, 0, 0);
Date d = new Date();
d.setTime(ts.getTime());
System.out.println(d);
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
//System.out.println(ts.getTime());
System.out.println(simpleDateFormat.format(ts));
System.out.println(Timestamp.valueOf(simpleDateFormat.format(ts)));
}

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

Java 8

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

这打印

2016-03-13T02:45:00Z

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

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

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

Timestamp ts = Timestamp.from(inst);
System.out.println(ts);

2016-03-12 20:45:00.0

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

爪哇 6 和 7

与上述非常相似的代码将在Java 7中工作,如果你将ThreeTen Backport添加到你的项目中。这是java.time类到 Java 6 和 7 的向后移植,我在底部包含一个链接(它是 JSR-310 的 ThreeTen,其中首次描述了现代 API)。

Instant inst = LocalDateTime.of(2016, Month.MARCH, 12, 20, 45)
.atZone(ZoneId.of("America/Chicago"))
.toInstant();
Timestamp ts = DateTimeUtils.toSqlTimestamp(inst);

您注意到与Java 8的唯一区别是我们将Instant转换为Timestamp的方式。当然,结果是一样的。

我不想依赖ThreeTen Backport,当然还有办法获得Timestamp。我不会像在代码中那样使用已弃用的构造函数,即使只要没有人篡改 JVM 的时区设置,它就可以工作。如果您知道您想要等于 02:45 UTC 的Timestamp,一个选项是

Timestamp ts = Timestamp.valueOf("2016-03-12 20:45:00");

不过,它仍然取决于 JVM 的时区设置。

您的代码中出了什么问题?

如前所述,Timestamp没有时区,因此将Timestamp转换为 UTC 没有意义。

代码中发生的情况:

  • 已弃用的Timestamp构造函数使用 JVM 的时区设置(我认为是美国/芝加哥)来构造一个对应的Timestamp2016 年 3 月 12 日晚上 8:45 在您的时区(与 UTC 时间 3 月 13 日凌晨 2:45 的时间点相同)。
  • 您的SimpleDateFormat正确地将其格式化为2016-03-13 02:45:00(UTC)。
  • Timestamp.valueOf()也使用美国/芝加哥时区。但是,在 3 月 12 日至 13 日之间的夜晚,夏令时(夏令时)从这个时区开始。凌晨 2 点,时钟向前移动到 3。所以今天晚上没有2:45。Timestamp选择3:45。

链接

  • Oracle 教程:解释如何使用java.time的日期时间。
  • Java 规范请求 (JSR) 310,其中首次描述了java.time
  • ThreeTen Backport 项目,将java.time向 Java 6 和 7 的反向移植。
  • ThreeTenABP,ThreeTen Backport 的安卓版
  • 问:如何在Android项目中使用ThreeTenABP,并进行了非常详尽的解释。

相关内容

  • 没有找到相关文章

最新更新