SimpleDateFormat返回错误的天数

时间:2016-12-09 12:34:59

标签: java android date simpledateformat duration

我需要从长值中获取天数,小时数,分钟数,秒数。但是我从下面的代码中得到了错误的天数。

public static String formatTimeUTC(long value, String pattern) {
    final SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US);
    format.setTimeZone(TimeZone.getTimeZone("UTC"));
    Date date = new Date(value);
    String formatString = format.format(date);
    return formatString;
}

当我将106988550"dd:HH:mm:ss"传递给此方法时,我正在" 02:05:43:08"

预期的实际答案是:" 01:05:43:08"

我不知道哪里出错了,我怎么能得到实际答案。

4 个答案:

答案 0 :(得分:1)

预计表达式System.out.println(formatTimeUTC(106988550L, "dd:HH:mm:ss"));会额外打印一天(02:05:43:08)。为什么呢?

<强>摘要:

班级SimpleDateFormat并非设计用于打印持续时间,而是指向时间点。对于旧类型java.util.Date也可以这样说,它不是持续时间而是瞬间。

<强>混凝土:

模式部分“dd”指示格式化程序打印名义日期,而不是自UNIX时代以来的天数。在这种情况下,它是1970年日历日期的一部分-01-的 02 T05:43:08.550。因此,您需要在UNIX纪元上从原始日期1中减去一天。

备选方案:

正如您所看到的那样,以这种方式打印持续时间变得非常尴尬(通过滥用不是为此目的而设计的类SimpleDateFormat)。我建议使用更好的API。例如Joda-Time或我的库Time4J

Joda-Time(基于builder-approach):

PeriodFormatter pf =
    new PeriodFormatterBuilder().minimumPrintedDigits(2).appendDays().appendLiteral(":")
    .appendHours().appendLiteral(":").appendMinutes().appendLiteral(":").appendSeconds()
    .toFormatter();
long v = 106988550L;
System.out.println(
    pf.print(new Period(v, PeriodType.dayTime()).normalizedStandard())); // 01:05:43:08

对于Android:使用改编Joda-Time-Android

Time4J(基于pattern approach):

long v = 106988550L;
Duration<IsoUnit> duration = Duration.of(v, ClockUnit.MILLIS);
System.out.println(
    Duration.formatter("DD:hh:mm:ss").format(duration.with(Duration.STD_PERIOD))
); // 01:05:43:08

对于Android:使用姐妹项目Time4A。

您也可以调查 Android平台中内置的课程DateUtils,但我不确定它是否适合您的目的,因为它的API很笨拙(您需要设置组合无论如何都是位标志。)

答案 1 :(得分:1)

Answer by Hochschild是正确的。您正在处理一段时间作为日期时间,喜欢将苹果与橙子混合。

java.time

java.time类取代了麻烦的旧日期时间类。轻松完成这项工作。

你实际上没有解释,但我猜你的号码是经过的毫秒数。

long input = 106_988_550L ;

我们将其表示为Duration

Duration d = Duration.ofMillis( input );

我们可以将该值表示为使用标准ISO 8601格式子集格式化的字符串,持续时间为PTnHnMnS

String output = d.toString();
  

PT29H43M8.55S

请参阅live code in IdeOne.com

在Java 9及更高版本中,您可以通过调用to…ParttoDaysParttoHoursPart方法来访问该值的每个组件。

关于java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和&amp; SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

从哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如IntervalYearWeekYearQuartermore

答案 2 :(得分:0)

change your TimeZone this

format.setTimeZone(TimeZone.getTimeZone("UTC"));

to this

format.setTimeZone(TimeZone.getTimeZone("GMT+0:00"));

and check the output.

答案 3 :(得分:0)

您可以使用 java.time.Duration,它以 ISO-8601 standards 为模型,并作为 JSR-310 implementation 的一部分与 Java-8 一起引入。 Java-9 引入了一些更方便的方法。

演示:

import java.time.Duration;

public class Main {
    public static void main(String[] args) {
        long value = 106988550;

        Duration duration = Duration.ofMillis(value);
        // Default format
        System.out.println(duration);

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

        // ####################################Java-9####################################
        formattedElapsedTime = String.format("%02d:%02d:%02d:%02d", duration.toDaysPart(), duration.toHoursPart(),
                duration.toMinutesPart(), duration.toSecondsPart());
        System.out.println(formattedElapsedTime);
        // ##############################################################################
    }
}

输出:

PT29H43M8.55S
01:05:43:08
01:05:43:08

Trail: Date Time 了解现代日期时间 API。