我的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
如果我在24.10.2014设置系统日期
并且该代码返回
Sun Oct 26 14:44:26 GMT+03:00 2014
GMT+03:00
如果我在26.10.2014设置系统日期
在我看来,这是java zoneinfo系统的错误行为。 我下载了tzupdater并运行它,文件Europe / Moscow已更新,现在它的大小为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]
为什么这样?为什么在这两种情况下偏移是相同的?
答案 0 :(得分:2)
通过添加正确时区的定义来解决问题。
TimeZone.setDefault(TimeZone.getTimeZone("Europe/Moscow"));
答案 1 :(得分:2)
+03:00
)时不要使用偏移量(Europe/Moscow
)java.util.Date
。 使用UTC暂时使用java.time.Instant
。
Instant.now()
请在某个时区中使用java.time.ZonedDateTime
。
ZonedDateTime.now(
ZoneId.of( "Europe/Moscow" )
)
正如Jon Skeet的评论所指出的那样,您的JVM的初始默认时区不是time zone,而仅仅是offset-from-UTC。
有什么区别?偏移量只是小时(分钟)和秒(正数(在UTC之前)或负数(在UTC之后))的数量。时区多了 个。时区是特定区域的人们过去,现在和将来对偏移量的更改的历史记录。每当政界人士认为如此时,区域的偏移量就会改变。例如,许多政客都接受Daylight Saving Time (DST)的疯癫,并且每年两次更改抵消额。
因此,如果您将时区设置为仅偏移量(例如+03:00
(比UTC / GMT早3小时),而不是时区(例如Europe/Moscow
),则当前日期时间将始终报告时间比UTC早三小时。您所在区域的偏移量更改(例如DST)将被忽略,因为您是这样说的,您说的是“始终比UTC提前三小时”。
您使用的是可怕的日期时间类,而这些类在几年前已被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年UTC的第一刻起算。字符串中显示的时区实际上不在Date
对象中。
但这是没有根据的,因为这是许多完全避免此类的原因之一。请改用java.util.Instant
。使用GregorianCalendar
代替ZonedDateTime
。
java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
目前位于Joda-Time的maintenance mode项目建议迁移到java.time类。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
在哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。
答案 2 :(得分:0)
您的第二次测试(2014年10月26日)是在冬季变化之后所以您可能需要更正时间-1小时