我的 Mageia 4 中有欧洲/莫斯科时区。
代码是这样的
System.out.println(new java.util.Date());
System.out.println(System.getProperty("user.timezone"));
Run Code Online (Sandbox Code Playgroud)
回报
Fri Oct 24 13:43:22 GMT+03:00 2014
GMT+03:00
Run Code Online (Sandbox Code Playgroud)
如果我将系统日期设置为2014年10月24日
该代码返回
Sun Oct 26 14:44:26 GMT+03:00 2014
GMT+03:00
Run Code Online (Sandbox Code Playgroud)
如果我将系统日期设置为2014年10月26日
在我看来,这是 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());
Run Code Online (Sandbox Code Playgroud)
它返回
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]
Run Code Online (Sandbox Code Playgroud)
和
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]
Run Code Online (Sandbox Code Playgroud)
为什么这样?为什么这两种情况下的偏移量相同?
+03:00当您表示时区 ( Europe/Moscow)时,请勿使用偏移量 ( )java.util.Date.对于 UTC 时间,请使用java.time.Instant.
Instant.now()\nRun Code Online (Sandbox Code Playgroud)\n\n对于某个时区的某个时刻,请使用java.time.ZonedDateTime。
ZonedDateTime.now(\n ZoneId.of( "Europe/Moscow" ) \n)\nRun Code Online (Sandbox Code Playgroud)\n\n正如 Jon Skeet 的评论所指出的,您的 JVM\xe2\x80\x99s 初始默认时区不是一个时区,它只是与 UTC 的偏移量。
\n\n有什么不同?偏移量只是小时数、分钟数和秒数,正数(早于 UTC)或负数(晚于 UTC)。时区的意义要大得多。时区是特定地区的人们使用的偏移量的过去、现在和未来变化的历史。只要政治家认为,某个地区的抵消额就可以改变。例如,许多政治家相信夏令时 (DST)的疯狂做法,并每年更改两次偏移量。
\n\n因此,如果您将时区设置为仅偏移量(例如+03:00(比 UTC/GMT 提前三小时))而不是时区(例如 )Europe/Moscow,则您当前的日期时间将始终报告为比 UTC 早三个小时。您所在地区的偏移量变化(例如 DST)将被忽略,因为您是这么说的,您说过“始终比 UTC 早三个小时”。
您正在使用糟糕的日期时间类,这些类在几年前就被JSR 310 中定义的java.time类所取代。
\n\n而不是TimeZone使用ZoneId.
ZoneId z = ZoneId.of( "Europe/Moscow" ) ;\nZonedDateTime 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).\nRun Code Online (Sandbox Code Playgroud)\n\n您只应将 JVM 设置为默认时区作为最后的绝望之举。
\n\n设置默认时区(顺便说一句,还有默认区域设置)会立即影响该 JVM 中运行的所有应用程序的所有线程中的所有代码。你会在其他程序员背后粗鲁地改变区域。您甚至可能会发现他们的代码在运行时更改了您背后的区域。
\n\n最好编写所有日期时间处理,不要依赖当前的默认区域(或区域设置)。通过传递可选参数明确指定您想要/预期的时区。就我个人而言,我希望这些时区参数是必需的而不是可选的,以帮助受过教育的程序员解决日期时间问题。
\n\n我们可以在上面的代码中看到一个例子。请注意我们如何将ZoneId“俄罗斯”传递给该now方法。否则,我们将捕获恰好是 JVM\xe2\x80\x99s 当前默认时区的任何区域的挂钟时间中的当前时刻。
提示:如果很重要,请务必与用户确认时区。
\n\njava.util.Date::toString谎言请注意,您调用的对象toString上的方法Date具有动态应用 JVM\xe2\x80\x99s 当前默认时区的反功能,同时生成表示该时刻的文本。尽管本意是好的,但这种不幸的设计决策却让无数试图在 Java 中争论日期时间值的程序员感到困惑。Ajava.util.Date实际上采用 UTC 格式,表示自 UTC 1970 年第一个时刻以来的毫秒数。字符串中显示的时区实际上并不在Date对象中。
但这是没有意义的,因为这是完全避免此类的众多原因之一。java.util.Instant代替使用。而不是GregorianCalendar使用ZonedDateTime.
java.time框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧遗留日期时间类,例如java.util.Date, Calendar, & SimpleDateFormat。
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310。
\n\nJoda -Time项目现在处于维护模式,建议迁移到java.time类。
\n\n您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*
从哪里获取 java.time 类?
\n\nThreeTen -Extra项目通过附加类扩展了 java.time。该项目是 java.time 未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如Interval、、等YearWeekYearQuarter。
| 归档时间: |
|
| 查看次数: |
6175 次 |
| 最近记录: |