代码之家  ›  专栏  ›  技术社区  ›  Antoine Claval

如果执行新日期(0L),则epoch不是epoch。为什么?

  •  4
  • Antoine Claval  · 技术社区  · 15 年前

    我的问题很难解释:

    如果我这样做:

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

    我得到以下输出:1970年1月1日星期四01:00:00 CET

    据医生说,我本来以为:1970年1月1日星期四00:00:00

    我想出错…

    编辑: 事实上,我看医生的速度太快了。我应该在1970年1月1日星期四00:00:00格林威治标准时间

    那么,我如何才能强制使用格林威治标准时间,而忽略所有当地时间呢?

    编辑,解决方案:

    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 回复  |  直到 8 年前
        1
  •  6
  •   Basil Bourque    11 年前

    这个 Epoch 定义为1970-1-1 UTC的00:00:00。自从 CET 是UTC+1,等于凌晨1点。

    如果你看 Date(long) 构造函数,您将看到它期望值是从epoch开始的毫秒数, UTC :

    分配日期对象和 初始化它以表示 自指定的毫秒数 标准基准时间称为 时代”,即1970年1月1日, 0:00 00 GMT。

    关于您希望强制使用格林威治标准时间而不是您的本地时区:简而言之,日期实例 总是 使用gmt。如果只想格式化输出字符串,使其使用gmt,则 DateFormat 类,特别是 setTimeZone() 方法。

        2
  •  3
  •   Williham Totland    15 年前

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

    如果这是非法行为,我不能告诉你。

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

    是的,地点时区。

    Reedit: 为了完全清晰。

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

    预期产量:1970年1月1日星期四00:00:00 CET

    实际 预期产量:1970年1月1日星期四00:00:00格林尼治标准时间(1970年1月1日星期四01:00:00 CET)

        3
  •  3
  •   Basil Bourque    8 年前

    TL:DR

    Instant.EPOCH
           .toString()
    

    1970年01月01日00:00:00Z

    Date::toString 谎言

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

    避免 日期 / Calendar

    您应该使用 Joda-Time 或者来自JSR 310的新Java 8类Java.Time.*。

    Java.时间

    使用 Instant 相当于 日期 ,时间线上的一个时间点。

    Instant.now()
    

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

    Instant.EPOCH.toString()
    

    1970年01月01日00:00:00Z

    如果“忽略所有时间”,您的意思是您真的想要一个没有时间的日期值,请使用 LocalDate 班级。

    LocalDate.ofEpochDay( 0L )
    

    1970年1月1日

    Joda时间示例

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

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

    这是你的代码,目标是 Unix time Epoch 但使用Joda时间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

    那么,我如何才能强制使用格林威治标准时间,而忽略所有当地时间呢?

    使用 UTC /GMT(无时区偏移),或者:

    • 将日期时间转换为具有不同时区的其他实例
      (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
    
        4
  •  1
  •   Jim Lewis    15 年前

    CET比格林尼治标准时间提前一小时,格林尼治标准时间是用来定义时代的时区。

    推荐文章