java zoneinfo 有什么问题?

2024-03-17

我的 Mageia 4 中有欧洲/莫斯科时区。

代码是这样的

System.out.println(new java.util.Date());
System.out.println(System.getProperty("user.timezone"));

returns

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

如果我将系统日期设置为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());

它返回

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]

and

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]

为什么这样?为什么这两种情况下的偏移量相同?


tl;dr

  • 不要使用偏移量 (+03:00)当您指的是时区(Europe/Moscow)
  • 切勿依赖 JVM 当前的默认时区。
  • 切勿使用java.util.Date.

在 UTC 中,使用java.time.Instant.

Instant.now()

对于某个时区的某个时刻,请使用java.time.ZonedDateTime.

ZonedDateTime.now(
    ZoneId.of( "Europe/Moscow" ) 
)

偏移量与时区

正如 Jon Skeet 的评论所指出的,您的 JVM 的初始默认时区不是一个时区 https://en.wikipedia.org/wiki/Time_zone,这只是一个与 UTC 的偏移量 https://en.wikipedia.org/wiki/UTC_offset.

有什么不同?偏移量只是小时数、分钟数和秒数,正数(早于 UTC)或负数(晚于 UTC)。时区是much更多的。时区是特定地区的人们使用的偏移量的过去、现在和未来变化的历史。只要政治家认为,某个地区的抵消额就可以改变。例如,许多政客相信了夏令时 (DST) https://en.wikipedia.org/wiki/Daylight_saving_time,并每年更改两次偏移量。

因此,如果您将时区设置为纯粹的偏移量,例如+03:00(比 UTC/GMT 早三个小时)而不是时区,例如Europe/Moscow,您当前的日期时间将始终报告为比 UTC 早三个小时。您所在地区的偏移量变化(例如 DST)将被忽略,因为您是这么说的,您说过“始终比 UTC 早三个小时”。

java.time

您正在使用可怕的日期时间类,这些类在几年前就被java.timeJSR 310 中定义的类。

代替TimeZone, use 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 中运行的所有应用程序的所有线程中的所有代码。你会在其他程序员背后粗鲁地改变区域。您甚至可能会发现他们的代码更改了后面的区域your back, during运行。

最好编写所有日期时间处理,不要依赖当前的默认区域(或区域设置)。通过传递可选参数明确指定您想要/预期的时区。就我个人而言,我希望这些时区参数是必需的而不是可选的,以帮助受过教育的程序员解决日期时间问题。

我们可以在上面的代码中看到一个例子。注意我们如何通过ZoneId对于俄罗斯来说now方法。否则,我们将捕获恰好是 JVM 当前默认时区的任何区域的挂钟时间中的当前时刻。

提示:如果很重要,请务必与用户确认时区。

java.util.Date::toString lies

请注意,toString方法上的Date您调用的对象具有动态应用 JVM 当前默认时区的反功能,同时生成表示该时刻的文本。尽管本意是好的,但这种不幸的设计决策却让无数试图在 Java 中争论日期时间值的程序员感到困惑。 Ajava.util.Date实际上采用 UTC 格式,是自 UTC 1970 年第一个时刻以来的毫秒数。字符串中显示的时区实际上并不在Date目的。

但这是没有意义的,因为这是其中之一many完全避免此类的原因。使用java.util.Instant反而。代替GregorianCalendar, use ZonedDateTime.


About java.time

The java.time http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html框架内置于 Java 8 及更高版本中。这些课程取代了麻烦的旧课程legacy https://en.wikipedia.org/wiki/Legacy_system日期时间类,例如java.util.Date https://docs.oracle.com/javase/10/docs/api/java/util/Date.html, Calendar https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html, & SimpleDateFormat http://docs.oracle.com/javase/10/docs/api/java/text/SimpleDateFormat.html.

要了解更多信息,请参阅甲骨文教程 http://docs.oracle.com/javase/tutorial/datetime/TOC.html。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310 https://jcp.org/en/jsr/detail?id=310.

The 乔达时间 http://www.joda.org/joda-time/项目,现在在维护模式 https://en.wikipedia.org/wiki/Maintenance_mode,建议迁移到java.time http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html类。

您可以交换java.time对象直接与您的数据库。用一个JDBC驱动程序 https://en.wikipedia.org/wiki/JDBC_driver符合JDBC 4.2 http://openjdk.java.net/jeps/170或稍后。不需要字符串,不需要java.sql.*类。

从哪里获取 java.time 类?

  • Java SE 8 https://en.wikipedia.org/wiki/Java_version_history#Java_SE_8, Java SE 9 https://en.wikipedia.org/wiki/Java_version_history#Java_SE_9, Java SE 10 https://en.wikipedia.org/wiki/Java_version_history#Java_SE_10, Java SE 11 https://en.wikipedia.org/wiki/Java_version_history#Java_SE_11, and later - Part of the standard Java API with a bundled implementation.
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 https://en.wikipedia.org/wiki/Java_version_history#Java_SE_6 and Java SE 7 https://en.wikipedia.org/wiki/Java_version_history#Java_SE_7
    • 大部分的java.time功能向后移植到 Java 6 和 7三十后端口 http://www.threeten.org/threetenbp/.
  • Android https://en.wikipedia.org/wiki/Android_(operating_system)
    • 更高版本的 Android 捆绑实现java.time类。
    • 对于早期的 Android (三十ABP项目适应三十后端口 http://www.threeten.org/threetenbp/(上文提到的)。看如何使用 ThreeTenABP... http://stackoverflow.com/q/38922754/642706.

The 三十额外 http://www.threeten.org/threeten-extra/项目通过附加类扩展了 java.time。该项目是 java.time 未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如Interval http://www.threeten.org/threeten-extra/apidocs/org/threeten/extra/Interval.html, YearWeek http://www.threeten.org/threeten-extra/apidocs/org/threeten/extra/YearWeek.html, YearQuarter http://www.threeten.org/threeten-extra/apidocs/org/threeten/extra/YearQuarter.html, and more http://www.threeten.org/threeten-extra/apidocs/index.html.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java zoneinfo 有什么问题? 的相关文章

随机推荐

  • FireMonkey 控件是否具有与 VCL Invalidate() 等效的方法?

    我正在创建一些自定义 FireMonkey GUI 控件 组件需要更新以响应用户交互 VCL 控件可以调用 Invalidate 将其放入队列中进行重绘 FireMonkey 有等效的方法吗 FireMonkey 控件有一个 Repaint
  • 在 Flutter/Dart 中如何将参数从命令行传递到 main ?

    如何运行命令并使用 Flutter Dart 传递一些自定义参数 以便可以在main 调用例如 flutter run device my custom arg 那么我可以通过以下方式访问它 void main List
  • 运行 Pig 脚本时的堆空间问题

    我正在尝试执行包含大约 3000 万数据的 Pig 脚本 但收到以下堆空间错误 gt ERROR 2998 Unhandled internal error Java heap space gt gt java lang OutOfMemo
  • 应将哪些文件导入到 Web 服务项目的 Subversion 存储库中?

    我使用Web服务自上而下的方法在Eclipse中创建了一个Java项目 即创建一个WSDL文件并使用它来生成带有axis2的Skeleton Java类和Web服务 因此 有很多自动生成的文件和axis2 jar图书馆 我的项目具有以下文件
  • 如何在 codeigniter 挂钩文件中加载模型

    这是我的问题 我正在构建一个需要过滤器的应用程序 我已经让过滤系统正常工作 我什至可以查明我当前想要访问的实际方法 问题是我无法从过滤器文件访问 CI 核心 我在网上搜索过 虽然我找到了一些建议的解决方案 例如 Dipping into C
  • @xmlschema jaxb package-info.java 编译错误

    我尝试在包级别使用注释 但从 Eclipse 中收到编译错误 我有课Head具有以下包 注释 javax xml bind annotation XmlSchema xmlns javax xml bind annotation XmlNs
  • Facebook 页面的 webhook [关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 我在一页上拥有管理员访问权限 我创建了 facebook 应用程序 并在我的网站上创建并验证了 webhook 问题是我
  • Html.ListBoxFor错误问题asp.mvc 3

    我的代码中有类似的内容 但收到错误 异常详细信息 System ArgumentException 值不能为 null 或空 参数名称 名称 我究竟做错了什么 感谢帮助 model IEnumerable
  • 表单外的复选框

    由于设计要求 我需要在表单外部放置几个复选框 是否仍然可以将这些值包含在表单的提交操作中 也许用javascript或其他我没有想到的方式 如果您使用 HTML5 则有一个form属性 请参见以下示例 p p
  • 如何使用 web3.js 1.0 进行身份验证和发送合约方法

    我对如何使用 web3 1 0 库执行合约的方法感到困惑 此代码有效 只要我先手动解锁帐户 var contract new web3 eth Contract contractJson contractAddress contract m
  • 使用回车符迭代文件

    有没有办法使用语法迭代文本文件 with open filename r as f for line in f print f 如果文件仅包含回车符而没有换行符 到目前为止我能做的就是 with open filename r as f f
  • 我所有的 javascript 在底部添加了一些代码

    我的网站使用 CodeIgniter 今天我发现我的网站在所有 JavaScript 文件 包括 jQuery 文件 的底部添加了一些代码 代码是这样的 4fd970 You are blocked by day limit 4fd970
  • 无法签入 TFS 的更改

    我在尝试签入对 Visual Studio Online 上托管的 TFS 的更改时遇到问题 上周才开始 我在跑步Visual Studio Professional 2017版本15 5 2 当我尝试签入更改时 出现以下错误 C My W
  • 将属性绑定到列表视图数据模板内的元素

    我无法让数据绑定在DataTemplate以 Xamarin 形式 我可以让它与ListView 即绑定RowHeight 但一旦进入DataTemplate 将内容设置为我的 ViewModel 的属性没有任何影响 在下面的示例中 如果我
  • Sqlite计算查询中YYYYMMDD日期格式之间的天数差异

    我已经以 YYYYMMDD 格式存储了一些患者记录的治疗日期 tdate 和接收日期 rdate 我想查询rdate tdate结果小于30的记录 我的尝试是 SELECT FROM table WHERE rdate tdate lt 3
  • Matlab:获取图中点击的坐标但保留按钮回调

    我需要一个函数 它可以为我提供在图形窗口中单击的坐标以及单击的鼠标按钮 左 中 右或按下 KEY 的坐标 但我仍然想使用 uicontrol 按钮 我目前正在使用 ginput 它工作正常 但按钮回调函数没有执行 因此我认为 ginput
  • 将日期字符串转换为 Unix 时间戳

    我的日期是 Mon Mar 15 20 51 18 0000 2010 如何将此日期转换为 Unix 时间戳 require time Time parse Mon Mar 15 20 51 18 0000 2010 to i
  • 从 intellij 检查中排除目录,但不从自动完成中排除

    据我所知 排除目录的唯一方法是将其标记为在项目结构中排除 然而 这将使 IntelliJ 完全忽略该目录 因此它不会出现在自动完成选项中 我不想要这个 我希望排除在检查之外 但包含在其他一切中 这可能吗 我正在使用 Intellij 12
  • MySQL InnoDB - 对事务感到困惑

    我已经使用MySQL很多年了 但是没有太多使用InnoDB引擎的经验 我现在正在对它运行一些测试 因为我将要使用它 并且从我读到的内容来看 如果该事务中的任何查询存在任何问题 它不应该允许任何内容 通过 我的问题是 为什么在下面的代码中 当
  • java zoneinfo 有什么问题?

    我的 Mageia 4 中有欧洲 莫斯科时区 代码是这样的 System out println new java util Date System out println System getProperty user timezone