“Java Date()以UTC格式返回日期” - 它实际上意味着什么?

时间:2011-05-10 08:40:28

标签: java date gmt

我的问题可能微不足道,但我只是在寻求澄清。我在SO中读到Java的Date()实际上总是在UTC时间,为什么当我创建一个Date()对象并使用toString()打印它时,它会显示本地时间。如果这不是打印它的正确方法,它应该是什么让我得到UTC时间?

3 个答案:

答案 0 :(得分:7)

对于格式化,您应该使用DateFormat实施(例如SimpleDateFormat)。这将允许您指定时区(和输出格式)。 Date本身没有时区概念 - 它代表了一个瞬间,使用“自Unix时代以来的毫秒”作为存储。 toString()方法只使用系统默认时区将表示的任何瞬间转换为本地时间。

我个人建议完全放弃内置的日期/时间API,并使用Joda Time作为一个更明智的库。

答案 1 :(得分:1)

java.util.Date 对象仅表示自称为“纪元”的标准基准时间(即 1970 年 1 月 1 日 00 日)以来的 毫秒 数: 00:00 GMT(或UTC)。由于它不保存任何时区信息,它的 toString 函数应用 JVM 的时区返回一个 String 格式,EEE MMM dd HH:mm:ss zzz yyyy,从这个 毫秒值。要以不同的格式和时区获取 String 对象的 java.util.Date 表示,您需要将 SimpleDateFormat 与所需的格式和适用的时区一起使用,例如

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

public class Main {
    public static void main(String[] args) {
        Date date = new Date();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.ENGLISH);

        sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
        String strDateNewYork = sdf.format(date);
        System.out.println(strDateNewYork);

        sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
        String strDateUtc = sdf.format(date);
        System.out.println(strDateUtc);
    }
}

输出:

2021-06-20T09:43:39.517-04:00
2021-06-20T13:43:39.517Z

ONLINE DEMO

java.time

java.util 日期时间 API 及其格式化 API SimpleDateFormat 已过时且容易出错。建议完全停止使用它们并切换到 modern Date-Time API*

另外,下面引用的是来自 home page of Joda-Time 的通知:

<块引用>

请注意,从 Java SE 8 开始,要求用户迁移到 java.time (JSR-310) - JDK 的核心部分,取代了该项目。

使用 java.time(现代日期时间 API)的解决方案:

import java.time.Instant;

public class Main {
    public static void main(String[] args) {
        Instant now = Instant.now();
        System.out.println(now);
    }
}

输出:

2021-06-20T13:37:42.174352Z

ONLINE DEMO

Instant 表示 UTC 中时间线上的一个瞬时点。输出中的 Z 是零时区偏移的 timezone designator。它代表祖鲁语并指定 Etc/UTC 时区(时区偏移为 +00:00 小时)。

Trail: Date Time 了解有关现代 Date-Time API 的更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,您可以使用 ThreeTen-Backport,它将大部分 java.time 功能向后移植到 Java 6 & 7. 如果您正在为 Android 项目工作并且您的 Android API 级别仍然不符合 Java-8,请检查 Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

答案 2 :(得分:0)

  

“ Java Date()以UTC返回日期”-实际上是什么意思?

UTC是我们调整全球时间的基准。

因为穴居人的日子是正午,所以正午或中午12:00。当然,这意味着在不同地方有不同的时刻。在日本,中午比欧洲早几个小时,而在美洲甚至更晚。

在现代时代,人类创造了time zones,其中午适用于大片土地,以至于太阳不可能同时覆盖所有土地。因此,太阳或“solar time”不再可以用来定义时间。现代时区定义为距基线一定小时数-分钟-秒。

什么基线?历史的命运将基线任意选择为贯穿Royal Observatory, Greenwich的纬度,遍及英国伦敦。东部的时区是UTC的某些小时-分钟-秒 ,而西部的时区是UTC的某些。例如,印度比世界标准时间早五个半小时,而加勒比海马提尼克岛比世界标准时间晚四个小时。

如果偏移量是零时,分,秒,那么我们说我们处于“在UTC”或“在UTC”。

  

Java的Date()实际上总是在UTC时间

是的,java.util.Date类尽管名称很不幸,但它代表的日期是一天中的时间,与UTC的偏移量是零。

顺便说一下,Date类现在已过时。 java.time.Instant类现在用作其替换,以表示UTC中的时刻。 Instant的分辨率为nanoseconds,比Date的{​​{3}}好。

  

当我创建一个Date()对象并使用toString()打印它时,它将显示本地时间

遗留日期时间类存在很多问题。如上所述,一种是较差的命名。另一个是不幸的设计决定所引起的良好意图,即Date::toString应该在生成文本时动态应用JVM的当前默认时区,以根据UTC进行调整。这个错误的决定没有给Java程序员带来混乱和痛苦,因为它给人一种错觉,即java.util.Date被分配了一个时区。

顺便说一句……更糟糕的是,java.util.Date 确实有一个时区,但是没有访问获取器/设置器方法,但深深地嵌入了源代码中。但是该区域确实会影响某些行为,例如确定此类对象之间的相等性。令人困惑?是。正如我所说的,这些传统的日期时间类充斥着糟糕的设计决策。

  

如果这不是正确的打印方式,那应该是什么,这样我才能获得UTC时间?

正确的方法是完全避免使用Date类。只能使用 java.time 类。

➥要获取UTC当前时刻,请使用milliseconds

Instant instant = Instant.now() ;

提示:如果您要更改时间以进行人工测试,请将备用Instant.now传递给Clock

要生成一个String的文本,该文本表示标准Instant.now( Clock )格式的Instant的值,只需调用toString。幸运的是,该类不会像Date那样注入时区。 ISO 8601方法说出了简单的真相,即UTC时刻的文本。

String output = instant.toString() ;
  

2019-12-03T10:15:30.032163Z

请注意,日期时间对象(例如Instant)没有“格式”。只有表示那些对象值的文本才具有格式。文本和日期时间对象是不同的,并且彼此分开。日期时间对象可以生成此类文本,并且可以解析此类文本,但实际上不是该文本。

如果需要灵活性来生成其他格式的文本,请应用ZoneOffset以获取OffsetDateTime对象,或应用ZoneId以获取ZonedDateTime对象。应用DateTimeFormatter对象以生成文本。


关于 java.time

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

目前位于SimpleDateFormatJoda-Time项目建议迁移到maintenance mode类。

要了解更多信息,请参见java.time。并在Stack Overflow中搜索许多示例和说明。规格为Oracle Tutorial

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

在哪里获取java.time类?

How to use ThreeTenABP…项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如ThreeTen-ExtraIntervalYearWeekYearQuarter