首页 > 解决方案 > 如何在 Java 中表示和操作大于 24:00 的时间值?

问题描述

我目前正在使用大于 24:00 的时间值来表示午夜之后仍与前一天的详细信息相关联的时间的应用程序域中做一些工作。例如,它可能使用星期一的 25:15 来表示星期二的凌晨 1:15,因为从域的角度来看,这个值仍然与星期一的数据相关联。

在24 小时制的 Wikipedia 文章中简要提到了这种类型的时间使用:

超过 24:00 的时间符号(例如 24:01 或 25:00 而不是 00:01 或 01:00)不常用,相关标准也未涵盖。但是,在营业时间超过午夜的 [各个国家/地区] 的某些特殊情况下,它们偶尔会被使用,例如广播电视制作和调度。

Java 提供了LocalTime模型类来表示时间。但是,LocalTime被限制在给定日期的午夜(包括)和第二天的午夜(不包括)之间,即在范围内[0:00-23:59:59.999999999]

Java Time API 的编写很灵活,但核心 API 中排除了更专业的概念。正如Java 8 日期和时间库的主要作者策划的ThreeTen Extra项目中所述:

并非每一段日期/时间逻辑都适用于 JDK。有些概念太专业或太庞大而无法融入其中。

通过核心 Java 库或ThreeTen Extra找到现有类型或其他直接方法来对这种约束较少的时间类型进行建模,我没有运气。然而,我很可能遗漏了一些东西,也许是一些相当明显的东西。

我如何在 Java 中模拟这种约束较少的时间,理想情况下使用java.timeAPI 或其扩展,例如 ThreeTen-Extra 项目?我希望能够使用它以文本方式表示时间值(“25:15”)并理想地使用它执行时间计算(例如将“星期一@25:15”转换为“星期二@1:15 AM”)。

如果没有直接的方法,我可能最终会在 Threeten-Extra 项目中打开一个问题。

标签: javatimejava-time

解决方案


不,不存在

我深信,三十家庭中的任何一个班级或其他地方的常用班级都没有支持你想要的东西。我的搜索最接近DayCycles的是 Time4J 库的类(链接在底部)。它由一天中的时间(a PlainTime)和相对于未指定日期的天数组成,所以你要求什么;但它专门用于返回从 a 中添加或减去时间的结果,PlainTime并且不提供它自己的任何功能。

自己旋转

我认为开发自己的可以与 java.time 互操作的类不会太难。java.time.Duration根据更精确的要求,可能会像 Mark B 所建议的那样建立基础。

如果您对这些有苛刻的要求,解析和格式化可能是最难的部分。可能值得从 Joda-Time 库的源代码中获取灵感,因为它包括格式化和解析持续时间的工具。

另一个灵感来源是java.time.LocalTime.

以下是前几位:

public class SpecializedTime {

    private Duration timeSince0000;
    
    private SpecializedTime(Duration timeSince0000) {
        this.timeSince0000 = timeSince0000;
    }

    static SpecializedTime parse(String text, DateTimeFormatter formatter) {
        ParsePosition position = new ParsePosition(0);
        TemporalAccessor parsed = formatter.parseUnresolved(text, position);
        if (position.getErrorIndex() != -1) {
            throw new DateTimeParseException("Parse error", text, position.getErrorIndex());
        }
        if (position.getIndex() != text.length()) {
            throw new DateTimeParseException("Unparsed text", text, position.getIndex());
        }
        if (! parsed.isSupported(ChronoField.HOUR_OF_DAY)) {
            throw new DateTimeParseException("Cannot resolve", text, 0);
        }
        
        Duration time = Duration.ofHours(parsed.getLong(ChronoField.HOUR_OF_DAY));
        if (parsed.isSupported(ChronoField.MINUTE_OF_HOUR)) {
            int minuteOfHour = parsed.get(ChronoField.MINUTE_OF_HOUR);
            // Should validate, 0..59
            time = time.plusMinutes(minuteOfHour);
        }
        // Same for seconds and nanoseconds
        
        return new SpecializedTime(time);
    }
    
    @Override
    public String toString() {
        return String.format("%02d:%02d", timeSince0000.toHours(), timeSince0000.toMinutesPart());
    }

}

示范:

        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("H:m");
        SpecializedTime st = SpecializedTime.parse("25:15", timeFormatter);
        System.out.println(st);

输出:

25:15

关联

DayCycles表格 Time4J的文档


推荐阅读