小编典典

TimeStamp.valueOf()方法

java

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。当我将其转换时,最后两行在一小时内打印不同的值,即最后一次打印3月13日凌晨2:45,最后一次打印3月13日凌晨3:45。他们为何与众不同,我该如何纠正。


阅读 1520

收藏
2020-11-30

共1个答案

小编典典

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改为使用该类。Instantjava.time现代Java日期和时间API
的类之一(有时我们使用LocalDateTime相同的API,这取决于您的确切要求和数据库列的数据类型)。

a
Timestamp和an中都没Instant有时区。不同于Timestamp所述Instant在UTC总是打印(由表示Z在上述输出的结束)。如您所见,以上代码段已将您的CST时间20:45
CST正确转换为第二天UTC。

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

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

2016-03-12 20:45:00.0

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

Java 6和7

如果将ThreeTen Backport添加到项目中,则与上述代码非常相似的代码将在Java 7中运行。这是这些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唯一的区别是我们转换的方式InstantTimestamp。结果当然是一样的。

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

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

但是,它仍然取决于JVM的时区设置。

您的代码出了什么问题?

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

您的代码中会发生什么:

  • Timestamp建议使用的构造函数使用您的JVM的时区设置(美国/芝加哥,我认为)Timestamp在您的时区(与3月13日UTC时间3月13日相同的时间点)的相应时间2016年3月12日构造相应的时间。
  • 您将其SimpleDateFormat正确格式化为2016-03-13 02:45:00(UTC)。
  • Timestamp.valueOf()也使用美国/芝加哥时区。但是,在3月12日至13日之间的夜晚,夏季时间(夏令时)在该时区开始。凌晨2时,时钟向前移动到3.因此,有 没有2:45这个夜晚。Timestamp选择3:45代替。
2020-11-30