SimpleDateFormat有时会错误地格式化

时间:2018-01-15 09:26:22

标签: java simpledateformat duration milliseconds gmt

我想将我的时间戳转换为XXhours:YYminutes字符串。我的方法有时可以正常工作,除非它获得更大的价值。例如,

193500000 - > 05小时:45分钟(错误,正确是53小时:45分钟)
60300000 - > 16小时:45分钟(正确)
63900000 - > 17小时:45分钟(正确)
108000000-> 06:00:00分(错误,正确是30小时:00分钟)
117000000 - > 08小时:30分钟(错误,正确是32小时:30分钟)

    SimpleDateFormat dateFormat = new SimpleDateFormat("HH'hours' mm'minutes'");
    dateFormat.setTimeZone( TimeZone.getTimeZone( "GMT"));
    String string  = dateFormat.format(totalTime);

6 个答案:

答案 0 :(得分:2)

不幸的是SimpleDateFormat是不可能的。 “HH”表示一天中的小时。如果您的日期超过24小时,则会产生模24。

我建议您使用新的时间API编写自定义代码。

以下是示例:

    Duration duration = Duration.ofMillis(193500000);

    long minutes = duration.toMinutes() % 60;
    long hours = duration.toHours();

    System.out.println("" + hours + "hours:"+minutes+"minutes");

答案 1 :(得分:2)

请仔细阅读:https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

HH是的小时,不超过24小时: - )

你想要的可能是这样的:

    int msecPerHour = 3600*1000;
    int hours = totalTime/msecPerHour;
    int msecPerMinute = 60*1000;
    int minutes = totalTime/msecPerMinute - hours*60;
    String str = "" + hours + " hours " + minutes + " minutes";

答案 2 :(得分:2)

The answer by talex您应该使用Duration这是正确的。在Java 9格式化中,Duration变得更容易,更易于编写和阅读:

public static String formatDuration(long totalTimeMillis) {
    Duration totalDuration = Duration.ofMillis(totalTimeMillis);
    return String.format(Locale.ENGLISH,
            "%02d hours %02d minutes",
            totalDuration.toHours(),
            totalDuration.toMinutesPart());
}

我们不再需要模运算(或类似)来查找分钟。为了演示我使用问题中的时间值调用上述方法:

    System.out.println(formatDuration(60300000));
    System.out.println(formatDuration(63900000));
    System.out.println(formatDuration(108000000));
    System.out.println(formatDuration(117000000));
    System.out.println(formatDuration(193500000));

它会打印您要求的结果:

16 hours 45 minutes
17 hours 45 minutes
30 hours 00 minutes
32 hours 30 minutes
53 hours 45 minutes

我在数字和单位之间放了一个空格,我发现它更具可读性,如果你不想要它就可以删除它。

格式字符串中的%02d说明符可确保您在问题中获得前导零的两位数字:formatDuration(14700000),例如,产生04 hours 05 minutes

SimpleDateFormat用于格式化日期和/或时间,而不是格式化持续时间或已用时间。我说“是”因为那个课程现在已经过时了,而且因为它也是出了名的麻烦我建议你再也不用了。要格式化日期或时段,请使用DateTimeFormatter中的java.time

答案 3 :(得分:1)

193500000 - > 05小时:45分钟(错误,正确是53小时:45分钟)
这是因为53小时= 2天5小时

60300000 - > 16小时:45分钟(正确)
63900000 - > 17小时:45分钟(正确)

108000000-> 06:00:00分(错误,正确是30小时:00分钟)
这是因为30小时= 1天6小时

117000000 - > 08小时:30分钟(错误,正确是32小时:30分钟)
这是因为32小时= 1天8小时

如果您只想从ms计算小时数:

193500000/(1000*60*60)   = number of hours  
(193500000/(1000*60))%60 = number of remaining minutes 

答案 4 :(得分:1)

SimpleDateFormat 是此要求的错误类

您的要求是计算持续时间而不是日期时间。 SimpleDateFormatjava.time.format.DateTimeFormatter(现代日期时间 API 的一部分)应该用于表示日期/时间/日期时间,即表示时间点而不是时间段/持续时间的东西.记住这一点的经验法则是:

  1. 在英语语法时态中使用 SimpleDateFormatjava.time.format.DateTimeFormatter 表示您用 since 指代的事物。
  2. Period and Duration 用于英语语法时态中用 for 指代的事物。

检查The Difference between Since and For – English grammar

为了获得毫秒级的持续时间,您可以使用 java.time.Duration,它以 ISO-8601 standards 为模型,并在 Java-8 中作为 {{3} }. Java-9 引入了一些更方便的方法。

演示:

import java.time.Duration;

public class Main {
    public static void main(String[] args) {
        Duration duration = Duration.ofMillis(193500000);
        // Default format
        System.out.println(duration);

        // Custom format
        // ####################################Java-8####################################
        String formattedElapsedTime = String.format("%02d hours %02d minutes", duration.toHours(),
                duration.toMinutes() % 60);
        System.out.println(formattedElapsedTime);
        // ##############################################################################

        // ####################################Java-9####################################
        formattedElapsedTime = String.format("%02d hours %02d minutes", duration.toHours(), duration.toMinutesPart());
        System.out.println(formattedElapsedTime);
        // ##############################################################################
    }
}

输出:

PT53H45M
53 hours 45 minutes
53 hours 45 minutes

JSR-310 implementation 了解现代日期时间 API。

答案 5 :(得分:0)

看起来您正在尝试转换持续时间,而不是日期时间。 SimpleDateFormat用于将日期时间格式化为不同语言环境的不同格式。

您可能正在寻找类似的内容,以便在持续时间之间进行转换:

String.format("%d hours, %d minutes", 
    TimeUnit.MILLISECONDS.toHours(millis),
    TimeUnit.MILLISECONDS.toMinutes(millis) - 
    TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(millis))
);