4

我的问题很简单解释:

如果我这样做:

public class Main {

public static void main(String[] args) throws Exception {
        Date d = new Date(0L );
        System.out.println(d);
}

}

我得到以下输出:Thu Jan 01 01:00:00 CET 1970

根据文档,我期待:Thu Jan 01 00:00:00 CET 1970

我想走错了...

编辑:确实,我读文档太快了。我应该有 Thu Jan 01 00:00:00 GMT 1970

那么,如何强制使用 GMT,而忽略所有当地时间?

编辑,解决方案:

public static void main(String[] args) throws Exception {
    SimpleDateFormat sdf = new SimpleDateFormat("H:m:s:S");
SimpleTimeZone tz = new SimpleTimeZone(0,"ID");
sdf.setTimeZone(tz) ;
Date d = new Date(0L );
System.out.println( sdf.format(d));
}
4

4 回答 4

6

纪元定义为 1970-1-1 UTC 的 00:00:00 。由于CET 是 UTC+1,因此它等于您的时间凌晨 1 点。

如果您查看Date(long)构造函数,您会发现它期望该值是自纪元UTC以来的毫秒数:

分配一个 Date 对象并将其初始化以表示自称为“纪元”的标准基准时间(即 1970 年 1 月 1 日 00:00:00 GMT)以来的指定毫秒数。

关于您希望强制使用 GMT 而不是本地时区:简而言之,Date 实例始终使用 GMT。如果您只想格式化输出 String 以便它使用 GMT 有一个DateFormat类,特别是它的setTimeZone()方法。

于 2010-03-12T17:31:30.407 回答
3

tl:博士

Instant.EPOCH
       .toString()

1970-01-01T00:00:00Z

Date::toString谎言

您已经了解了避免使用 java.util.Date/Calendar 类的众多原因之一:Date实例没有时区信息,但它的toString方法在呈现字符串以供显示时使用您的默认时区。令人困惑,因为它暗示 Date 有一个时区,而实际上它没有。

避免Date/Calendar

您应该使用Joda-Time或 JSR 310 中的新 Java 8 类 java.time.* 而不是日期/日历。

java.time

使用Instant类相当于Date, UTC 时间轴上的时刻。

Instant.now()

对于纪元参考日期,使用常量。

Instant.EPOCH.toString()

1970-01-01T00:00:00Z

如果“忽略所有时间”是指您真的想要一个没有时间的仅日期值,请使用LocalDate该类。

LocalDate.ofEpochDay( 0L )

1970-01-01

Joda-Time 示例

更新:Joda-Time 项目现在处于维护模式,团队建议迁移到 java.time 类。

在 Joda-Time 中,DateTime 实例确实知道自己的时区。如果需要,您可以使用格式化程序在其他时区创建字符串输出。

这是针对Unix 时间 Epoch的代码,但使用的是 Joda-Time 2.3。

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;

DateTimeZone timeZone_Paris = DateTimeZone.forID( "Europe/Paris" );

DateTime epochParis = new DateTime( 0L, timeZone_Paris );
DateTime epochUtc = new DateTime( 0L, DateTimeZone.UTC );

转储到控制台...</p>

System.out.println( "epochParis: " + epochParis );
System.out.println( "epochUtc: " + epochUtc );

运行时……</p>

epochParis: 1970-01-01T01:00:00.000+01:00
epochUtc: 1970-01-01T00:00:00.000Z

转换为 UTC/GMT

那么,我怎样才能强制使用 GMT,而忽略所有当地时间?

要使用UTC /GMT(无时区偏移),请执行以下任一操作:

  • 将 DateTime 转换为具有不同时区的另一个实例
    (Joda-Time 使事物不可变以保证线程安全,因此我们实际上并不转换,而是基于旧实例创建新实例。)
  • 使用格式化程序创建为指定时区显示的字符串。
// To use UTC/GMT instead of local time zone, create new instance of DateTime.
DateTime nowInParis = new DateTime( timeZone_Paris );
DateTime nowInUtcGmt = nowInParis.toDateTime( DateTimeZone.UTC );

转储到控制台...</p>

System.out.println( "nowInParis: " + nowInParis );
System.out.println( "nowInUtcGmt: " + nowInUtcGmt );

运行时……</p>

nowInParis: 2013-12-22T08:40:01.443+01:00
nowInUtcGmt: 2013-12-22T07:40:01.443Z
于 2013-12-22T07:52:14.027 回答
3

这可能与您的区域设置有关。假设您是法国人而不是法裔加拿大人,您的时间戳似乎被视为没有时区的时间戳,并且Date构造函数尝试对此进行更正,在日期上增加一个小时。

如果这是否是无证行为,我不能告诉你。

编辑:读取错误:CET!= UTC:/

所以是的,语言环境时区。

重新编辑:为了完全和绝对的清晰。

输出:1970 年 1 月 1 日星期四 01:00:00 CET

您的预期输出:Thu Jan 01 00:00:00 CET 1970

实际预期输出:1970 年 1 月 1 日星期四 00:00:00 GMT (≡ 1970 年 1 月 1 日星期四 01:00:00 CET)

于 2010-03-12T17:30:38.200 回答
1

CET 比 GMT 早一小时,这是用于定义 Epoch 的时区。

于 2010-03-12T17:30:20.523 回答