我的Mageia 4号有欧洲/莫斯科时区。
像这样的代码
System.out.println(new java.util.Date());
System.out.println(System.getProperty("user.timezone"));返回
Fri Oct 24 13:43:22 GMT+03:00 2014
GMT+03:00如果我将系统日期设置在2014年10月24日
而代码返回
Sun Oct 26 14:44:26 GMT+03:00 2014
GMT+03:00如果我将系统日期设置为26.10.2014
在我看来,这是java zoneinfo系统的错误行为。我下载了tzupdater并运行它,更新了欧洲/莫斯科的文件,现在它的大小是705 kB。
我尝试下面的代码:
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Moscow"));
System.out.println(new java.util.Date());
System.out.println(java.util.TimeZone.getDefault());然后它又回来了
Fri Oct 24 15:10:34 MSK 2014
sun.util.calendar.ZoneInfo[id="Europe/Moscow",offset=10800000,dstSavings=0,useDaylight=false,transitions=79,lastRule=null]和
Sun Oct 26 15:32:03 MSK 2014
sun.util.calendar.ZoneInfo[id="Europe/Moscow",offset=10800000,dstSavings=0,useDaylight=false,transitions=79,lastRule=null]为什么会这样呢?为什么这两种情况下的抵消是相同的?
发布于 2019-03-14 00:29:35
tl;dr
+03:00)时,不要使用偏移量(Europe/Moscow)java.util.Date。在UTC的某个时刻,使用java.time.Instant。
Instant.now()在时区的某个时刻,使用java.time.ZonedDateTime。
ZonedDateTime.now(
ZoneId.of( "Europe/Moscow" )
)偏移量与时区
正如Jon的评论所指出的,JVM最初的默认时区不是时区,它只是一个与世界协调时相抵。
有什么关系?偏移量只是指数小时、分钟和秒数、正(高于UTC)或负(UTC后面)。时区更重要。时区是过去、现在和未来对某一特定地区人民使用的偏移量变化的历史。一个地区的补偿可以在政客们认为的时候改变。例如,许多政客相信夏令时(DST)的疯狂行为,并且每年两次改变这种抵消。
因此,如果您将时区设置为仅为+03:00 (比UTC /格林尼治时间提前3小时)这样的偏移量,而不是像Europe/Moscow这样的时区,则您当前的日期时间总是比UTC提前3小时。您的地区的偏移量更改(如DST )将被忽略,因为您这样说,您说“总是比UTC提前三个小时”。
java.time
您正在使用几年前被JSR 310中定义的java.time类取代的糟糕的日期时间类。
不要使用TimeZone,而是使用ZoneId。
ZoneId z = ZoneId.of( "Europe/Moscow" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ; // Capture the current moment as seen in the wall-clock time used by the people of a particular region (a time zone).避免设置默认时区
您只应该将JVM的默认时区设置为绝望的最后一步。
设置默认时区(顺便说一下,设置默认的地区)会立即影响在JVM中运行的所有应用程序的所有线程中的所有代码。您将粗暴地改变其他程序员背后的区域。您甚至可能会发现,在运行时,他们的代码会在后台更改区域。
最好是编写所有日期时间处理,以避免依赖当前的默认区域(或地区)。通过传递可选参数,显式指定所需/预期的时区。就我个人而言,我希望那些时区参数是必需的,而不是可选的,以帮助受过教育的程序员处理日期时间问题。
我们可以在上面的代码中看到这方面的一个例子。注意如何将俄罗斯的ZoneId传递给now方法。否则,我们将捕获JVM当前默认时区所在区域的墙上时钟时间中的当前时刻。
提示:如果关键时刻,请始终与用户确认时区。
java.util.Date::toString谎言
请注意,您正在调用的toString对象上的Date方法具有一个反特性,即动态应用JVM当前的默认时区,同时生成表示该时刻的文本。尽管用意良好,但这个不幸的设计决策让无数试图在Java中争论日期-时间值的程序员感到困惑。一个java.util.Date实际上是以UTC为单位的,从1970年世界协调时的第一个时刻算起就是毫秒数。字符串中显示的时区实际上不在Date对象中。
但是这是没有意义的,因为这是完全避免这个类的许多原因之一。使用java.util.Instant代替。不要使用GregorianCalendar,而是使用ZonedDateTime。

关于java.time
http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html框架内置到Java8和更高版本中。这些类取代了麻烦的旧遗赠日期时间类,如java.util.Date、Calendar和SimpleDateFormat。
要了解更多信息,请参见http://docs.oracle.com/javase/tutorial/datetime/TOC.html。并搜索堆栈溢出以获得许多示例和解释。规范是JSR 310。
http://www.joda.org/joda-time/项目现在在维护模式中,建议迁移到java.time类。
您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC 4.2。不需要字符串,也不需要java.sql.*类。
在哪里获得java.time类?
三次-额外项目使用其他类扩展java.time。这个项目是将来可能加入java.time的试验场。您可以在这里找到一些有用的类,如Interval、YearWeek、YearQuarter和更多。
发布于 2014-10-31 17:30:11
通过增加正确时区的定义,解决了这个问题。
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Moscow"));发布于 2014-10-31 12:16:56
您的第二次测试(26.10.2014)是在更改到冬季之后,因此您可能还需要在-1小时内更正时间。
https://stackoverflow.com/questions/26674248
复制相似问题