Force Java timezone as GMT/UTC

我需要强制对 GMT/UTC 执行任何与时间相关的操作,而不管机器上设置的时区如何。有什么方便的代码吗?

澄清一下,我对所有操作都使用 DB 服务器时间,但它是根据本地时区格式化的。

谢谢!

301676 次浏览

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

详情请参阅 SimpleDateFormat.setTimeZone(..)Calendar.setTimeZone(..)

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

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

如果在从数据库 ResultSet检索 Date/Time/Timestamp 对象时需要设置特定的时区,请使用接受 Calendar对象的 getXXX方法的第二种形式:

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);

Usefull Reference

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

我必须为 Windows2003Server 设置 JVM 时区,因为它总是为 new Date ()返回 GMT;

-Duser.timezone=America/Los_Angeles

Or your appropriate time zone. Finding a list of time zones proved to be a bit challenging also...

这里有两个清单;

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

你可以使用 SetDefault ()改变时区:

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

另外,如果你可以这样设置 JVM 时区

System.setProperty("user.timezone", "EST");

or -Duser.timezone=GMT in the JVM args.

for me, just quick 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"));
}

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

创建一对客户机/服务器,以便在执行之后,客户机服务器发送正确的时间和日期。然后,客户机询问服务器 pmGMT,服务器返回正确的答案。

如果你想得到格林尼治标准时间只与 intiger: Var currentTime = new Date () ; Var currentYear = “2010” Var currentMonth = 10; var currentDay ='30' Var current 小时 =’20’ 每分钟 =’20’ Var current =’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)

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

使用系统属性:

-Duser.timezone=UTC

博士

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

避免依赖主机操作系统或 JVM 作为默认时区

我建议您编写所有的代码来显式地说明所需/期望的时区。您不必依赖于 JVM 当前的默认时区。请注意,JVM 的当前默认时区可以在运行时更改 at any moment,任何应用程序的任何线程中的任何代码都可以调用 TimeZone.setDefault。这样的调用会立即影响该 JVM 中的所有应用程序。

爪哇时间

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

遗留的日期时间类已经被 JSR 310中定义的 爪哇时间类所取代。

若要表示时区,请使用 ZoneId。若要表示与 UTC 的偏移量,请使用 ZoneOffset。偏移量仅仅是在本初子午线之前或之后的几个小时-分钟-秒。时区更重要。时区是过去、现在和未来的变化历史,用来抵消特定地区人们使用的偏移量。

我需要强制任何时间相关的操作到格林尼治标准时间/协调世界时

对于零小时-分钟-秒的偏移量,使用常量 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和更高版本中,我们可以与数据库交换 爪哇时间对象。JDBC 需要 OffsetDateTime,而 InstantZonedDateTime是可选的。

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

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

  • 提取一个 Instant: odt.toInstant()
  • 从给定的偏移量调整到零的偏移量: OffsetDateTime odtUtc = odt.withOffsetSameInstant (ZoneOffset.UTC) ;’。

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


About 爪哇时间

The < em > java.time framework is built into Java 8 and later. These classes supplant the troublesome old 遗产 date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

要了解更多,请参阅 < em > Oracle 教程 。并搜索堆栈溢出许多例子和解释。规范是 JSR 310

现在在 维修模式中的 尤达时间项目建议迁移到 爪哇时间类。

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

Where to obtain the java.time classes?

在 MySQL 中执行这一行来重置时区:

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

希望以下代码可以帮助您。

    DateFormat formatDate = new SimpleDateFormat(ISO_DATE_TIME_PATTERN);
formatDate.setTimeZone(TimeZone.getTimeZone("UTC"));
formatDate.parse(dateString);