Java - 以分钟计算差异

Java - Count Difference in minutes

这是我从 SQL 服务器获得的 JSON:

https://pastebin.com/raw/xhCnXynA

这是我正在运行的 SQL 脚本:

DECLARE @T TABLE(ID INT,FromDate DATETIME, ToDate DATETIME)

INSERT INTO @T(ID,FromDate,ToDate)
SELECT 1,'20090801','20090803' UNION ALL
SELECT 2,'20090802','20090809' UNION ALL
SELECT 3,'20090805','20090806' UNION ALL
SELECT 4,'20090812','20090813' UNION ALL
SELECT 5,'20090811','20090812' UNION ALL
SELECT 6,'20090802','20090802'

SELECT ROW_NUMBER() OVER(ORDER BY s1.FromDate) AS ID,
       s1.FromDate,
       MIN(t1.ToDate) AS ToDate
FROM @T s1
INNER JOIN @T t1 ON s1.FromDate <= t1.ToDate
  AND NOT EXISTS(SELECT * FROM @T t2
                 WHERE t1.ToDate >= t2.FromDate
                   AND t1.ToDate < t2.ToDate)
WHERE NOT EXISTS(SELECT * FROM @T s2
                 WHERE s1.FromDate > s2.FromDate
                   AND s1.FromDate <= s2.ToDate)
GROUP BY s1.FromDate
ORDER BY s1.FromDate

结果:

我的Java代码:

//Date Format
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");   

Integer downTime;

while (rs.next()) {  

    //Parse to Date
    eventStart = formatter.parse(rs.getString("EventStart"));
    eventEnd = formatter.parse(rs.getString("EventEnd"));

    if (eventStart.after(eventEnd)){
         //How should I do this?
    }
    else{
         //How should I do this?
    }

    //I have to count here the difference between the dates in minutes
}  

计算两个日期之间的分钟差

最好使用新 Java Date/Time API 中的 java.time.format.DateTimeFormatterjava.time.LocalDateTime 而不是 SimpleDateFormatDate :

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
LocalDateTime eventStart = LocalDateTime.parse("2019-10-09 01:24:05.0", formatter);
LocalDateTime eventEnd = LocalDateTime.parse("2019-10-09 01:35:14.0", formatter);
Duration duration;
if (eventStart.isBefore(eventEnd)) {
  duration = Duration.between(eventStart, eventEnd);
} else {
  duration = Duration.between(eventEnd, eventStart);
}
long minutes = duration.toMinutes();
System.out.println("" + minutes + " minute(s)");

结果是:11 minute(s).

合并所有重叠的日期范围

要合并所有重叠的日期范围,请考虑以下方法。

创建一个 class 以使用方法 isOverlappingWithmergeWithtoMinutes 表示日期范围并覆盖 equalshashCode

private static class DateRange {

  private final LocalDateTime startDate;
  private final LocalDateTime endDate;

  public DateRange(LocalDateTime startDate, LocalDateTime endDate) {
    this.startDate = startDate;
    this.endDate = endDate;
  }

  public boolean isOverlappingWith(DateRange other) {
    return !startDate.isAfter(other.endDate) && !endDate.isBefore(other.startDate);
  }

  public DateRange mergeWith(DateRange other) {
    return new DateRange(
        startDate.isBefore(other.startDate) ? startDate : other.startDate,
        endDate.isAfter(other.endDate) ? endDate : other.endDate);
  }

  public long toMinutes() {
    return Duration.between(startDate, endDate).toMinutes();
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    DateRange dateRange = (DateRange) o;
    return Objects.equals(startDate, dateRange.startDate) &&
        Objects.equals(endDate, dateRange.endDate);
  }

  @Override
  public int hashCode() {
    return Objects.hash(startDate, endDate);
  }

  @Override
  public String toString() {
    return "DateRange{" +
        "startDate=" + startDate +
        ", endDate=" + endDate +
        '}';
  }
}

遍历所有日期范围并尝试合并它们。要跟踪重复项,需要额外的 HashSet。这个想法是尝试将每个日期范围与列表中的下一个范围合并。如果至少有一个合并,则删除原始日期范围。如果列表不包含生成的合并日期范围,则将其附加到列表中。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");

List<List<String>> rawDateRanges = List.of(
    List.of("2009-08-01 00:00:00.0", "2009-08-03 00:00:00.0"),
    List.of("2009-08-05 00:00:00.0", "2009-08-06 00:00:00.0"),
    List.of("2009-08-02 00:00:00.0", "2009-08-09 00:00:00.0"),
    List.of("2009-08-12 00:00:00.0", "2009-08-13 00:00:00.0"),
    List.of("2009-08-11 00:00:00.0", "2009-08-12 00:00:00.0"),
    List.of("2009-08-02 00:00:00.0", "2009-08-02 00:00:00.0"));

List<DateRange> dateRanges = new ArrayList<>();
for (List<String> rawDateRange : rawDateRanges) { //Replace with while (rs.next()) { ... }
  LocalDateTime fromDate = LocalDateTime.parse(rawDateRange.get(0), formatter);
  LocalDateTime toDate = LocalDateTime.parse(rawDateRange.get(1), formatter);
  dateRanges.add(new DateRange(fromDate, toDate));
}

Set<DateRange> mergedDateRanges = new HashSet<>();
for (int i = 0; i < dateRanges.size(); i++) {
  DateRange dateRange = dateRanges.get(i);
  boolean merged = false;
  for (int j = i + 1; j < dateRanges.size(); j++) {
    DateRange otherDateRange = dateRanges.get(j);
    if (dateRange.isOverlappingWith(otherDateRange)) {
      dateRange = dateRange.mergeWith(otherDateRange);
      merged = true;
    }
  }
  if (merged) {
    dateRanges.remove(i--);
    if (mergedDateRanges.add(dateRange)) {
      dateRanges.add(dateRange);
    }
  }
}

List<Long> minutes = dateRanges.stream()
    .peek(System.out::println)
    .map(DateRange::toMinutes) //Convert to minutes
    .collect(toList());

System.out.println(minutes);

输出:

DateRange{startDate=2009-08-01T00:00, endDate=2009-08-09T00:00}
DateRange{startDate=2009-08-11T00:00, endDate=2009-08-13T00:00}
[11520, 2880]