如果做一个新的日期(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的时区。