Сравнение только части даты без сравнения времени в JavaScript - PullRequest
339 голосов
/ 23 апреля 2010

Что не так с кодом ниже?

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

Кстати, когда я отображаю две даты в предупреждении, они отображаются одинаково.

Мой код:

window.addEvent('domready', function() {
    var now = new Date();
    var input = $('datum').getValue();
    var dateArray = input.split('/');
    var userMonth = parseInt(dateArray[1])-1;
    var userDate = new Date();
    userDate.setFullYear(dateArray[2], userMonth, dateArray[0], now.getHours(), now.getMinutes(), now.getSeconds(), now.getMilliseconds());

    if (userDate > now)
    {
        alert(now + '\n' + userDate);
    }
});

Есть ли более простой способ сравнения дат без учета времени?

Ответы [ 20 ]

700 голосов
/ 01 июня 2011

Я все еще изучаю JavaScript, и я нашел единственный способ сравнить две даты без времени, используя метод setHours объекта Date и установите часы, минуты, секунды и миллисекунды на ноль. Затем сравните две даты.

Например,

date1 = new Date()
date2 = new Date(2011,8,20)

date2 будет установлен с часами, минутами, секундами и миллисекундами на ноль, но для date1 будет установлено время создания даты1. Чтобы избавиться от часов, минут, секунд и миллисекунд на дату1, сделайте следующее:

date1.setHours(0,0,0,0)

Теперь вы можете сравнивать две даты только как ДАТЫ, не беспокоясь об элементах времени.

77 голосов
/ 27 июня 2016

ОСТЕРЕГАЙТЕСЬ ВРЕМЕННОЙ ЗОНЕ

Использование объекта даты для непосредственного представления даты-даты влечет за собой огромную проблему избыточной точности.Вам нужно управлять временем и часовым поясом, чтобы не пускать их, и они могут вернуться обратно на любом этапе. Принятый ответ на этот вопрос попадает в ловушку.

Дата JavaScript не имеет понятия о часовом поясе .Это момент времени (тики начиная с эпохи) с удобными (статическими) функциями для перевода в и из строк, с использованием по умолчанию «локального» часового пояса устройства или, если указано, UTC или другого часового пояса.Чтобы представить дату с помощью объекта даты, вы хотите, чтобы ваши даты представляли полночь UTC в начале рассматриваемой даты. Это общее и необходимое соглашение, которое позволяет работать с датами независимо от сезона иличасовой пояс их создания.Поэтому вам нужно быть очень бдительными, чтобы управлять понятием часового пояса, как при создании объекта «Дата в формате UTC», так и при его сериализации.

Многие люди смущены поведением консоли по умолчанию.Если вы распылите дату на консоль, вы увидите, что вы увидите ваш часовой пояс.Это просто потому, что консоль вызывает toString() в вашу дату, а toString() дает вам локальное представление.Базовая дата не имеет часового пояса !(Пока время совпадает со смещением часового пояса, у вас все еще есть объект даты UTC в полночь)

десериализация (или создание объектов даты UTC в полночь)

Большинство извремя, вы хотите, чтобы ваша дата отражала часовой пояс пользователя. Нажмите, если сегодня ваш день рождения .Пользователи в Новой Зеландии и США нажимают одновременно и получают разные даты.В этом случае сделайте это ...

// create a date (utc midnight) reflecting the value of myDate and the environment's timezone offset.
new Date(Date.UTC(myDate.getFullYear(),myDate.getMonth(), myDate.getDate()));

Иногда международная сопоставимость превосходит локальную точность.В этом случае сделайте это ...

// the date in London of a moment in time. Device timezone is ignored.
new Date(Date.UTC(myDate.getUTCFullYear(), myDate.getUTCMonth(), myDate.getUTCDate()));

Десериализация даты

Часто даты на проводе будут в формате ГГГГ-ММ-ДД.Чтобы десериализовать их, сделайте это ...

var midnightUTCDate = new Date( dateString + 'T00:00:00Z');

Сериализация

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

  • toISOString()
  • getUTCxxx()
  • getTime() //returns a number with no time or timezone.
  • .toLocaleDateString("fr",{timezone:"UTC"}) // whatever locale you want, but ALWAYS UTC.

И полностью избегайте всего остального, особенно ...

  • getYear(), getMonth(), getDate()

Итак, чтобы ответить на ваш вопрос, опоздал на 7 лет ...

<input type="date" onchange="isInPast(event)">
<script>
var isInPast = function(event){
  debugger;
  var userEntered = new Date(event.target.valueAsNumber); // valueAsNumber has no time or timezone!
  var now = new Date();
  var today = new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() ));
  if(userEntered.getTime() < today.getTime())
    alert("date is past");
  else if(userEntered.getTime() == today.getTime())
    alert("date is today");
  else
    alert("date is future");

}
</script>

Вижу это ...

66 голосов
/ 13 апреля 2015

Как насчет этого?

Date.prototype.withoutTime = function () {
    var d = new Date(this);
    d.setHours(0, 0, 0, 0);
    return d;
}

Позволяет вам сравнивать часть даты с такой датой, не влияя на значение вашей переменной:

var date1 = new Date(2014,1,1);
new Date().withoutTime() > date1.withoutTime(); // true
21 голосов
/ 10 июля 2016

Использование Moment.js

Если у вас есть возможность включить стороннюю библиотеку, определенно стоит взглянуть на Moment.js . Это значительно упрощает работу с Date и DateTime.

Например, видя, что одна Дата идет после другой, но исключая их время, вы бы сделали что-то вроде этого:

var date1 = new Date(2016,9,20,12,0,0); // October 20, 2016 12:00:00
var date2 = new Date(2016,9,20,12,1,0); // October 20, 2016 12:01:00

// Comparison including time.
moment(date2).isAfter(date1); // => true

// Comparison excluding time.
moment(date2).isAfter(date1, 'day'); // => false

Второй параметр, который вы передаете в isAfter - это точность для сравнения, которая может быть любой из year, month, week, day, hour, minute или second.

9 голосов
/ 03 февраля 2017

Просто сравните, используя .toDateString, как показано ниже:

new Date().toDateString();

Это вернет вам только часть даты, а не время или часовой пояс, например:

«Пт Фев 03 2017»

Следовательно, обе даты можно сравнивать в этом формате аналогично без временной части.

8 голосов
/ 02 июня 2011

Это может быть немного более чистая версия, также обратите внимание, что вы всегда должны использовать radix при использовании parseInt.

window.addEvent('domready', function() {
    // Create a Date object set to midnight on today's date
    var today = new Date((new Date()).setHours(0, 0, 0, 0)),
    input = $('datum').getValue(),
    dateArray = input.split('/'),
    // Always specify a radix with parseInt(), setting the radix to 10 ensures that
    // the number is interpreted as a decimal.  It is particularly important with
    // dates, if the user had entered '09' for the month and you don't use a
    // radix '09' is interpreted as an octal number and parseInt would return 0, not 9!
    userMonth = parseInt(dateArray[1], 10) - 1,
    // Create a Date object set to midnight on the day the user specified
    userDate = new Date(dateArray[2], userMonth, dateArray[0], 0, 0, 0, 0);

    // Convert date objects to milliseconds and compare
    if(userDate.getTime() > today.getTime())
    {
            alert(today+'\n'+userDate);
    }
});

Оформить страницу MDC parseInt для получения дополнительной информации о radix.

JSLint - это отличный инструмент для обнаружения таких вещей, как отсутствующий осциллограф и многие другие вещи, которые могут вызвать неясные и сложные ошибки отладки.Это заставляет вас использовать лучшие стандарты кодирования, чтобы избежать головной боли в будущем.Я использую его в каждом проекте JavaScript, который я кодирую.

5 голосов
/ 23 апреля 2010

Библиотека date.js удобна для этих целей. Это значительно упрощает все сценарии, связанные с датой в JS.

3 голосов
/ 07 ноября 2011

Вот как я это делаю:

var myDate  = new Date($('input[name=frequency_start]').val()).setHours(0,0,0,0);
var today   = new Date().setHours(0,0,0,0);
if(today>myDate){
    jAlert('Please Enter a date in the future','Date Start Error', function(){
        $('input[name=frequency_start]').focus().select();
    });
}
3 голосов
/ 26 марта 2015

Поскольку я не вижу здесь подобного подхода, и мне не нравится устанавливать h / m / s / ms в 0, так как это может вызвать проблемы с точным переходом на местный часовой пояс с измененным date объектом (Iпредположим так), позвольте мне представить здесь, написанную несколько мгновений назад, функцию lil:

+: Прост в использовании, выполняет основные операции сравнения (сравнение дня, месяца и года без времени.)
-: Кажется, что это полная противоположность мышлению "из коробки".

function datecompare(date1, sign, date2) {
    var day1 = date1.getDate();
    var mon1 = date1.getMonth();
    var year1 = date1.getFullYear();
    var day2 = date2.getDate();
    var mon2 = date2.getMonth();
    var year2 = date2.getFullYear();
    if (sign === '===') {
        if (day1 === day2 && mon1 === mon2 && year1 === year2) return true;
        else return false;
    }
    else if (sign === '>') {
        if (year1 > year2) return true;
        else if (year1 === year2 && mon1 > mon2) return true;
        else if (year1 === year2 && mon1 === mon2 && day1 > day2) return true;
        else return false;
    }    
}

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

datecompare(date1, '===', date2) для проверки на равенство,
datecompare(date1, '>', date2) для большей проверки,
!datecompare(date1, '>', date2) для проверки меньшей или равной

Также, очевидно, вы можете переключать date1 и date2 в некоторых местах для достижения любого другого простого сравнения.

2 голосов
/ 08 марта 2018

Эффективный и правильный способ сравнения дат:

Math.floor(date1.getTime() / 86400000) > Math.floor(date2.getTime() / 86400000);

Он игнорирует временную часть, он работает для разных часовых поясов, и вы также можете сравнить на равенство ==. 86400000 - это количество миллисекунд в дне (= 24*60*60*1000).

Помните, что оператор равенства == не должен никогда использоваться для сравнения объектов Date, потому что он терпит неудачу, когда вы ожидаете, что сработает тест на равенство, поскольку он сравнивает два объекта Date (и не сравнивает две даты) например:

> date1;
outputs: Thu Mar 08 2018 00:00:00 GMT+1300

> date2;
outputs: Thu Mar 08 2018 00:00:00 GMT+1300

> date1 == date2;
outputs: false

> Math.floor(date1.getTime() / 86400000) == Math.floor(date2.getTime() / 86400000);
outputs: true

Примечания. Если вы сравниваете объекты Date, для которых временная часть установлена ​​на ноль, вы можете использовать date1.getTime() == date2.getTime(), но вряд ли стоит оптимизировать. Вы можете использовать <, >, <= или >= при непосредственном сравнении объектов Date, поскольку эти операторы сначала преобразуют объект Date, вызывая .valueOf() до того, как оператор выполнит сравнение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...