强制Java时区为GMT / UTC

时间:2010-04-13 08:21:47

标签: java timezone utc gmt

我需要强制任何与GMT / UTC相关的操作,无论机器上设置的时区如何。代码中有什么方便的方法吗?

为了澄清,我正在使用数据库服务器时间进行所有操作,但它根据当地时区进行格式化。

谢谢!

13 个答案:

答案 0 :(得分:105)

OP回答了这个问题,要更改正在运行的JVM的单个实例的默认时区,设置user.timezone系统属性:

java -Duser.timezone=GMT ... <main-class>

如果您需要在从数据库ResultSet检索日期/时间/时间戳对象时设置特定时区,请使用采用getXXX对象的Calendar方法的第二种形式:

Calendar tzCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
ResultSet rs = ...;
while (rs.next()) {
    Date dateValue = rs.getDate("DateColumn", tzCal);
    // Other fields and calculations
}

或者,在PreparedStatement中设置日期:

Calendar tzCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
PreparedStatement ps = conn.createPreparedStatement("update ...");
ps.setDate("DateColumn", dateValue, tzCal);
// Other assignments
ps.executeUpdate();

这些将确保当数据库列不保留时区信息时,存储在数据库中的值是一致的。

java.util.Datejava.sql.Date类以UTC格式存储实际时间(毫秒)。要将输出格式化为另一个时区,请使用SimpleDateFormat。您还可以使用Calendar对象将时区与值相关联:

TimeZone tz = TimeZone.getTimeZone("<local-time-zone>");
//...
Date dateValue = rs.getDate("DateColumn");
Calendar calValue = Calendar.getInstance(tz);
calValue.setTime(dateValue);

有用的参考

https://docs.oracle.com/javase/9/troubleshoot/time-zone-settings-jre.htm#JSTGD377

https://confluence.atlassian.com/kb/setting-the-timezone-for-the-java-environment-841187402.html

答案 1 :(得分:18)

此外,如果您可以这样设置JVM时区

System.setProperty("user.timezone", "EST");
JVM中的

-Duser.timezone=GMT

答案 2 :(得分:10)

我必须为Windows 2003 Server设置JVM时区,因为它总是为新的Date()返回GMT;

-Duser.timezone=America/Los_Angeles

或您的适当时区。找到时区列表证明也有点挑战......

这是两个清单;

http://wrapper.tanukisoftware.com/doc/english/prop-timezone.html

http://publib.boulder.ibm.com/infocenter/iseries/v5r3/index.jsp?topic=%2Frzatz%2F51%2Fadmin%2Freftz.htm

答案 3 :(得分:8)

对我来说,只需快速SimpleDateFormat,

  private static final SimpleDateFormat GMT = new SimpleDateFormat("yyyy-MM-dd");
  private static final SimpleDateFormat SYD = new SimpleDateFormat("yyyy-MM-dd");
  static {
      GMT.setTimeZone(TimeZone.getTimeZone("GMT"));
    SYD.setTimeZone(TimeZone.getTimeZone("Australia/Sydney"));
  }

然后使用不同的时区格式化日期。

答案 4 :(得分:7)

tl; dr

String sql = "SELECT CURRENT_TIMESTAMP ;
…
OffsetDateTime odt = myResultSet.getObject( 1 , OffsetDateTime.class ) ;

避免在默认时区使用主机操作系统或JVM

我建议您编写所有代码以明确声明所需/预期的时区。您不必依赖JVM的当前默认时区。并且请注意,JVM的当前默认时区可以在运行时随时更改 ,任何应用程序的任何线程中的任何代码都可以调用TimeZone.setDefault。这样的调用会立即影响该JVM中的所有应用。

java.time

其他一些答案是正确的,但现在已过时。与最早的Java版本捆绑在一起的可怕的日期时间类是有缺陷的,由不了解日期时间处理的复杂性和微妙之处的人编写。

JSR 310中定义的 java.time 类已取代了传统的日期时间类。

要表示时区,请使用ZoneId。要表示自UTC的偏移量,请使用ZoneOffset。偏移量仅在本初子午线之前或之后数小时-分钟-秒。时区更多。时区是特定地区人民过去,现在和将来对偏移量的更改的历史记录。

我需要对GMT / UTC进行任何与时间相关的操作

对于零时分秒,请使用常数ZoneOffset.UTC

Instant

要使用UTC捕获当前时刻,请使用Instant。此类表示UTC中的时刻,根据定义始终为UTC。

Instant instant = Instant.now() ;  // Capture current moment in UTC.

ZonedDateTime

要查看某个特定地区的人们在墙上钟表中使用的同一时刻,请调整到一个时区。同一时刻,时间轴上的同一点,不同的时钟时间。

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

数据库

您提到一个数据库。

要从数据库中检索时刻,您的列应为类似于SQL标准TIMESTAMP WITH TIME ZONE的数据类型。检索对象而不是字符串。在JDBC 4.2和更高版本中,我们可以与数据库交换 java.time 对象。 JDBC需要OffsetDateTime,而InstantZonedDateTime是可选的。

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

在大多数数据库和驱动程序中,我想您将获得UTC所示的时刻。但是,如果没有,您可以通过以下两种方式进行调整:

  • 提取Instantodt.toInstant()
  • 从给定的偏移量调整为零偏移量:OffsetDateTime odtUtc = odt.withOffsetSameInstant(ZoneOffset.UTC);`。

Table of date-time types in Java (both legacy and modern) and in standard SQL


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规范为JSR 310

Joda-Time项目(现在位于maintenance mode中)建议迁移到java.time类。

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

在哪里获取java.time类?

答案 5 :(得分:6)

我会以原始形式(长时间戳或java的日期)从DB中检索时间,然后使用SimpleDateFormat对其进行格式化,或使用Calendar来操作它。在这两种情况下,您都应该在使用之前设置对象的时区。

有关详细信息,请参阅SimpleDateFormat.setTimeZone(..)Calendar.setTimeZone(..)

答案 6 :(得分:3)

您可以使用TimeZone.setDefault()更改时区:

TimeZone.setDefault(TimeZone.getTimeZone("GMT"))

答案 7 :(得分:1)

创建一对客户端/服务器,以便在执行后,客户端服务器发送正确的时间和日期。然后,客户端询问服务器pm GMT,服务器发送回答权。

答案 8 :(得分:1)

哇。我知道这是一个古老的线程,但我可以说的是不要在任何用户级代码中调用TimeZone.setDefault()。这总是为整个JVM设置时区,并且几乎总是一个非常糟糕的主意。学习使用joda.time库或Java 8中新的DateTime类,它与joda.time库非常相似。

答案 9 :(得分:1)

在MySQL中执行此行以重置您的时区:

SET @@global.time_zone = '+00:00';

答案 10 :(得分:0)

使用系统属性:

-Duser.timezone=UTC

答案 11 :(得分:0)

希望以下代码会为您提供帮助。

AttributeError: 'ChunkedStream' object has no attribute 'closed'

答案 12 :(得分:-4)

如果您希望仅使用intiger获得GMT时间:     var currentTime = new Date();     var currentYear ='2010'     var currentMonth = 10;     var currentDay = '30'     var currentHours = '20'     var currentMinutes = '20'     var currentSeconds = '00'     var currentMilliseconds = '00'

currentTime.setFullYear(currentYear);
currentTime.setMonth((currentMonth-1)); //0is January
currentTime.setDate(currentDay);  
currentTime.setHours(currentHours);
currentTime.setMinutes(currentMinutes);
currentTime.setSeconds(currentSeconds);
currentTime.setMilliseconds(currentMilliseconds);

var currentTimezone = currentTime.getTimezoneOffset();
currentTimezone = (currentTimezone/60) * -1;
var gmt ="";
if (currentTimezone !== 0) {
  gmt += currentTimezone > 0 ? ' +' : ' ';
  gmt += currentTimezone;
}
alert(gmt)