时间在Java完成全天检查

时间:2016-07-29 14:35:42

标签: java time date-format

我有一个包含时间信息的列表,如下所示,

List<String> dayList = new LinkedList<String>();
dayList.add("00:00-23:59");

我需要找出满足一整天的清单。

我尝试的是,

List<String> dayList = new LinkedList<String>();
dayList.add("00:00-12:59");
dayList.add("13:00-20:30");
dayList.add("20:31-23:59");
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
long totalMinutes = 0;

for(String data : dayList){
    Date startDate = sdf.parse(data.split("-")[0]);
    Date endDate   = sdf.parse(data.split("-")[1]);
    totalMinutes += TimeUnit.MILLISECONDS.toMinutes(endDate.getTime()-startDate.getTime());
}

if(totalMinutes==(1439-(dayList.size()-1))){
     System.out.println("Completes Full Day");
} else{
     System.out.println("Not Completes Full Day");
}

注意:列表项可以相互重叠。

如果列表包含

,则此逻辑失败
  • 11:00-09:59&amp; 10:00-10:59(完成全天)
  • 00:00-11:59&amp; 00:00-11:59(未完成全天)

    等。

任何人都可以建议任何其他逻辑吗?

5 个答案:

答案 0 :(得分:2)

不,逻辑不好。尝试添加表单"00:00-00:50"的100个条目。显然,他们并没有满满一整天,但他们满足你的算法。

要实际实现这一点,您需要一种称为间隔树(https://en.wikipedia.org/wiki/Interval_tree)的东西。我使用的一个这样的示例实现存在于Guava中。如果您要使用它,则需要将日期添加为Range s,然后询问RangeSet它是否包含整天(使用encloses()):

https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/collect/RangeSet.html

答案 1 :(得分:2)

我建议采用以下方法。它使用 LocalTime 来简化时间操作,使用 Pattern 来解析输入。

  1. 使用创建 LocalTime 的正则表达式解析输入。使用 将其存储在地图中,并以 结尾。< / LI>
  2. 地图 进行排序。
  3. 使用 LocalTime 操作检查间隔边界。别忘了开始结束一天。
  4. 主要方法:

    public static void main(String[] args) {
        List<String> dayList = new LinkedList<String>();
        dayList.add("00:00-12:59");
        dayList.add("13:00-20:30");
        dayList.add("18:31-23:59");
    
        Pattern pattern = Pattern.compile("([0-9]{2}:[0-9]{2})-([0-9]{2}:[0-9]{2})");
    
        DayCoverage dayCoverage = new DayCoverage();
        for (String day : dayList) {
            Matcher matcher = pattern.matcher(day);
            if (!matcher.matches()) {
                System.err.println("Invalid day entry: " + day);
                return;
            }
            LocalTime start = LocalTime.parse(matcher.group(1));
            LocalTime end = LocalTime.parse(matcher.group(2));
    
            dayCoverage.addIntervall(start, end);
        }
    
        if (dayCoverage.isComplete()) {
            System.out.println("Completes Full Day");
        } else {
            System.out.println("Not Completes Full Day");
        }
    }
    

    Class DayCoverage:

    static class DayCoverage {
    
        private Map<LocalTime, LocalTime> cover = new HashMap<>();
    
        public void addIntervall(LocalTime start, LocalTime end) {
            if(end.isBefore(start)){
                this.cover.put(end, start); 
            } else {
                this.cover.put(start, end);
            }
        }
    
        public boolean isComplete() {
            if(this.cover.isEmpty()){
                System.err.println("Coverage empty.");
                return false;
            }
    
            Set<LocalTime> startTimes = this.cover.keySet();
            List<LocalTime> sortedStartTimes = new ArrayList<>(startTimes);
            Collections.sort(sortedStartTimes);
    
            LocalTime first = sortedStartTimes.get(0);
            if(! LocalTime.MIN.equals(first)){
                System.err.println("Coverage does not start with 00:00.");
                return false;
            }
    
            LocalTime lastEnd= LocalTime.MIN;
            for (LocalTime start : sortedStartTimes) {
                if(lastEnd.plus(1, ChronoUnit.MINUTES).isBefore(start)){
                    System.err.println("Missing coverage between: " + lastEnd + " and " + start);
                    return false;
                }
                lastEnd = this.cover.get(start);
            }
    
            if(LocalTime.MAX.truncatedTo(ChronoUnit.MINUTES).isAfter(lastEnd)){
                System.err.println("Missing coverage between: " + lastEnd + " and 23:59");
                return false;
            }
    
            return true;
        }
    
    }
    

答案 2 :(得分:1)

一天中没有多少分钟(以计算方式计算),所以我只想使用BitSet为当天的每一分钟保留一个标记:

int minutesPerDay = 24 * 60;

BitSet uncoveredMinutes = new BitSet(minutesPerDay);
uncoveredMinutes.set(0, minutesPerDay);

for (String dayItem : dayList) {
    String[] parts = dayItem.split("-");

    String[] hoursAndMinutes = parts[0].split(":");
    int hours = Integer.parseInt(hoursAndMinutes[0]);
    int minutes = Integer.parseInt(hoursAndMinutes[1]);
    int start = hours * 60 + minutes;

    hoursAndMinutes = parts[1].split(":");
    hours = Integer.parseInt(hoursAndMinutes[0]);
    minutes = Integer.parseInt(hoursAndMinutes[1]);
    int end = hours * 60 + minutes;

    uncoveredMinutes.clear(start, end + 1);
}

if (uncoveredMinutes.isEmpty()) {
    System.out.println("Completes full day");
} else{
    System.out.println("Does not complete full day");
}

注意BitSet.clear要求第二个参数是一个独占边界(就像String.substring和List.subList一样);这是传递end + 1的原因。

答案 3 :(得分:0)

问题并非100%明确,但我假设结果的最小时间单位为分钟,即"00:00-23:59"涵盖了整整一天。

这种逻辑并不好:你只是测量持续时间并确保它们总和到正确的总和。这意味着如果您添加"00:00-11:59"两次,它将总计一整天,但仅涵盖早晨。如果存在重叠,如澄清的话,它也会失败,因为由于重叠,它们可以非常有效地总计超过一整天。

您要做的第一件事是转换列表以删除重叠。首先,按开始时间排序时间跨度。然后,对于每个时间跨度,如果任何后续时间跨度在其范围内具有开始时间,则可以将它们组合成单个时间跨度。

这应该会为您提供一个非重叠时间表的列表。删除重叠后,将总持续时间相加并与一整天的1439进行比较将是有效的。

答案 4 :(得分:-1)

VGR版本变化不大:

    List<String> dayList = new LinkedList<>();
    dayList.add("11:00-09:59");
    dayList.add("09:00-10:30");
    dayList.add("10:10-10:59");

    int minutesPerDay = 24 * 60;

    BitSet uncoveredMinutes = new BitSet(minutesPerDay);
    uncoveredMinutes.set(0, minutesPerDay);

    DateTimeFormatter sdf = DateTimeFormatter.ofPattern("HH:mm");

    for (String dayItem : dayList) {
        String[] data = dayItem.split("-");
        LocalDateTime startDate = LocalDateTime.of(LocalDate.now(),LocalTime.parse(data[0], sdf));
        LocalDateTime endDate = LocalDateTime.of(LocalDate.now(),LocalTime.parse(data[1], sdf));

        if (endDate.isBefore(startDate)){
            endDate = endDate.plusMinutes(Duration.ofDays(1).toMinutes());
        }

        LocalDateTime terminateDate = endDate.plusMinutes(1);
        while(startDate.isBefore(terminateDate)) {
            int hours = startDate.getHour();
            int minutes = startDate.getMinute();
            int start = hours * 60 + minutes;
            uncoveredMinutes.clear(start);
            startDate = startDate.plusMinutes(1);
        }
    }

    System.out.println(uncoveredMinutes);
    if (uncoveredMinutes.isEmpty()) {
        System.out.println("Completes full day");
    } else{
        System.out.println("Does not complete full day");
    }