Java.util.Date:尝试更多地了解UTC和ET

时间:2011-05-11 15:18:26

标签: java date timezone

我住在北卡罗来纳州,顺便说一句,这是在东边。所以我编译并运行这段代码并打印出同样的东西。文档说java.util.date尝试反映UTC时间。

Date utcTime = new Date();
Date estTime = new Date(utcTime.getTime() + TimeZone.getTimeZone("ET").getRawOffset());
DateFormat format = new SimpleDateFormat("dd/MM/yy h:mm a");
System.out.println("UTC: " + format.format(utcTime));
System.out.println("ET: " + format.format(estTime));   

这就是我得到的

UTC: 11/05/11 11:14 AM
ET: 11/05/11 11:14 AM

但是如果我去试图反映所有不同时间的website,那么UTC和ET是不同的。我在这里做错了什么

6 个答案:

答案 0 :(得分:7)

那是因为getRawOffset()返回0 - 它也为我做“ET”,实际上TimeZone.getTimeZone("ET")基本上返回GMT。我怀疑那不是你的意思。

北卡罗来纳州最好的奥尔森时区名称是“America / New_York”,我相信。

请注意,您不应该只将时区的原始偏移量添加到UTC时间 - 您应该设置格式化程序的时区。 Date值并不真正了解时区......自1970年1月1日UTC以来,它总是只有几毫秒。

所以你可以使用:

import java.text。; import java.util。;

Date date = new Date();
DateFormat format = new SimpleDateFormat("dd/MM/yy h:mm a zzz");

format.setTimeZone(TimeZone.getTimeZone("America/New_York"));
System.out.println("Eastern: " + format.format(date));

format.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
System.out.println("UTC: " + format.format(date));

输出:

Eastern: 11/05/11 11:30 AM EDT
UTC: 11/05/11 3:30 PM UTC

我还建议您考虑使用Joda Time而不是内置库 - 这是一个更好的API。

答案 1 :(得分:1)

手风琴this post你必须写TimeZone.getTimeZone("ETS")而不是TimeZone.getTimeZone("ET")

答案 2 :(得分:1)

TimeZone.getTimeZone(“ET”)。getRawOffset()返回0这就是为什么

答案 3 :(得分:1)

您要查找的时区为"EST""EDT"(白天时间),而不是"ET"。请参阅http://mindprod.com/jgloss/timezone.html

答案 4 :(得分:1)

东部标准时间的正确缩写是“EST”,而不是“ET”。如果getRawOffset()方法传递给未知时区,则看起来{0}}方法返回0。

TimeZone.getTimeZone("EST").getRawOffset()

此外,当您输出utcTime变量时,您不会输出UTC时间。您正在输出EST时间,因为您居住在该时区。根据我的理解,Date类在内部以UTC格式存储时间...但是当您将其格式化为将其输出为人类可读的字符串时,它会考虑当前的区域设置/时区。

答案 5 :(得分:1)

不知不觉中,您在代码中引入了两个主要问题

  1. 未使用正确的时区名称:两个/三个/四个字母的时区名称(例如 ET、EST、CEST 等)容易出错。 proper way of naming a timezone地区/城市,例如欧洲/伦敦。在大多数情况下,地区城市所属大陆的名称。
  2. 不将 LocaleSimpleDateFormat 一起使用:解析/格式化类型,例如旧版 SimpleDateFormat 或现代版 DateTimeFormatterLocale 敏感,因此您应该始终使用 Locale 以避免出现意外。您可以查看 this answer 以了解更多信息。

另外,请注意,java.util.Date 对象不像 modern Date-Time types 那样是真正的 Date-Time 对象;相反,它表示自称为“纪元”的标准基准时间以来的毫秒数,即 January 1, 1970, 00:00:00 GMT(或 UTC)。由于它不包含任何格式和时区信息,因此它应用格式 EEE MMM dd HH:mm:ss z yyyy 和 JVM 的时区来返回从该毫秒值派生的 Date#toString 值。如果您需要以不同的格式和时区打印日期时间,则需要使用具有所需格式和适用时区的 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("dd/MM/yy hh:mm a zzz", Locale.ENGLISH);

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

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

示例输出:

05/06/21 08:29 AM EDT
05/06/21 12:29 PM UTC

ONLINE DEMO

java.time

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

使用现代 API java.time 的演示:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;

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

        ZonedDateTime zdtUTC = now.atZone(ZoneId.of("Etc/UTC"));
        System.out.println(zdtUTC);

        ZonedDateTime zdtNewYork = now.atZone(ZoneId.of("America/New_York"));
        System.out.println(zdtNewYork);
    }
}

示例输出:

2021-06-05T12:19:58.092338Z
2021-06-05T12:19:58.092338Z[Etc/UTC]
2021-06-05T08:19:58.092338-04:00[America/New_York]

ONLINE DEMO

需要不同格式的输出字符串?

您可以使用 DateTimeFormatter 作为不同格式的输出字符串,例如

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        Instant now = Instant.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/uu hh:mm a zzz", Locale.ENGLISH);

        ZonedDateTime zdtUTC = now.atZone(ZoneId.of("Etc/UTC"));
        System.out.println(dtf.format(zdtUTC));

        ZonedDateTime zdtNewYork = now.atZone(ZoneId.of("America/New_York"));
        System.out.println(dtf.format(zdtNewYork));
    }
}

示例输出:

05/06/21 12:34 PM UTC
05/06/21 08:34 AM EDT

ONLINE DEMO

在这里,您可以使用 yy 代替 uu,而是使用 I prefer u to y

modern Date-Time API 中详细了解 java.timeTrail: Date Time*


* 出于任何原因,如果您必须坚持使用 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