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/Montreal
,Africa/Casablanca
或Pacific/Auckland
。切勿使用3-4个字母的缩写,例如EST
或IST
,因为它们不是真实的时区,不是标准化的,甚至不是唯一的(!)。ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;
要在UTC中查看同一时刻,请提取
Instant
。 Instant
类代表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.Date
,Calendar
和SimpleDateFormat
。现在位于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 8,Java SE 9,Java SE 10,Java SE 11和更高版本-具有捆绑实现的标准Java API的一部分。
Java 9添加了一些次要功能和修复。
Java SE 6和Java 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添加内容的试验场。您可能会在这里找到一些有用的类,例如
Interval
,YearWeek
,YearQuarter
和more。
关于java - 为什么Timestamp在单元测试中打印运行模型和调试模型之间的差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52155951/