首页 > 解决方案 > 比较多个日历并使用开始和结束查找哪个更接近运行或现在处于活动状态

问题描述

我的求助请求有点奇怪。我会尽量简短。

我有这条线,我在其中解析 Ex 的时间表。18:00-19:00;22:00-23:00 18:00-19:00 为一个对象,22:00-23:00 以“;”隔开。这意味着您可以添加无限的时间表。

现在我使用以下方法解析这一行:

Arrays.asList(schedule.replaceAll("\\s", "").split(";")).forEach(s -> _schedules.add(new ScheduleCalendar(Integer.parseInt(s.split("-")[0].split(":")[0]), Integer.parseInt(s.split("-")[0].split(":")[1]), Integer.parseInt(s.split("-")[1].split(":")[0]), Integer.parseInt(s.split("-")[1].split(":")[1]))));

我用这个类

public static class ScheduleCalendar
    {
        private final Calendar[] _calendar = new Calendar[2];

        public ScheduleCalendar(final int startingHour, final int startingMinute, final int endingHour, final int endingMinute)
        {
            final Calendar starting = Calendar.getInstance();
            starting.set(Calendar.HOUR_OF_DAY, startingHour);
            starting.set(Calendar.MINUTE, startingMinute);
            starting.set(Calendar.SECOND, 0);
            starting.set(Calendar.MILLISECOND, 0);

            _calendar[0] = starting;

            final Calendar ending = Calendar.getInstance();
            ending.set(Calendar.HOUR_OF_DAY, endingHour);
            ending.set(Calendar.MINUTE, endingMinute);
            ending.set(Calendar.SECOND, 0);
            ending.set(Calendar.MILLISECOND, 0);

            _calendar[1] = ending;
        }

        public boolean isBefore(final ScheduleCalendar schedule)
        {
            return false;
        }

        public Calendar[] getCalendars()
        {
            return _calendar;
        }

        public boolean isNow()
        {
            return _calendar[0].getTimeInMillis() > System.currentTimeMillis() && _calendar[1].getTimeInMillis() < System.currentTimeMillis();
        }
    }

最后存储在

private final List<ScheduleCalendar> _schedules = new ArrayList<>();

现在我想做一个方法来检索最近的时间表或如果可能的话。有没有什么花哨和快速的方法使用 java 8-16 来重现这段代码而不必编写这么长的代码?有什么图书馆可能吗?

标签: java

解决方案


如果我们使用的是 java 8+ ,则没有充分的理由使用Calendar

假设时间范围'from' < 'to',即“23:00-01:00”是不允许的,使用LocalTimewith lambda函数可以大大简化代码。

寻找最近或活动的算法:

  1. 丢弃过时的时间范围('from' > active time)
  2. 对于那些“到”<活动时间,选择最大“到”(最接近)的
  3. 如果(2)中没有时间范围,对于那些'from' < active time <'to',选择最大'from'的那个。

当然,您可以交换 2 和 3 的顺序,具体取决于您对最近与活动的优先级。

import java.time.LocalTime;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class Scheduler {
    public static void main(String[] args) {
        String values = "21:00-23:00;20:00-21:00;18:00-19:00;22:30-23:00";
        LocalTime now = LocalTime.parse("22:00");
        List<LocalTimeRange> timeRanges = Arrays.stream(values.split(";")).map(s -> {
            String[] arr = s.split("-");
            return new LocalTimeRange(LocalTime.parse(arr[0]), LocalTime.parse(arr[1]));
        }).collect(Collectors.toList());
        getClosetOrActive(timeRanges, now).ifPresentOrElse(System.out::println, () -> System.out.println("No time range match"));
    }

    private static Optional<LocalTimeRange> getClosetOrActive(List<LocalTimeRange> timeRanges, LocalTime activeTime) {
        // Outdated range is discarded
        List<LocalTimeRange> notOutdatedRanges = timeRanges.stream().
                filter(timeRange -> !timeRange.getFrom().isAfter(activeTime)).collect(Collectors.toList());
        // For range before active time, retrieve the one with 'to' closest to activeTime
        Optional<LocalTimeRange> closet = notOutdatedRanges.stream().filter(localTimeRange -> localTimeRange.getTo().isBefore(activeTime))
                .sorted(Comparator.comparing(LocalTimeRange::getTo).reversed()).findFirst();
        if (closet.isPresent()) {
            return closet;
        }
        // For range cover active time, retrieve the one with latest 'from'
        return notOutdatedRanges.stream().filter(localTimeRange -> !localTimeRange.getTo().isBefore(activeTime))
                .sorted(Comparator.comparing(LocalTimeRange::getFrom).reversed()).findFirst();
    }

    public static class LocalTimeRange {
        private final LocalTime from;
        private final LocalTime to;

        public LocalTime getFrom() {
            return from;
        }

        public LocalTime getTo() {
            return to;
        }

        @Override
        public String toString() {
            return from + "-" + to;
        }

        public LocalTimeRange(LocalTime from, LocalTime to) {
            this.from = from;
            this.to = to;
        }
    }
}

推荐阅读