如果做一个新的日期(0L),时代不是时代。 为什么?

我的问题非常直截了当地解释了:

如果我这样做:

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

根据文件,我期待:1970年1月1日00:00:00 CET 1970年

我想错了……

编辑:的确,我读得太快了。 我应该在1970年1月1日00:00:00 GMT

那么,我如何强制使用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)); } 

Epoch定义为1970-1-1 UTC的00:00:00。 由于CET是UTC + 1,所以它等于你的时间凌晨1点。

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

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

关于你强迫GMT而不是当地时区的愿望:简而言之,Date实例总是使用GMT。 如果你只想格式化输出String,那么它使用GMT就有一个DateFormat类,特别是它的setTimeZone()方法。

这可能与您的区域设置有关。 假设您是法语而不是法语 – 加拿大语,您的时间戳似乎被视为没有时区的时间戳,并且Date构造函数会尝试更正此值,并在日期中添加一小时。

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

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

所以是的,Locale时区。

Reedit:完全清晰。

输出:Thu Jan 01 01:00:00 CET 1970

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

实际预期产量:1970年1月1日00:00:00 GMT 1970年(≡Thu1月01日01:00:00 CET 1970)

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。*而不是Date / Calendar。

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

转储到控制台……

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

跑的时候……

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

转储到控制台……

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

跑的时候……

 nowInParis: 2013-12-22T08:40:01.443+01:00 nowInUtcGmt: 2013-12-22T07:40:01.443Z 

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