为什么我不能得到在java.time分钟或小时的时间?

问题描述 投票:48回答:6

在新Duration日期API(JSR 310)的java.time package类的Java 8及更高版本中,javadoc中说:

这类车型在秒和纳秒项的数量或时间量。它可以使用其他基于持续时间的单位,例如分钟,hours.In另外被访问,天单元可直接或将被视为完全等于24小时,从而忽视夏令效果。

那么,为什么下面的代码会崩溃吗?

Duration duration = Duration.ofSeconds(3000);
System.out.println(duration.get(ChronoUnit.MINUTES));

这就提出了一个UnsupportedTemporalTypeException

java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Minutes
    at java.time.Duration.get(Duration.java:537)

那么,什么是推荐的方式来提取的持续时间对象分钟和小时?难道我们要计算从自己的秒数?为什么它实现的呀?

java java-8 java-time
6个回答
66
投票

“为什么是实现呀?”

其他答案应对toXxx()方法,使要查询的小时/分钟。我会尽力处理原因。

加入该TemporalAmount接口和get(TemporalUnit)方法的过程中相当晚。我个人并不完全相信,我们不得不的工作在这方面的设计正道足够的证据,但略有手臂,扭到添加TemporalAmount。我相信,在我们这样做稍微混淆了API。

现在回想起来,我相信TemporalAmount包含正确的方法,但我相信,get(TemporalUnit)应该有不同的方法名。其原因是,本质上get(TemporalUnit)是一个框架级方法 - 它不适合日常使用。不幸的是,方法名get并不意味着这一点,导致盲蝽象调用get(ChronoUnit.MINUTES)Duration

所以,想get(TemporalUnit)的方式是想象一个低层次的框架观看量为Map<TemporalUnit, Long>其中Duration是大小两个与MapSECONDS的密钥的NANOS

以相同的,这样,Period从低级别的框架看作尺寸3的Map - DAYSMONTHSYEARS(其幸好具有较少错误的几率)。

总体而言,应用程序代码的最好的建议是忽略方法get(TemporalUnit)。使用getSeconds()getNano()toHours()toMinutes()代替。

最后一个办法让“HH:MM:SS”从Duration是做:

LocalTime.MIDNIGHT.plus(duration).format(DateTimeFormatter.ofPattern("HH:mm:ss"))

不漂亮可言,但它的持续时间不超过一天的工作。

New to…Part methods in Java 9

JDK-8142936问题现在在Java中实现9,添加下面的方法访问Duration的每个部分。

  • toDaysPart
  • toHoursPart
  • toMinutesPart
  • toSecondsPart
  • toMillisPart
  • toNanosPart

29
投票

documentation说:

这将返回各自的两个支持的单位,秒和NANOS的值。所有其他单位抛出异常。

所以,最好的猜测答案 - 这就是他们设计的方式。

你可以用一些其他的方法来得到它hours

long hours = duration.toHours();

minutes

long minutes = duration.toMinutes();

8
投票

我想补充到BIGT的答案(+1)中指出的有用toHourstoMinutes和其他转换方法。该Duration specification说:

这类车型在秒和纳秒项的数量或时间量。 [...]

的持续时间的范围需要许多比长更大的存储。为了实现这一点,类存储长表示秒数和表示纳秒的秒的int,这将始终为0和999,999,999之间。

有各种各样的getter方法,如getSecondsgetNanoget(TemporalUnit)。鉴于持续时间被表示为(秒,毫微秒)对,为什么get(TemporalUnit)被限制为秒和毫微秒很明显。这些getter方法直接从持续时间实例中提取数据和为无损的。

相比之下,有各种各样的对方法,包括toDaystoHourstoMillis toMinutestoNanos该做的持续时间值转换。这些转换是有损的,因为它们涉及到数据的截断,否则可能会引发异常,如果持续时间值不能按照要求的格式来表示。

这显然是一开始的方法,无需转换提取数据和对方法进行某种形式的转换设计的一部分。


7
投票

为了得到一个“标准化”的方式时/分/秒组件,您需要手动计算它们 - 下面的代码基本上是从Duration#toString方法复制:

Duration duration = Duration.ofSeconds(3000);
long hours = duration.toHours();
int minutes = (int) ((duration.getSeconds() % (60 * 60)) / 60);
int seconds = (int) (duration.getSeconds() % 60);
System.out.println(hours + ":" + minutes + ":" + seconds);

1
投票

删除众议院再拿到分钟

long hours = attendanceDuration.toHours(); long minutes = attendanceDuration.minusHours(hours).toMinutes();


-1
投票

通过下面的代码我得到这个持续时间的输出:

1天,2小时,5分钟

代码例如:

private String getDurationAsString(Duration duration)
{
    StringBuilder durationAsStringBuilder = new StringBuilder();
    if (duration.toDays() > 0)
    {
        String postfix = duration.toDays() == 1 ? "" : "s";
        durationAsStringBuilder.append(duration.toDays() + " day");
        durationAsStringBuilder.append(postfix);
    }

    duration = duration.minusDays(duration.toDays());
    long hours = duration.toHours();
    if (hours > 0)
    {
        String prefix = Utils.isEmpty(durationAsStringBuilder.toString()) ? "" : ", ";
        String postfix = hours == 1 ? "" : "s";
        durationAsStringBuilder.append(prefix);
        durationAsStringBuilder.append(hours + " hour");
        durationAsStringBuilder.append(postfix);
    }

    duration = duration.minusHours(duration.toHours());
    long minutes = duration.toMinutes();
    if (minutes > 0)
    {
        String prefix = Utils.isEmpty(durationAsStringBuilder.toString()) ? "" : ", ";
        String postfix = minutes == 1 ? "" : "s";
        durationAsStringBuilder.append(prefix);
        durationAsStringBuilder.append(minutes + " minute");
        durationAsStringBuilder.append(postfix);
    }

    return durationAsStringBuilder.toString();
}

说明:

通过使用时间的界面,你可以很容易地找到你想要的确切字符串显示。你只需要从目前的持续时间减少更大TemporalUnit。

例如:

  1. 计算天
  2. 减少持续天数
  3. 计算小时
  4. 减少持续时间等时间......直到你得到持续时间= 0
© www.soinside.com 2019 - 2024. All rights reserved.