为什么通过SimpleDateFormat解析时Java纪元时间会延迟30分钟

t9aqgxwy  于 5个月前  发布在  Java
关注(0)|答案(1)|浏览(70)

以某种方式解析日期时间字符串并将其转换为纪元后的毫秒,在不同的环境中会有不同的工作方式。这似乎是时区或其他东西的问题。理论上,这个字符串应该表示纪元后的0秒:“1970-01- 01 T00:00:00 Z”
实际上,在开发人员的机器上,这是神秘的30分钟(18000000毫秒)。

/**
     * This really ought to return 0, but locally it returns 30 minutes worth of milliseconds.
     * @return The milliseconds since the common epoch. Really ought to be zero, but isn't always.
     */
    public long determineMysteriousMachineTimeDelta()  {
        String strDateOfEpochStart = "1970-01-01T00:00:00Z";
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        Date dateStartOfEpoch = null;
        try {
            dateStartOfEpoch = format.parse(strDateOfEpochStart);

        } catch (ParseException e) {
            return -1;
        }
        return dateStartOfEpoch.getTime();
    }

字符串
谢谢你,谢谢

dphi5xsq

dphi5xsq1#

tl;dr

Instant.parse( "1970-01-01T00:00:00Z" )

字符串

Z,从不'Z'

永远不要在格式模式中的Z周围加上引号。
这个字母表示offset from UTC的零小时-分钟-秒。发音为“Zulu”。
你的引号表示“期待这段文字,但忽略它”,所以你的格式模式丢弃了关键信息。

避免使用旧的日期时间类

永远不要使用SimpleDateFormatCalendarDate类。这些都是遗留类,存在严重缺陷。它们在几年前就被JSR 310中定义的现代 java.time 类所取代。

java.time

您的输入字符串符合ISO 8601标准。
当解析/生成文本时,默认情况下在 java.time 类中使用该标准。因此无需指定格式模式。
要表示UTC中的某个时刻,请使用Instant类。

Instant instant = Instant.parse( "1970-01-01T00:00:00Z" ) ;

epoch计数

询问从UTC(1970-01- 01 T00:00 Z)中看到的1970年第一个时刻的epoch reference开始的毫秒数。
因此,在您的示例中,我们期望计数为零毫秒。

long millis = instant.toEpochMilli() ;


代码run at Ideone.com
顺便说一句,小心这里的数据丢失-Instant解析为纳秒,比毫秒精细得多。

相关问题