【问题标题】:Sum of time with result more than 24 hours结果超过 24 小时的时间总和
【发布时间】:2019-07-01 21:50:23
【问题描述】:

假设如下sn-p:

LocalTime test = LocalTime.of(21, 14);
test.plusHours(5);

结果通常是02:14,但我想求和超过 24 小时限制,所以结果是 26:14

在这种情况下,我有一个字段,用户可以输入在一项任务上花费了多少时间。但是,我必须按小时(例如 48 小时)而不是天(例如 2 天和 4 小时)工作。

有没有一种方法可以在java.time API 中实现?如果没有,我能做些什么来实现这一目标?我正在使用 Java 8、Spring Boot 和 Hibernate 来映射数据库。

【问题讨论】:

  • 您为什么要这样做?听起来像一个XY问题。 (即“你真正想做什么”?)
  • @selbie 我有一个字段,用户可以在其中输入在一项任务上花费了多少时间。该时间可能超过 24 小时。
  • 显而易见的解决方案是将用户的输入从他键入的内容标准化为有效的 LocalTime 对象。或将所有内容标准化为分钟。 (例如,如果用户键入“26:14”作为时间,您将其规范化为 26*60+14 分钟并存储它。另一个转换函数可以从绝对分钟回到显示时间。
  • 为什么不是 java.time.LocalDateTime?
  • LocalTime 表示时间值。 26:14 不是时间值,而是经过时间值。就像普通手表和秒表之间的区别一样。 Duration 是用于跟踪经过时间值的类。

标签: java date time duration hour


【解决方案1】:

java.time.Duration

您为值使用了错误的数据类型。你需要一个DurationDurationPeriod 的时间级对应物:

基于时间的时间量,例如“34.5 秒”。

Duration durationTaken = Duration.of(5, ChronoUnit.HOURS);

如果您想将其与日期概念相关联,例如计算结束时间,您可以 plusdurations 到日期/时间类型:

LocalTime endTime = test.plus(durationTaken); //02:14

您也可以使用LocalDateTime 做到这一点:

LocalDateTime startTime = LocalDateTime.of(LocalDate.now(), test); //2019-02-07T21:14

//add the duration:
LocalDateTime endDate = startTime.plus(durationTaken); //2019-02-08T02:14

【讨论】:

  • 我之前搜索过 Duration,但我不知道如何使它与 Hibernate 一起工作。以后如何求和(我必须在代码中将第四个转换回整数?)
  • 您能否在问题中澄清一下?不确定你是如何使用它的(就像实体的数据类型一样?)
  • 如果我使用 Spring Boot(创建 Web 服务)和 Hibernate 来映射数据库。当我阅读 Duration 文档时,乍一看我并没有“明白”它是如何工作的,但我想我只需要弄清楚。
  • @athosbr99 不要将持续时间存储为一天中的时间,例如 SQL 标准的 TIME 类型。这是对数据类型的滥用,并且会使任何阅读您的代码的人感到困惑。相反,将持续时间存储为字符串,使用标准 ISO 8601 格式:PnYnMnDTnHnMnS
  • @athosbr99 Duration 类设计为一对整数:整个持续时间的总秒数加上小数秒的纳秒计数。因此,是的,如果您愿意牺牲小数秒,并且考虑到 Postgres 将 BIGINT 实现为 64 位整数(不幸的是,SQL 标准没有指定长度),将持续时间存储为长整数是有意义的。当我建议使用 ISO 8601 文本格式时,我想到的是 Period for years-month-days,它会像 Duration 那样转换为特定数字。
【解决方案2】:

要指定任务需要多长时间,请使用Duration

Duration initialDuration = Duration.ofHours(21).plusMinutes(34);
Duration afterFurtherWork = initialDuration.plusHours(5);
System.out.printf("Total duration was %2d hours and %02d minutes.%n",
        afterFurtherWork.toHours(), afterFurtherWork.toMinutesPart());

更新:作为 Ole V.V.指出,toMinutesPart 是在 Java 9 中添加的。如果仍在使用 Java 8,请使用 toMinutes()%60

【讨论】:

  • toMinutesPart 方法从 Java 9 开始就存在。
【解决方案3】:

LocalTime 不支持此功能。它有一个静态初始化器,在 24 小时左右有一些非常成熟的规则。

/**
 * Constants for the local time of each hour.
 */
private static final LocalTime[] HOURS = new LocalTime[24];
static {
    for (int i = 0; i < HOURS.length; i++) {
        HOURS[i] = new LocalTime(i, 0, 0, 0);
    }
    MIDNIGHT = HOURS[0];
    NOON = HOURS[12];
    MIN = HOURS[0];
    MAX = new LocalTime(23, 59, 59, 999_999_999);
}

根据您更新的 cmets,我可能会建议将小时转换为您的最低时间值,即使用 TimeUnit.HOURS.toMinutes(value)。

【讨论】:

  • 为清晰起见进行了编辑。我可以将类型更改为其他任何类型,而不是 LocalTime。
猜你喜欢
  • 2018-04-01
  • 1970-01-01
  • 2021-11-15
  • 1970-01-01
  • 1970-01-01
  • 2016-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多