2016-07-29 26 views
2

我有一個包含時間信息列表如下,時間完成全天檢查在Java中

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 & 10:00-10:59(完成對全天)
  • 00:00-11:59 & 00:00-11:59(未完成對全天)

    等..失敗

任何人都可以提出任何其他邏輯嗎?

+0

是否爲您的使用情況下工作嗎? – Makoto

+0

爲什麼不計算差異總和而不將值轉換爲日期? – 11thdimension

+0

@Makoto它的工作正常。我正在檢查一個很好的解決方案 –

回答

2

我會建議採用以下方法。它使用LocalTime來簡化時間操作,並使用模式來解析輸入。

  1. 使用正則表達式解析輸入LocalTime s。在地圖使用啓動並將其作爲關鍵,並最終爲
  2. 排序地圖
  3. 使用LocalTime操作檢查區間邊界。不要忘記一天結束的開始。

主要方法:

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"); 
    } 
} 

類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

不,邏輯不好。嘗試添加"00:00-00:50"表單的100個條目。顯然,他們並沒有全天填寫滿足你的算法。

要實際執行此操作,您需要一些稱爲間隔樹(https://en.wikipedia.org/wiki/Interval_tree)的內容。我用過的一個這樣的示例實現存在於Guava中。如果你想使用它,你需要將日期添加爲Range秒,然後問RangeSet是否含有整天(用encloses()):

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

0

的問題是不是100%清楚,但我假設結果的最小時間單位是分鐘,那就是"00:00-23:59"覆蓋全天。

這個邏輯並不好:你只測量持續時間並確保他們總計正確的總數。這意味着如果您添加"00:00-11:59"兩次,它將總計爲一整天,但只涵蓋早上。如果有重疊,澄清,它也將失敗,因爲它們可以相當有效地總和超過一整天由於重疊。

你想要做的第一件事是轉換列表以消除重疊。首先,按開始時間對您的時間段進行排序。然後,對於每個時間段,如果任何後續時間段的開始時間在其範圍內,則可以將它們組合爲單個時間段。

這應該給你一個非重疊時間段列表。消除重疊後,總計總持續時間並與1439比較一整天將是有效的。

-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"); 
    } 
+0

這實際上並不清楚。它不會處理重疊的List項目,而不是原始問題的代碼。 – VGR

+0

VGR,當你沒有閱讀問題中的腳註的情況下(關於重疊)(: –

+0

VGR,對不起,但我不能添加評論你的答案 –

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的原因。

+0

如果列表包含11:00-09:59&10: 00-10:59然後這個答案失敗,這樣就完成了整整一天 –

+0

等待,所以,你想要測試是否包含24小時的任何*連續間隔?是否48小時或更多也被認爲是「全天」? – VGR