有人可以解释为什么会这样吗?为什么那段时间有24分钟的补偿以及如何处理?
Scala 2.12和Java 8.
scala> java.sql.Timestamp.valueOf("1900-01-01 00:59:00")
res22: java.sql.Timestamp = 1900-01-01 00:59:00.0
scala> java.sql.Timestamp.valueOf("1900-01-01 01:00:00")
res23: java.sql.Timestamp = 1900-01-01 01:24:00.0
scala> java.sql.Timestamp.valueOf("1900-01-01 01:14:00")
res24: java.sql.Timestamp = 1900-01-01 01:38:00.0
scala> java.sql.Timestamp.valueOf("1900-01-01 01:20:00")
res25: java.sql.Timestamp = 1900-01-01 01:44:00.0
scala> java.sql.Timestamp.valueOf("1900-01-01 01:23:00")
res26: java.sql.Timestamp = 1900-01-01 01:47:00.0
scala> java.sql.Timestamp.valueOf("1900-01-01 01:24:00")
res27: java.sql.Timestamp = 1900-01-01 01:24:00.0
scala> java.sql.Timestamp.valueOf("1900-01-01 01:30:00")
res28: java.sql.Timestamp = 1900-01-01 01:30:00.0
答案 0 :(得分:4)
查看IANA时区数据库中的时区定义:
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Europe/Warsaw 1:24:00 - LMT 1880
1:24:00 - WMT 1915 Aug 5 # Warsaw Mean Time
1:00 C-Eur CE%sT 1918 Sep 16 3:00
2:00 Poland EE%sT 1922 Jun
1:00 Poland CE%sT 1940 Jun 23 2:00
1:00 C-Eur CE%sT 1944 Oct
1:00 Poland CE%sT 1977
1:00 W-Eur CE%sT 1988
1:00 EU CE%sT
1900年,波兰的时区偏离UTC一小时24分钟,即他们使用的是当地平均太阳时。那是在1915年8月5日引入标准时区之前。
你必须向PostgreSQL提供一个timestamp without time zone
,它在你当地的时区解释(偏移量为1:24)。
某人(scala?)然后将此时间戳转换回当地时区的时间戳,但错误地使用了一小时的偏移量。
我不知道如何解决这个问题,但要么全程使用timestamp without time zone
,要么修复认为波兰时间与1900年UTC相差1小时的组件。
答案 1 :(得分:2)
据我所知,这里涉及两个错误。两个都是java.util.Date
类中的{如果我是正确的),java.sql.Timestamp
的超类。
首先,在1900年华沙没有时间抵消过渡。我的Java 8知道的最早的过渡是在1915年。所以华沙在我们关注的所有时间里都与格林尼治标准时间相差1:24
我试过了:
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Warsaw"));
ZoneOffset offset0124 = ZoneOffset.ofHoursMinutes(1, 24);
System.out.println("" + new Date(0, 0, 1, 0, 59)
+ " -> " + new Date(0, 0, 1, 0, 59).toInstant().atOffset(offset0124));
System.out.println("" + new Date(0, 0, 1, 1, 14)
+ " -> " + new Date(0, 0, 1, 1, 14).toInstant().atOffset(offset0124));
System.out.println("" + new Date(0, 0, 1, 1, 24)
+ " -> " + new Date(0, 0, 1, 1, 24).toInstant().atOffset(offset0124));
打印:
Mon Jan 01 00:59:00 CET 1900 -> 1900-01-01T01:23+01:24
Mon Jan 01 01:38:00 CET 1900 -> 1900-01-01T01:38+01:24
Mon Jan 01 01:24:00 CET 1900 -> 1900-01-01T01:24+01:24
你使用的方法Timestamp.valueOf
方法间接使用了一个弃用的Date
构造函数,所以我(不是完全相同的构造函数,我使用没有秒的那个,信任它没有区别) 。我将评论以上三种情况落后:
Date.toString()
和OffsetDateTime
获得预期时间。OffsetDateTime
看到这一点。同样的错误。但是,Date.toString()
按预期生成00:59。在我看来,这是第二个以某种方式补偿第一个错误的错误。我没有检查过,但我怀疑这个bug的来源也会导致Timestamp.toString()
行为不正确。作为检查,我计算了0:59和1:24的Timestamp
个对象之间的差异。期望的结果是25分钟或1 500 000毫秒。代码是:
System.out.println(java.sql.Timestamp.valueOf("1900-01-01 01:24:00").getTime()
- java.sql.Timestamp.valueOf("1900-01-01 00:59:00").getTime());
打印
60000
60秒,与1分钟相同。因此,尽管这两个时间戳都以我们预期的方式打印,但仍然存在一个错误。