开发者社区> 问答> 正文

在Java中,某些日期无法正确转换为特定时区的午夜时间戳记

此Java代码(以日期作为字符串给出)应该在CET区域的午夜打印同一日期的纪元时间戳(假设我不在同一区域中)。

public static void main(String[] args) throws ParseException {

    String dateStr = "1995-06-06";

    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
    formatter.setTimeZone(TimeZone.getTimeZone("CET"));
    Date date = formatter.parse(dateStr);
    Calendar c = new GregorianCalendar();
    c.setTimeZone(TimeZone.getTimeZone("CET"));
    c.setTime(date);

    c.set(Calendar.HOUR_OF_DAY, 0);
    c.set(Calendar.MINUTE, 0);
    c.set(Calendar.SECOND, 0);
    c.set(Calendar.MILLISECOND, 0);

    System.out.println("Epoch timestamp = " + c.getTime().getTime());
}

如果运行上面的程序,我应该得到打印:

 Epoch timestamp = 802389600000

我可以在这里验证它是正确的:

https://www.epochconverter.com/timezones?q=802389600&tz=Europe%2FMalta

现在,这适用于大多数日期。但是,有些奇怪的日期(例如“ 1975-09-19”)无法使用。实际上,它生成180313200000作为时间戳,该时间戳为凌晨1点而不是午夜:

https://www.epochconverter.com/timezones?q=180313200&tz=Europe%2FMalta

问题来源:Stack Overflow

展开
收起
montos 2020-03-22 14:28:55 761 0
1 条回答
写回答
取消 提交回答
  • 时区差异 您的Java代码使用CET,它实际上不是时区(例如,因为一年中的大部分时间都使用CEST而不是时区)。Java将CET转换为欧洲/巴黎。法国和巴黎在1975年没有使用夏令时(DST)。1976年3月重新引入。

    您指向纪元转换器的链接指定了马耳他时区(欧洲/马耳他)。马耳他确实在1975年使用夏季时间:从4月20日至当年9月21日为CEST。

    这说明了结果的差异。

    用Java代码 如果您想要马耳他时间:

    String dateStr = "1975-09-19";
    
        long epochTimestamp = 
                LocalDate 
                .parse(dateStr)                            
                .atStartOfDay(ZoneId.of("Europe/Malta"))
                .toInstant()
                .toEpochMilli();
    
        System.out.println("Epoch timestamp = " + epochTimestamp);
    

    打印:

    纪元时间戳= 180309600000

    您链接到的时代转换器很高兴同意:

    转换结果(180309600) 180309600 在欧洲/马耳他(CEST)时区转换为1975年9月19日,星期五,上午00:00:00(上午),偏移量(与格林威治标准时间/格林尼治标准时间之间的差异)为+02:00或7200秒。此日期为白天节约时间。

    在Java中,请使用java.time(现代的Java日期和时间API)进行日期和时间工作。它是如此的好得多相比于旧的日期和时间类,如与工作SimpleDateFormat,TimeZone,Date和Calendar。另外,将小时等设置为0也不是获取当天第一时间的正确方法。在某些情况下,夏令时从一天的开始开始,因此一天的第一时刻是01:00:00。Java知道这一点,因此该atStartOfDay方法将为您提供当天相关的正确信息。

    而且,无论使用过时的类还是现代的类,都始终以区域/城市格式指定时区,例如,欧洲/巴黎或欧洲/马耳他。三个,四个和五个字母的时区缩写通常是模棱两可的,并且通常不是真实的时区,因此请不要依赖。

    链接 - 时区在巴黎,法兰西岛,法国 - 马耳他瓦莱塔所在时区 - Oracle教程:Date Time说明如何使用java.time。

    回答来源:Stack Overflow

    2020-03-22 14:30:55
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
JAVA开发手册1.5.0 立即下载