28

Сравнение двух дат в JavaScript

19

Проблема с сравнением дат в JavaScript

Здравствуйте!

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

Не могли бы вы подсказать, как правильно реализовать такое сравнение? Какие методы или подходы лучше всего использовать для этой задачи? Заранее спасибо за помощь!

4 ответ(ов)

4

Самый простой способ сравнения дат в JavaScript - это сначала преобразовать их в объекты Date, а затем сравнить эти объекты.

Ниже представлен объект с тремя функциями:

  • dates.compare(a, b)

    Возвращает число:

    • -1, если a < b
    • 0, если a = b
    • 1, если a > b
    • NaN, если a или b является некорректной датой
  • dates.inRange(d, start, end)

    Возвращает булевый тип или NaN:

    • true, если d находится между start и end (включительно)
    • false, если d раньше start или позже end
    • NaN, если одна или несколько дат являются некорректными
  • dates.convert

    Используется другими функциями для преобразования входных данных в объект даты. Входные данные могут быть:

    • объектом date: возвращается без изменений
    • массивом: интерпретируется как [год, месяц, день]. ПРИМЕЧАНИЕ: месяц - от 0 до 11
    • числом: интерпретируется как количество миллисекунд с 1 января 1970 года (метка времени)
    • строкой: поддерживаются несколько разных форматов, таких как "YYYY/MM/DD", "MM/DD/YYYY", "Jan 31 2009" и т.д.
    • объектом: интерпретируется как объект с атрибутами год, месяц и дата. ПРИМЕЧАНИЕ: месяц - от 0 до 11.

Пример кода:

// Источник: http://stackoverflow.com/questions/497790
var dates = {
    convert: function(d) {
        // Преобразует дату в d в объект даты. Входные данные могут быть:
        //   объектом даты: возвращается без модификации
        //   массивом     : интерпретируется как [год, месяц, день]. ПРИМЕЧАНИЕ: месяц от 0 до 11.
        //   числом       : интерпретируется как количество миллисекунд
        //                  с 1 января 1970 года (метка времени)
        //   строкой      : любой формат, поддерживаемый движком JavaScript, например
        //                  "YYYY/MM/DD", "MM/DD/YYYY", "Jan 31 2009" и т.д.
        //   объектом     : интерпретируется как объект с атрибутами год, месяц и дата
        //                  ПРИМЕЧАНИЕ: месяц от 0 до 11.
        return (
            d.constructor === Date ? d :
            d.constructor === Array ? new Date(d[0], d[1], d[2]) :
            d.constructor === Number ? new Date(d) :
            d.constructor === String ? new Date(d) :
            typeof d === "object" ? new Date(d.year, d.month, d.date) :
            NaN
        );
    },
    compare: function(a, b) {
        // Сравнивает две даты (могут быть любого типа, поддерживаемого функцией convert)
        // и возвращает:
        //  -1 : если a < b
        //   0 : если a = b
        //   1 : если a > b
        // NaN : если a или b является некорректной датой
        // ПРИМЕЧАНИЕ: Код внутри isFinite выполняет присваивание (=).
        return (
            isFinite(a = this.convert(a).valueOf()) &&
            isFinite(b = this.convert(b).valueOf()) ?
            (a > b) - (a < b) :
            NaN
        );
    },
    inRange: function(d, start, end) {
        // Проверяет, попадает ли дата в d между датами start и end.
        // Возвращает булевый тип или NaN:
        //    true  : если d между start и end (включительно)
        //    false : если d раньше start или позже end
        //    NaN   : если одна или несколько дат некорректны.
        // ПРИМЕЧАНИЕ: Код внутри isFinite выполняет присваивание (=).
        return (
            isFinite(d = this.convert(d).valueOf()) &&
            isFinite(start = this.convert(start).valueOf()) &&
            isFinite(end = this.convert(end).valueOf()) ?
            start <= d && d <= end :
            NaN
        );
    }
}

Используйте этот код для работы с датами в JavaScript, что упростит ваши задачи по сравнению дат и проверке диапазонов.

1

Самый простой способ — вычесть одну дату из другой и сравнить результат.

var oDateOne = new Date();
var oDateTwo = new Date();

console.log(oDateOne - oDateTwo === 0); // Проверяет, равны ли даты
console.log(oDateOne - oDateTwo < 0);   // Проверяет, является ли oDateOne раньше oDateTwo
console.log(oDateOne - oDateTwo > 0);   // Проверяет, является ли oDateOne позже oDateTwo

Таким образом, результат вычитания двух объектов Date возвращает разницу в миллисекундах, что позволяет легко выполнить нужные сравнения.

0

Сравнение только даты (игнорируя временную составляющую):

Date.prototype.sameDay = function(d) {
  return this.getFullYear() === d.getFullYear()
    && this.getDate() === d.getDate()
    && this.getMonth() === d.getMonth();
}

Использование:

if(date1.sameDay(date2)) {
    // выделить день в календаре или что-то еще умное
}

Я больше не рекомендую изменять prototype встроенных объектов. Вместо этого попробуйте следующее:

function isSameDay(d1, d2) {
  return d1.getFullYear() === d2.getFullYear() &&
    d1.getDate() === d2.getDate() &&
    d1.getMonth() === d2.getMonth();
}

console.log(isSameDay(new Date('Jan 15 2021 02:39:53 GMT-0800'), new Date('Jan 15 2021 23:39:53 GMT-0800')));
console.log(isSameDay(new Date('Jan 15 2021 10:39:53 GMT-0800'), new Date('Jan 16 2021 10:39:53 GMT-0800')));

Обратите внимание, что год/месяц/день будут возвращены для вашего часового пояса; я рекомендую использовать библиотеку, учитывающую часовые пояса, если вы хотите проверить, принадлежат ли две даты одному и тому же дню в другом часовом поясе.

Например:

> (new Date('Jan 15 2021 01:39:53 Z')).getDate()  // 15 января по UTC
14  // Возвращает "14", потому что я в GMT-08
0

Примечание - Сравнение только части даты:

Когда мы сравниваем две даты в JavaScript, учитываются также часы, минуты и секунды. Поэтому, если нам нужно сравнить только даты, мы можем использовать следующий подход:

var date1 = new Date("01/01/2014").setHours(0, 0, 0, 0);
var date2 = new Date("01/01/2014").setHours(0, 0, 0, 0);

Теперь: выражение if (date1.valueOf() > date2.valueOf()) будет работать без проблем.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь