Сравнение диапазона дат в массиве

1

Я пытаюсь сравнить даты в массиве для перекрытия, но с проблемой. Пользователь может добавить столько дат, сколько захочет, и мне нужно проверить их, чтобы они не перекрывались.

Даты Массив (даты начала и окончания в сочетании с (-) между ними:

dates (4) ["02/07/2018-02/07/2018", "02/05/2018-02/07/2018", "02/06/2018-02/06/2018", "02/08/2018-02/08/2018"]

Мой код:

        function CheckOverlappingDates(dates) {
        var startDate = []; 
        var endDate = [];
        var isOverlap;
        for (var i = 0; i < dates.length; i++) {
            var split = dates[i].split('-');  // just split once
            startDate.push(new Date(split[0]).toLocaleDateString());
            endDate.push(new Date(split[1]).toLocaleDateString());

            for (var x = 0; x < startDate.length; x++) {
                if (startDate[x] >= startDate[x + 1] && startDate[x + 1] <= endDate[x + 1]) {
                    isOverlap = true;
                } else {
                    isOverlap = false;
                }
            }

        }

    }

Я разделил их на начало и закончил, как показано ниже.

Изображение 174551

но моя функция не сравнивает несколько диапазонов дат.

  • 0
    Конвертируйте их в эпоху Миллиса. Тогда сравните.
  • 0
    Это: new Date(split[0]).toLocaleDateString() последующим сравнением результирующих строк с использованием startDate[x] >= startDate[x + 1] - не очень хорошая идея. Разбор исходной строки зависит от реализации, так как является результатом toLocaleString , нет никаких оснований полагать, что результаты будут правильными или надежными, и многие считают, что они этого не сделают.
Теги:
arrays
date
date-comparison

2 ответа

1
Лучший ответ

При сравнении строк даты вы можете преобразовать их в объекты Date или сохранить их как строки и использовать localeCompare. Не используйте встроенный анализатор даты, поскольку он ненадежен. Функция 2 строки может форматировать как строки или преобразование на дату, строки могут быть более эффективными, но сравнение в качестве дат меньше кода.

Чтобы увидеть, имеет ли массив диапазонов перекрытие, каждый диапазон нужно сравнивать с теми, которые находятся после него в массиве. Там нет необходимости проверять с ними раньше, чем это уже было сделано.

Неясно, что делать с перекрывающимися диапазонами, поэтому эта функция просто возвращает массив строк с "диапазоном A перекрытий диапазона B". Он также предполагает, что диапазоны включены, поэтому 02/05/2018-02/07/2018 перекрывается 02/07/2018-02/08/2018.

например

var dates = ["02/07/2018-02/07/2018", "02/05/2018-02/07/2018", "02/06/2018-02/06/2018", "02/08/2018-02/08/2018"];

// Assume array of ranges in format mm/dd/yyyy-mm/dd/yyyy
// Return array of overlapping ranges
function inRange(dates) {

  // Parse date string to Date
  function fn(s) {
    var b = s.split(/\D/);
    return new Date(b[2], b[0]-1, b[1]);
  }
  
  // Return true if range a overlaps range b
  // where range is string in format mm/dd/yyyy-mm/dd/yyyy
  // Overlaps if start or end of b are inside a, or
  // a is wholly inside b
  function overlaps(a, b) {
    a = a.split('-').map(fn);
    b = b.split('-').map(fn);
    return (b[0] >= a[0] && b[0] <= a[1]) || // b start in a
           (b[1] >= a[0] && b[1] <= a[1]) || // b end in a
           (b[0] <= a[0] && b[1] >= a[1]);   // b encloses a
  }
  
  // Array for overlapping ranges
  var overlappers = [];
  var max = dates.length - 1;

  dates.forEach(function(date, i) {
  
    // Don't test last as already tested
    if (i < max) {
    
      // Only test from this element to end of array
      for (var j = i+1; j <= max; j++) {
      
        // If overlaps, add to overlappers array
        if (overlaps(date, dates[j])) {
          overlappers.push(date + ' overlaps ' + dates[j]);
        }
      }
    }
  });
  return overlappers;
}

console.log(inRange(dates));

Простой парсер ожидает, что даты будут действительны. Если они должны быть проверены, в синтаксическом анализаторе требуется дополнительная строка кода, а в основной функции должны быть указаны недействительные даты.

1

Вы можете использовать for цикла, чтобы проверить.

var dates = ["02/07/2018-02/07/2018", "02/05/2018-02/07/2018", "02/06/2018-02/06/2018", "02/08/2018-02/08/2018"];
var overlaps = checkOverlaps(dates);

console.log("overlaps", overlaps);

var dates1 = ["02/07/2018-02/07/2018", "02/08/2018-02/10/2018", "02/19/2018-02/20/2018", "02/21/2018-02/21/2018"];
var nonoverlaps = checkOverlaps(dates1);

console.log("nonoverlaps", nonoverlaps);

var dates2 = ["02/07/2018-02/07/2018", "02/07/2018-02/10/2018"]; /* 2nd range starts on the end of the first range */
var overlaps2 = checkOverlaps(dates2);

console.log("overlaps", overlaps2);

function checkOverlaps(dates) {
  var o = false;

  for (var key1 in dates) {
    var cDateArr = dates[key1].split("-");
    var d1 = new Date(cDateArr[0]);
    var d2 = new Date(cDateArr[1]);

    for (var key2 in dates) {

      //make sure not comparing to own self
      if (key1 != key2) {
        var cDateArrB = dates[key2].split("-");
        var dB1 = new Date(cDateArrB[0]);
        var dB2 = new Date(cDateArrB[1]);

        if (
          (d1 < dB1 && d2 > dB1) ||
          (d1 < dB2 && d2 > dB2) ||
          cDateArr[0] == cDateArrB[0] ||
          cDateArr[0] == cDateArrB[1] ||
          cDateArr[1] == cDateArrB[0] ||
          cDateArr[1] == cDateArrB[1]
        ) {
          o = true;
        }
      }
    }
  }

  return o;
}
  • 1
    Большое спасибо, Эдди. ты спас мой день
  • 0
    Вы не должны использовать for..in для перебора массивов, так как могут быть перечисляемые свойства, которые вы не ожидаете, и свойства могут не посещаться в том порядке, в котором вы ожидаете. Наконец, вы не должны использовать встроенный анализатор для строк даты, они общеизвестно ненадежны.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню