java - 为什么Timestamp在单元测试中打印运行模型和调试模型之间的差异?

标签 java timestamp sqldatetime

    java.sql.Date date = java.sql.Date.valueOf("1900-01-01");
    //-2209017600000
    System.out.println(date.getTime());
    java.sql.Timestamp timestamp = new Timestamp(date.getTime());
    System.out.println(timestamp); 


如果直接在单元测试中运行,则结果为1900-01-01 00:00:00.0

如果在单元测试中使用调试运行,则结果将为1970-01-01 07:30:00.0

它如何输出1900-01-01 00:00:00.0?它存储在哪里?

为什么不输出1970-01-01 00:00:00.0?因为我看到Timestamp构造函数的注释说自格林尼治标准时间1970年1月1日00:00:00以来的毫秒数。负数是格林尼治标准时间1970年1月1日00:00:00之前的毫秒数。

最佳答案

tl; dr

避免使用可怕的旧日期时间类。使用java.time。 of,您看到的所有怪异行为都消失了,您的问题也没有定论。

LocalDate                 // A class to represent a date-only value, without time-of-day, without time zone. Replaces `java.sql.Date` which only pretends to be date-only but actually has both a time-of-day and a time zone.
.parse( "1900-01-01" )    // Standard ISO 8601 formatted strings are parsed directly by the *java.time* classes. 
.atStartOfDay(            // Let java.time determine the first moment of a day.
    ZoneId.of( "Pacific/Auckland" ) 
)                         // Returns a `ZonedDateTime` object.
.toString()               // Generates a `String` with text in standard ISO 8601 format, wisely extended by appending the name of the time zone in square brackets.



  1900-01-01T00:00 + 11:30 [太平洋/奥克兰]


您正在使用有关遗留日期时间类的这些问题来折磨自己。 Sun,Oracle和JCP社区几年前在采用JSR 310时都放弃了这些课程。我建议你这样做。

切勿使用java.sql.Date

此类是可怕的旧日期时间类的一部分,该类早在几年前就被java.time类所取代。该java.sql.Date特别是设计错误。它扩展了java.util.Date,而文档则告诉我们忽略该继承的事实。作为子类,它伪装成仅具有日期的值,但实际上具有从另一个Date继承的日期时间,而后者又被错误地命名为具有日期和日期时间。此外,时区潜伏在这些类中,尽管没有任何getter或setter方法都无法访问。令人困惑?是的,一团糟。切勿使用java.sql.Date

而是使用java.time.LocalDate

LocalDate ld = LocalDate.parse( "1900-01-01" ) ;



  ld.toString():1900-01-01


切勿使用java.sql.Timestamp

java.sql.Date一样,java.sql.Timestamp类在几年前被替换。使用java.time.Instant。如果递给Timestamp,请立即使用添加到旧类中的新转换方法进行转换。

如果要在特定日期的第一天,让LocalDate确定。第一时刻并不总是00:00:00,所以永远不要假设。指定人们使用您关心的特定壁钟时间的地区的时区。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用3-4个字母的缩写,例如ESTIST,因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;


要在UTC中查看同一时刻,请提取InstantInstant类代表UTC在时间轴上的时刻,分辨率为nanoseconds(最多九(9)个十进制小数位)。

Instant instant = zdt.toInstant() ;


如果要使用UTC进行第一天的工作,请使用OffsetDateTime

OffsetDateTime odt = ld.atOffset( ZoneOffset.UTC ) ;


转换次数

如果必须与尚未更新为java.time类的旧代码进行互操作,则可以来回转换。调用添加到旧类中的新方法。

java.sql.Timestamp ts = Timestamp.from( instant ) ;


…和…

Instant instant = ts.toInstant() ;


同上日期。

java.sql.Date d = java.sql.Date.valueOf( ld ) ;


…和…

LocalDate ld = d.toLocalDate() ;




关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

现在位于Joda-Time中的maintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换java.time对象。使用与JDBC driver或更高版本兼容的JDBC 4.2。不需要字符串,不需要java.sql.*类。

在哪里获取java.time类?


Java SE 8Java SE 9Java SE 10Java SE 11和更高版本-具有捆绑实现的标准Java API的一部分。


Java 9添加了一些次要功能和修复。

Java SE 6Java SE 7


大多数java.time功能都被反向移植到ThreeTen-Backport中的Java 6和7。

Android


更高版本的Android捆绑了java.time类的实现。
对于较早的Android(<26),ThreeTenABP项目改编为ThreeTen-Backport(如上所述)。请参见How to use ThreeTenABP…



ThreeTen-Extra项目使用其他类扩展了java.time。该项目是将来可能向java.time添加内容的试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

关于java - 为什么Timestamp在单元测试中打印运行模型和调试模型之间的差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52155951/

相关文章:

java - hibernate java选择查询

java - Hibernate 查询语言中四舍五入到小数点后两位

oracle - 带时区的 hibernate 时间戳

ios - NSDate,无法获得正确的日期格式

oracle-sqldeveloper - 如何在 Oracle 中使用 GETDATE() 查找当前日期和某个指定日期之间的天数?

c# - SqlDateTime 溢出,但我想要 NULL 或 MinValue

java - 从选定的对象创建 JSON

PHP:从时间戳生成相对日期/时间

sql - 将日期格式化为 2017-06-21T12 :33:47. 879 格式

java - 用 Java 打印用户输入?