【问题标题】:Check if LocalTime.now lies in set Durations检查 LocalTime.now 是否位于设置的持续时间
【发布时间】:2017-04-08 01:49:18
【问题描述】:

如标题中所述,我想知道我通过import java.time.LocalTime 收到的当前时间是否介于设置的持续时间之间。

最后,如果时间在早上,我希望我的程序说“早上好”,如果时间在下午,则说“下午好”,等等。

这些是我的持续时间:

Duration Morning = Duration.between(LocalTime.of(05,31),
LocalTime.of(11,30));
Duration Noon = Duration.between(LocalTime.of(11,31),    
LocalTime.of(13,30));
Duration Afternoon = Duration.between(LocalTime.of(13,31), 
LocalTime.of(17,30));
Duration Evening = Duration.between(LocalTime.of(17,31), 
LocalTime.of(22,30));
Duration Night = Duration.between(LocalTime.of(22,31),  
LocalTime.of(05,30));

我的问题是:如何检查当前时间是否介于其中一个 Duration 之间,以及如何将其转换为 String 以便我可以使用它来发出不同的消息?

【问题讨论】:

  • 你不能。 Duration 不是时间范围。这只是一个时间量,比如 35 秒。你不能说 8:35 是否在 35 秒内。这是没有意义的。这是 javadoc:docs.oracle.com/javase/8/docs/api/java/time/Duration.html。创建您自己的 TimeRange 类,其中包含两个 LocalTime。添加一个 contains(LocalTime) 方法,检查给定时间是否介于存储在范围内的两个时间之间。
  • 嘿,感谢您的快速回答,我该如何创建 TimeRange?我找不到任何关于它的信息。再次感谢您的宝贵时间。
  • 正如我所说,它只是您创建的一个类,具有两个 LocalTime 类型的字段(例如命名为 start 和 end),以及一个方法 contains(LocalTime)。不应该超过 20 行代码左右。
  • 谢谢,我看看我能不能做到:)

标签: java compare intervals localtime


【解决方案1】:

正如 JB Nizet 的评论正确指出的那样,持续时间不是间隔,即 - 不是固定/锚定在 24 小时制的时间线上。 Java-8 没有区间类。所以你有以下选择:

编写自定义间隔类

class ClockInterval {
    final LocalTime start;
    final LocalTime end;

    private ClockInterval(LocalTime start, LocalTime end) {
        this.start = start;
        this.end = end;
    }

    static ClockInterval between(LocalTime start, LocalTime end) {
        return new ClockInterval(start, end);
    }

    boolean contains(LocalTime time) {
        return !time.isBefore(start) && time.isBefore(end);
    }
}

然后(使用这个极其简约且不完整的课程):

ClockInterval morning = ClockInterval.between(LocalTime.of(5, 30), LocalTime.of(11, 30));
ClockInterval noon = ClockInterval.between(LocalTime.of(11, 30), LocalTime.of(13, 30));
ClockInterval afternoon = ClockInterval.between(LocalTime.of(13, 30), LocalTime.of(17, 30));
ClockInterval evening = ClockInterval.between(LocalTime.of(17, 30), LocalTime.of(22, 30));

LocalTime now = LocalTime.now();

if (morning.contains(now)) {
    System.out.println("Good morning.");
} else if (noon.contains(now)) {
    System.out.println("Good midday.");
} else if (afternoon.contains(now)) {
    System.out.println("Good afternoon.");
} else if (evening.contains(now)) {
    System.out.println("Good evening.");
} else {
    System.out.println("Good night.");
}

最后一个 else-branch 涵盖了午夜前后的任何时间,基于到目前为止定义的所有其他间隔之间没有任何间隙的事实(请参阅下面关于间隔边界的最后一条注释)。

使用我的库 Time4J

a) 第一种方式:class net.time4j.range.ClockInterval

Time4J 已经提供了这样的时钟间隔类。只需使用前面的示例并更改当前时间的导入语句和以下行:

PlainTime now = PlainTime.nowInSystemTime();

b) 第二种方式:使用自定义的时段格式化

PlainTime now = PlainTime.nowInSystemTime();

Map<PlainTime, String> dayPeriods = new HashMap<>();
dayPeriods.put(PlainTime.of(5, 30), "morning");
dayPeriods.put(PlainTime.of(11, 30), "midday");
dayPeriods.put(PlainTime.of(13, 30), "afternoon");
dayPeriods.put(PlainTime.of(17, 30), "evening");
dayPeriods.put(PlainTime.of(22, 30), "night");

String p =
  ChronoFormatter.setUp(PlainTime.axis(), Locale.ENGLISH)
  .addLiteral("Good ")
  .addDayPeriod(dayPeriods)
  .addLiteral('.')
  .build()
  .format(now);
System.out.println(p); // Good midday.

应该提到的是,通过模式符号 B 还可以自动本地化支持日周期。但是,此处使用的日周期方案不可自定义,而是源自 Unicode 数据。

String p =
ChronoFormatter.ofTimePattern("'Good' B.", PatternType.CLDR, Locale.ENGLISH)
  .with(Attributes.OUTPUT_CONTEXT, OutputContext.STANDALONE)
  .format(now);
System.out.println(p); // Good afternoon.

对于英语,此方案用作标准:

日周期规则: T0600=早上 T1200=下午 T1800=晚上 T2100=夜晚

如何处理区间边界?

一般来说,我建议对与任何具有(时钟-)时间单位的持续时间相关的区间边界使用半开方法。这意味着,一个区间的开始总是包含在内,并且完全等于前一个区间的开放结束的时间。这样做可以避免间隔之间的意外间隔,并且您可以确保始终匹配当前时间的任何间隔。

但是您尝试以不同的方式对区间边界进行建模。例如,您选择早上的时间间隔为“05:31/11:30”,下一个时间间隔从“11:31”开始。如果当前时间偶然是“11:30:17”(注意第二部分!),那么这样的时间不会匹配任何间隔。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多