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之前的毫秒数。
答案 0 :(得分:1)
避免使用可怕的旧日期时间类。使用 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 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类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。