java不正确的时区

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2106525/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 03:36:06  来源:igfitidea点击:

java incorrect timezone

javatimezone

提问by Jonathan Maddison

I have an instance of Java which seems to be using a completely incorrect time zone. Instead of using the Australia/Sydney time zone which Windows is using, it is using the America/Caracas time zone.

我有一个 Java 实例,它似乎使用了一个完全不正确的时区。它没有使用 Windows 使用的澳大利亚/悉尼时区,而是使用美国/加拉加斯时区。

I checked the Windows time through the system clock firstly, then checked HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/and ControlSet001, ControlSet002. All are set to a Sydney time zone.

我首先通过系统时钟检查了 Windows 时间,然后检查HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/ControlSet001ControlSet002。所有都设置为悉尼时区。

Does anybody know if this is a bug in Java, or if it is referring to a time set elsewhere?

有谁知道这是 Java 中的错误,还是指的是其他地方设置的时间?

Java version is 1.6.0_06

Java 版本是 1.6.0_06

采纳答案by Pool

Ensure you set the timezone for the JVM when starting the application:

确保在启动应用程序时为 JVM 设置时区:

-Duser.timezone="Australia/Sydney"

回答by balent

Try in your app to get default timezone, or set timezone manually (commented line).

尝试在您的应用中获取默认时区,或手动设置时区(注释行)。

Little example of mine:

我的小例子:

import java.text.DateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class Main {
    public static void main(String[] args) {
        Locale locale = Locale.getDefault();
        TimeZone localTimeZone = TimeZone.getDefault(); 
        //TimeZone localTimeZone = TimeZone.getTimeZone("Australia/Sydney");
        DateFormat dateFormat = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, locale);
        dateFormat.setTimeZone(localTimeZone);
        Date rightNow = new Date();
        System.out.println(locale.toString() + ": " + dateFormat.format(rightNow));
    }
}

回答by trashgod

You should update your JRE/SDK, but TZUpdatermay be sufficient.

您应该更新您的JRE/SDK,但TZUpdater可能就足够了。

回答by Roman

Check information on the following link: http://techtavern.wordpress.com/2010/04/15/java-and-incorrect-timezone-on-windows-xp/
It shows, that there is a bug in JVM, causing reading incorrect default timezone from windows registry. There is no bug fix yet.

检查以下链接上的信息:http: //techtavern.wordpress.com/2010/04/15/java-and-incorrect-timezone-on-windows-xp/
它表明,JVM 中存在一个错误,导致读取Windows 注册表中的默认时区不正确。还没有错误修复。

回答by Durandal

I had the very same problem recently, apparently this is caused by an ambiguity how Windows represents its timezone settings in the registry and Java failing to interpret it correctly.

我最近遇到了同样的问题,显然这是由于 Windows 在注册表中表示其时区设置的方式不明确,而 Java 未能正确解释它。

More details can be found in this article, which also describes "cures" for the affected machine:

更多细节可以在这篇文章中找到,其中还描述了受影响机器的“治愈”:

  • Changing date/time manually and then changing back to original correct time.
  • Changing timezone and then back to original one.
  • Requesting automatic time update from time server.
  • 手动更改日期/时间,然后更改回原来的正确时间。
  • 更改时区,然后回到原来的时区。
  • 从时间服务器请求自动时间更新。

回答by Robert A Henru

I had the same error, while I was setting my timezone to Malay Peninsula Standard Time, the JVM gave me Venezuela Time timezone.

我遇到了同样的错误,当我将时区设置为马来半岛标准时间时,JVM 给了我委内瑞拉时区。

The following fix works for me:

以下修复对我有用:

In the registry editor, edit your timezone to another timezone (I was trying to put another text like "Singapore Time". You can find the registry here:

在注册表编辑器中,将您的时区编辑为另一个时区(我试图添加另一个文本,例如“新加坡时间”。您可以在此处找到注册表:

HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/TimeZoneInformation

HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/TimeZoneInformation

And then, I reset it back to my desired timezone using Control Panel, Date and Time setting. When I check back to the registry editor, I can see it is reverted to Malay Peninsula Standard Time. And my JVM reads it correctly now...

然后,我使用控制面板、日期和时间设置将其重置回我想要的时区。当我返回注册表编辑器时,我可以看到它已恢复为马来半岛标准时间。我的 JVM 现在正确读取它...

回答by Baruch Youssin

There is a history of such problems that come and go, and no reasonable solution. See more here: Java incorrect time zone bug on Windows

历史上这样的问题来来去去,没有合理的解决办法。在此处查看更多信息:Windows 上的 Java 错误时区错误

Edit:Answering Tom and francis: In brief, Java runtime has hard time doing the job of correctly finding out the current time zone on the computer.

编辑:回答汤姆和弗朗西斯:简而言之,Java 运行时很难正确找出计算机上的当前时区。

Windows registry information on the time zones has been unreliable, and the same for native windows API which relies on msvcrt.dll and various msvcrxx.dll . There is also Managed (.NET) API which requires installing a certain version of .NET Framework which contradicts portability of Java.

Windows 时区注册表信息不可靠,对于依赖 msvcrt.dll 和各种 msvcrxx.dll 的本机 Windows API 也是如此。还有托管 (.NET) API,它需要安装特定版本的 .NET Framework,这与 Java 的可移植性相矛盾。

Thus, developers of Java runtime have hard time with the current time zone on Windows, and this may continue until Microsoft has some reason to cooperate.

因此,Java 运行时的开发人员很难在 Windows 上使用当前时区,这种情况可能会持续到 Microsoft 有理由合作为止。

If you want your Java application work correctly in any time zone, give users a possibility to correct the time zone via GUI.

如果您希望 Java 应用程序在任何时区都能正常工作,请让用户可以通过 GUI 更正时区。

回答by Basil Bourque

tl;dr

tl;博士

A Java programmer should never rely on the JVM's current default time zone.

Java 程序员永远不应该依赖 JVM 的当前默认时区。

  • Always specify a proper time zone namein the format of Continent/Region, such as Africa/Casablanca.
  • Always confirm the desired/expected zone with the user, when important.
  • 始终以 格式指定正确的时区名称Continent/Region,例如Africa/Casablanca.
  • 重要时,始终与用户确认所需/预期的区域。

Proper time zone names

正确的时区名称

Specify a proper time zone namein the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as CST, ESTor ISTas they are nottrue time zones, not standardized, and not even unique(!). For example, if you use ISTfor Ireland Standard Time, you might instead get India Standard Time with surprising results.

以、、 或等格式指定正确的时区名称。切勿使用 2-4 个字母的缩写,例如,或者因为它们不是真正的时区,不标准化,甚至不是唯一的(!)。例如,如果您使用爱尔兰标准时间,您可能会得到印度标准时间,但结果令人惊讶。continent/regionAmerica/MontrealAfrica/CasablancaPacific/AucklandCSTESTISTIST

ZoneId z = ZoneId.of( "America/Montreal" ) ; // Or "Pacific/Auckland", "Africa/Tunis", etc. 

Specify time zone

指定时区

Never rely on the JVM's current default time zone.That default value can change.

永远不要依赖 JVM 的当前默认时区。该默认值可以更改。

  • As the other Answers explain, most JVMs by default use the host OS' default time zone in play when the JVM launched.
  • Or the script launching the JVM may pass a flag to specify a default time zone at launch.
  • And during runtime(!)the JVM‘s current default time zone can be set by any code in any thread of any app within the JVM calling TimeZone.setDefault. (By the way, TimeZoneis obsoleted by ZoneId& ZoneOffset, except for that setter method which should never be called except in the most extreme situation.)
  • And, of course, the user or sysadmin can change their current default time zone on the host OS which is notdetected by running JVMs in most implementations as far as I know.
  • 正如其他答案所解释的那样,默认情况下,大多数 JVM 在 JVM 启动时使用主机操作系统的默认时区。
  • 或者启动 JVM 的脚本可能会传递一个标志来指定启动时的默认时区。
  • 并且在运行时(!)期间,JVM 的当前默认时区可以由 JVM 调用中任何应用程序的任何线程中的任何代码设置TimeZone.setDefault。(顺便说一句,TimeZone已被ZoneId&废弃,ZoneOffset除了在最极端的情况下永远不应该调用的 setter 方法。)
  • 而且,当然,用户或系统管理员可以更改主机操作系统上的当前默认时区,据我所知,在大多数实现中运行 JVM无法检测到这些时区。

So, for all those reasons, the JVM's current default time zone is completely out of the hands of the programmer, and even worse, can change dynamically at runtime. Therefore, using current default is not reliable.

因此,由于所有这些原因,JVM 的当前默认时区完全不受程序员控制,更糟糕的是,它可以在运行时动态更改。因此,使用当前默认值是不可靠的。

Use the JVM's current default time zone for only the most casual of purposes. For anything that matters, you simply must confirm the intended zone with the user. This is an inconvenient truth often resisted by programmers, but true nonetheless.

仅出于最随意的目的使用 JVM 的当前默认时区。对于任何重要的事情,您只需与用户确认预期的区域。这是一个经常被程序员抵制的令人不快的事实,但仍然如此。



Locale

语言环境

Tip: Ditto for Locale. The JVM's current default locale may or may not match that of the host OS, can change at any moment, and is therefore unreliable. Always confirm the desired/expected Localewith the user.

提示:同上Locale。JVM 的当前默认语言环境可能与主机操作系统的语言环境相匹配,也可能不匹配,可能随时更改,因此不可靠。始终Locale与用户确认所需/期望。



About java.time

关于java.time

The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date, Calendar, SimpleDateFormat, and java.util.TimeZone.

java.time框架是建立在Java 8和更高版本。这些类取代麻烦的老传统日期时间类,如java.util.DateCalendarSimpleDateFormat,和java.util.TimeZone

The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.

现在处于维护模式Joda-Time项目建议迁移到java.time类。

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310

You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*classes.

您可以直接与您的数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*

Where to obtain the java.time classes?

从哪里获得 java.time 类?

The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多