【问题标题】:Java SimpleDateFormat: an hour wrongJava SimpleDateFormat:一个小时错误
【发布时间】:2012-12-16 23:26:23
【问题描述】:

我不需要一个完整的故事来澄清我的问题,所以我将只显示代码(这只是一个示例)。为什么我的结果有差异?

代码

long millis = 2305293L;
System.out.println(
    millis + "ms = " + 
    (millis / 1000) + "s = " + 
    (millis / 1000 / 60) + "m");
System.out.println(
    new SimpleDateFormat("HH:mm:ss").
    format(
        new Date(millis)
        )
    );

输出

2305293ms = 2305s = 38m
01:38:25

【问题讨论】:

    标签: java date date-format


    【解决方案1】:

    其他答案都是正确的,并且是 2013 年问这个问题时的好答案。今天我们不应该再使用 DateSimpleDateFormat,所以我想向您展示几个现代代码 sn-ps 代替.格式化(在这种情况下)2 305 293 毫秒的正确方法取决于它们所代表的内容。我针对三种不同的情况提出了三种选择。

    格式化自纪元以来的毫秒数

    您需要决定要在哪个时区解释您的时间点。例如:

        long millis = 2_305_293L;
        DateTimeFormatter formatter = DateTimeFormatter
                .ofLocalizedDateTime(FormatStyle.LONG)
                .withLocale(Locale.ENGLISH);
        ZonedDateTime dateTime = Instant.ofEpochMilli(millis)
                .atZone(ZoneId.of("America/Coral_Harbour"));
        String formattedTime = dateTime.format(formatter);
        System.out.println(formattedTime);
    

    美国东部标准时间 1969 年 12 月 31 日晚上 7:38:25

    由于纪元珊瑚港的 UTC 偏移量为 -05:00,因此我们得到的时间接近 1969 年底。如果您想要 UTC 时间(因为纪元是用 UTC 定义的;换句话说,如果您想要00:38:25),有点不一样:

        DateTimeFormatter formatter = DateTimeFormatter
                .ofLocalizedDateTime(FormatStyle.MEDIUM)
                .withLocale(Locale.ENGLISH);
        OffsetDateTime dateTime = Instant.ofEpochMilli(millis)
                .atOffset(ZoneOffset.UTC);
    

    1970 年 1 月 1 日上午 12:38:25

    除了时区之外,您还可以通过区域设置来改变语言,通过格式样式(完整、长、中、短)来改变格式的长度。如果您想要没有日期的时间,请使用ofLocalizedTime 而不是ofLocalizedDateTime

    格式化一天中的毫秒

    假设您的毫秒是从 0:00(“午夜”)开始在任何时区:

        LocalTime time = LocalTime.MIN.with(ChronoField.MILLI_OF_DAY, millis);
        System.out.println(time);
    

    00:38:25.293

    如果此格式令人满意,则不需要任何显式格式化程序。如果没有,您可以使用DateTimeFormatter

    格式化持续时间,时间量

    时间量与时间完全不同,它作为Duration 对象处理。没有对格式化的直接支持,但从 Java 9 开始就不那么难了(当你知道怎么做的时候):

        Duration amountOfTime = Duration.ofMillis(millis);
        String formattedTime = String.format("%02d:%02d:%02d",amountOfTime.toHours(),
                amountOfTime.toMinutesPart(), amountOfTime.toSecondsPart());
        System.out.println(formattedTime);
    

    00:38:25

    链接

    Oracle tutorial: Date Time 解释如何使用 java.time。

    【讨论】:

      【解决方案2】:

      如果您在伦敦或巴黎,则时区为 1970 年 1 月 1 日的 GMT+1。

      由于@ARC 在 cmets 中解释的原因,英国在 1968 年 2 月 18 日至 1971 年 10 月 31 日期间使用 GMT+1 或 UTC+1

      我可以在不受任何时区干扰的情况下转换 long 吗?

      将时区设置为 GMT。

      long millis = 2305293L;
      SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
      sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
      System.out.println(sdf.format(new Date(millis)));
      

      打印

      00:38:25.293
      

      【讨论】:

      • 我知道的东西太随意了,连琐碎的追求都没有用;)
      • @Aquillo 添加到我的答案中。
      • 如果有人想知道原因,他可以阅读 BST(英国夏令时)。那个时期是一次失败的实验,无法让它恢复生机。
      • 显然这是一个名为英国标准时间的实验。维基百科:对实验前两年的事故数据的分析表明,虽然早上的伤亡人数有所增加,但晚上的伤亡人数却大幅下降,总共减少了约 2,700 人死亡并在实验的前两个冬天受重伤,当时每天约有 1,000 人在道路上丧生或受重伤。
      • @ARC 听起来他们应该保留它。对我来说,上班路上天黑,冬天回家路上天黑,所以GMT+0GMT+1 对我来说没什么区别。
      【解决方案3】:

      试试这个:

      System.out.println(new java.util.Date (0));
      

      您会看到它从 01:00:00 开始,因此相差一小时。

      【讨论】:

      • 是的,我注意到了不同之处。因此,问题是什么导致了它。但彼得已经完美地涵盖了它。
      • 我不认为这是由于 1970-01-01 的伦敦/巴黎时区。 AFAIK Date(0) 在世界任何地方都是这样构建的(使用 getHours()==1),即无论默认系统时区如何。检查stackoverflow.com/a/41615128/1141215
      • 因为时区,@PJ_Finnegan。但是我建议我们不要使用Date。该课程设计不良且早已过时。而是使用Instantjava.time, the modern Java date and time API 中的其他类。
      • @Ole V.V.我不在伦敦/巴黎时区,但我曾经在创建 Date(0) 的时间获得 +1 偏移量
      • @PJ_Finnegan 你在哪个时区,你从new Date(0) 得到什么?当我将 JVM 的默认时区设置为亚洲/东京并尝试new Date(0) 时,我得到Thu Jan 01 09:00:00 JST 1970。在亚洲/加尔各答,我得到Thu Jan 01 05:30:00 IST 1970
      猜你喜欢
      • 1970-01-01
      • 2018-06-23
      • 2011-12-18
      • 1970-01-01
      • 1970-01-01
      • 2018-09-20
      • 1970-01-01
      • 1970-01-01
      • 2014-04-09
      相关资源
      最近更新 更多