为什么我在java.time中不能在几分钟或几小时内获得持续时间?

Pie*_*nry 54 java java-8 java-time

在Java 8及更高版本中可用Duration的新JSR 310 date API(java.time包)中的类中,javadoc说:

此类以秒和纳秒为单位模拟时间量或时间量.它可以使用其他基于持续时间的单位进行访问,例如分钟和小时.此外,DAYS单位可以使用,并且被视为完全等于24小时,因此忽略了夏令时效果.

那么,为什么以下代码崩溃?

Duration duration = Duration.ofSeconds(3000);
System.out.println(duration.get(ChronoUnit.MINUTES));
Run Code Online (Sandbox Code Playgroud)

这提出了一个UnsupportedTemporalTypeException:

java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Minutes
    at java.time.Duration.get(Duration.java:537)
Run Code Online (Sandbox Code Playgroud)

那么从持续时间对象中提取分钟和小时的推荐方法是什么?我们是否必须从秒数开始计算?为什么这样实现?

Jod*_*hen 69

"为什么这样实施?"

其他答案涉及toXxx()允许查询小时/分钟的方法.我会尝试处理原因.

TemporalAmount界面和get(TemporalUnit)方法加入的过程中相当晚.我个人并不完全相信我们有足够的证据证明在该地区设计工作的正确方法,但稍微有些扭曲添加TemporalAmount.我相信在这样做时我们稍微混淆了API.

事后看来,我认为它TemporalAmount包含正确的方法,但我相信get(TemporalUnit)应该有一个不同的方法名称.原因是它get(TemporalUnit)本质上是一种框架级方法 - 它不是为日常使用而设计的.不幸的是,方法的名称get并不意味着这一点,导致盲蝽象调用get(ChronoUnit.MINUTES)Duration.

所以,想的办法get(TemporalUnit)是想象一个低层次的框架观看量为Map<TemporalUnit, Long>这里Duration是一个Map大小两次与中键SECONDSNANOS.

在是相同的,这样,Period从低级别的框架看作Map大小三- DAYS,MONTHSYEARS(其幸好具有较少错误的几率).

总的来说,应用程序代码的最佳建议是忽略该方法get(TemporalUnit).使用getSeconds(),getNano(),toHours()toMinutes()来代替.

最后,从a获得"hh:mm:ss"的一种方法Duration是:

LocalTime.MIDNIGHT.plus(duration).format(DateTimeFormatter.ofPattern("HH:mm:ss"))
Run Code Online (Sandbox Code Playgroud)

根本不是很漂亮,但它的工作时间不到一天.

to…PartJava 9中的新方法

JDK-8142936问题现在在Java 9中实现,添加了以下方法来访问a的每个部分Duration.

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

  • `toDays` 和 `toDaysPart` 之间的区别?文档是一样的。是否只是因为对于小时和分钟等其他单位来说,两种方法都有意义,所以他们还添加了两种具有相同效果的天数方法? (3认同)

blg*_*lgt 31

文件说:

这将为两个支持的单元SECONDS和NANOS中的每一个返回一个值.所有其他单位都抛出异常.

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

您可以使用其他一些方法在数小时内获取它:

long hours = duration.toHours();
Run Code Online (Sandbox Code Playgroud)

分钟:

long minutes = duration.toMinutes();
Run Code Online (Sandbox Code Playgroud)

  • 有趣.我实际上没有看到那些toXXX方法.但他们将总秒数转换为所需单位的数量,而不考虑上级单位.例如:持续时间为10000秒,`toMinutes()`方法将返回166.如果需要显示`hh:mm:ss`,则不太有用,但可以作为更完整的计算方法的一部分使用. (3认同)

Stu*_*rks 8

我想补充到BIGT的答案(+1)中指出有用的toHours,toMinutes和其他转换方法.该时间规范说:

此类以秒和纳秒为单位模拟时间量或时间量.[...]

持续时间的范围需要存储大于长的数字.为了实现这一点,该类存储一个代表秒的长整数和一个代表纳秒秒的int,它总是在0到999,999,999之间.

有各种各样的吸气剂的方法,如getSeconds,getNanoget(TemporalUnit).鉴于持续时间表示为(秒,纳米)对,很明显为什么get(TemporalUnit)限制为秒和纳米.这些getter方法直接从持续时间实例中提取数据,并且是无损的.

相比之下,有各种各样的对方法,包括toDays,toHours,toMillis toMinutes,和toNanos该做转换的时间值.这些转换是有损的,因为它们涉及截断数据,或者如果持续时间值无法以请求的格式表示,则它们可能会抛出异常.

很明显,get-methods在没有转换的情况下提取数据,而to-methods执行某种转换,这显然是设计的一部分.


ass*_*ias 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);
Run Code Online (Sandbox Code Playgroud)


小智 5

删除小时然后获取分钟

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