Добавление часов в объект JavaScript Date?

403

Меня удивляет, что объект Date в JavaScript не реализует какую-либо функцию добавления.

Я просто хочу функцию, которая может сделать это:

var now = Date.now();
var fourHoursLater = now.addHours(4);

function Date.prototype.addHours(h) {

   // how do I implement this?  

}

Я просто хотел бы получить несколько указателей в направлении.

  • Нужно ли делать разбор строк?

  • Могу ли я использовать setTime?

  • Как насчет миллисекунд?

Нравится:

new Date(milliseconds + 4*3600*1000 /*4 hrs in ms*/)?  

Это кажется действительно взломанным, хотя - и это даже работает?

Джефф Фрикадель Ян
источник

Ответы:

425

У самого JavaScript есть ужасные API Date / Time. Тем не менее, вы можете сделать это в чистом JavaScript:

Date.prototype.addHours = function(h) {
  this.setTime(this.getTime() + (h*60*60*1000));
  return this;
}
Джейсон Харвиг
источник
Работает как шарм! Спасибо
moreirapontocom
если, скажем, вы добавляете час, заставляя его перенести на следующий день, будет ли это ловить его и увеличивать все должным образом (день, месяц, год)?
cdoern
@cdoern Я думаю, что так и будет, поскольку getTime () будет возвращать миллисекунды, а вы просто добавляете к этому еще миллисекунды
The1993
370
Date.prototype.addHours= function(h){
    this.setHours(this.getHours()+h);
    return this;
}

Тестовое задание:

alert(new Date().addHours(4));
Kennebec
источник
25
Я не думаю, что это работает --- протестируйте что-нибудь с часом 23, например? Ответ Джейсона Харвига - то, что пришло мне в голову.
Доменик
11
Это плохая практика - добавлять вещи в прототип объекта в Javascript, и Domenic верен, это не работает. Приведенное ниже решение Джейсона Харвига лучше.
iKode
19
@Domenic Это прекрасно работает с 23:00, протестировано в консоли JavaScript Firefox 10, Chrome 21 и IE 8/9. Вот код, который я использовал для тестирования: var date = new Date(2012, 10, 22, 23, 0, 1); date.toString(); // Thu Nov 22 2012 23:00:01 GMT+0100 (CET) date.setHours(date.getHours() + 1); date.toString(); // Fri Nov 23 2012 00:00:01 GMT+0100 (CET) Он также отлично работает с setMinutes ()
tanguy_k
4
У меня возникли проблемы с этим решением - мне не удалось увеличить на 1 в точке перехода на летнее время (перевести часы на час вперед).
Andrewb
2
Также меня это укусило - я перебирал часы с помощью setHours (getHours-1): теперь, в первый час летнего времени, это заканчивается бесконечным циклом. Итак, проверьте результат!
cfstras
165

Приведенный ниже код должен добавить 4 часа к дате (пример сегодняшней даты)

var today = new Date();
today.setHours(today.getHours() + 4);

Это не приведет к ошибке, если вы попытаетесь добавить 4 к 23 (см. Документы ):

Если указанный параметр находится за пределами ожидаемого диапазона, setHours () пытается соответствующим образом обновить информацию о дате в объекте Date

SuperNova
источник
Я не видел этого и сделал дубликат ответа. Мне нравится этот метод. Точно и полезно.
Гэндальф Белый
Кажется, что это не работает, когда часы десятичные (не целые)
gregmagdits
3
Это лучший ответ здесь ... добавление addHours к прототипу Date вызывает беспокойство, поскольку в какой-то момент JS может добавить поддержку этой функции, и тогда у вас будет конфликтующий прототип. Это дает вам функциональность с использованием примерно столько же кода.
Крис Бойд
Удивлен, но на самом деле это увеличение дней, месяцев, если это необходимо, ссылка на документы была бы полезна
2oppin
4
Хотя использование значений часов> 23 не нарушает этого, оно тем не менее нарушает границы перехода на летнее время . Учитывая, что он сломан, нет причин использовать его; предпочитаю setTimeили setUTCHour.
Марк Амери
40

Вероятно, лучше сделать метод addHours неизменным, возвращая копию объекта Date, а не изменяя его параметр.

Date.prototype.addHours= function(h){
    var copiedDate = new Date(this.getTime());
    copiedDate.setHours(copiedDate.getHours()+h);
    return copiedDate;
}

Таким образом, вы можете связать несколько вызовов методов, не беспокоясь о состоянии.

Тахир Хасан
источник
Эта функция имеет те же проблемы, что и здесь. Stackoverflow.com/questions/1050720/… Дело не в том, работает ли она в определенных браузерах, но в других местах, использующих Javascript, это рассматривается как проблема. объединение вашего решения с этим stackoverflow.com/a/1050782/295535 представляется наилучшим решением
Ressu
1
Вы должны рассмотреть возможность изменения имени функции, так как слово add*обычно используется для изменения самого объекта.
mr5
@ mr5 - не уверен в этом, addчасто используется в классе .NET Framework DateTimeи имеет то же значение, что и +(плюс) в Math.
Тахир Хасан
1
currentDate.addHours(1)<- Исходя из моего программного инстинкта, я ожидаю, что currentDateзначение изменится, но в вашей реализации этого не произойдет. Что касается того, почему я предлагаю переименовать или изменить свою подпись на что-то
mr5
1
@TahirHassan не имеет ничего общего с техническими деталями, но при выборе правильного слова для использования в качестве имени функции. Я все еще предпочитаю изменчивую версию, когда перед функцией стоит префиксadd
mr5
23

Версия, предложенная kennebec, потерпит неудачу при переходе на летнее или зимнее время, так как это номер часа, который установлен.

this.setUTCHours(this.getUTCHours()+h);

добавит hчасы к thisнезависимым от времени системным особенностям. Метод Джейсона Харвига также работает.

Petter
источник
19

Вы можете использовать моментальные http://momentjs.com/ Библиотека.

var moment = require('moment');
foo = new moment(something).add(10, 'm').toDate();
Cmag
источник
7

Я также думаю, что оригинальный объект не должен быть изменен. Таким образом, чтобы спасти будущую рабочую силу, вот комбинированное решение, основанное на ответах Джейсона Харвига и Тахира Хасана :

Date.prototype.addHours= function(h){
    var copiedDate = new Date();
    copiedDate.setTime(this.getTime() + (h*60*60*1000)); 
    return copiedDate;
}
Эдвард Оламисан
источник
5

В библиотеке Datejs есть дополнение .

И вот методы даты JavaScript . Кеннебек мудро упомянул getHours () и setHours ();

Nosredna
источник
Обратите внимание, что эта библиотека находится в альфа-статусе.
Сам
4

Проверьте, не определен ли он, иначе определите его в прототипе Date:

if (!Date.prototype.addHours) {
    Date.prototype.addHours = function(h) {
        this.setHours(this.getHours() + h);
        return this;
    };
}
Микаэль Энгвер
источник
3

Другой способ справиться с этим - преобразовать дату в unixtime (эпоху), затем добавить эквивалент в (милли) секундах, а затем преобразовать его обратно. Таким образом, вы можете обрабатывать переходы дня и месяца, например добавление 4 часов к 21, что должно привести к следующему дню, 01:00.

SPRBRN
источник
Ты прав - но ты тоже на пару лет опоздал. Ответ Джейсона Харвига показал этот метод за 2 года до вас; этот ответ не добавляет ничего нового.
Марк Амери
3

Для простого добавления / вычитания функции часа / минуты в javascript попробуйте это:

function getTime (addHour, addMin){
    addHour = (addHour?addHour:0);
    addMin = (addMin?addMin:0);
    var time = new Date(new Date().getTime());
    var AM = true;
    var ndble = 0;
    var hours, newHour, overHour, newMin, overMin;
    //change form 24 to 12 hour clock
    if(time.getHours() >= 13){
        hours = time.getHours() - 12;
        AM = (hours>=12?true:false);
    }else{
        hours = time.getHours();
        AM = (hours>=12?false:true);
    }
    //get the current minutes
    var minutes = time.getMinutes();
    // set minute
    if((minutes+addMin) >= 60 || (minutes+addMin)<0){
        overMin = (minutes+addMin)%60;
        overHour = Math.floor((minutes+addMin-Math.abs(overMin))/60);
        if(overMin<0){
            overMin = overMin+60;
            overHour = overHour-Math.floor(overMin/60);
        }
        newMin = String((overMin<10?'0':'')+overMin);
        addHour = addHour+overHour;
    }else{
        newMin = minutes+addMin;
        newMin = String((newMin<10?'0':'')+newMin);
    }
    //set hour
    if(( hours+addHour>=13 )||( hours+addHour<=0 )){
        overHour = (hours+addHour)%12;
        ndble = Math.floor(Math.abs((hours+addHour)/12));
        if(overHour<=0){
            newHour = overHour+12;
            if(overHour == 0){
                ndble++;
            }
        }else{
            if(overHour ==0 ){
                newHour = 12;
                ndble++;
            }else{
                ndble++;
                newHour = overHour;
            }
        }
        newHour = (newHour<10?'0':'')+String(newHour);
        AM = ((ndble+1)%2===0)?AM:!AM;
    }else{
        AM = (hours+addHour==12?!AM:AM);
        newHour = String((Number(hours)+addHour<10?'0':'')+(hours+addHour));
    }
    var am = (AM)?'AM':'PM';
    return new Array(newHour, newMin, am);
};

Это можно использовать без параметров, чтобы получить текущее время

getTime();

или с параметрами, чтобы получить время с добавленными минутами / часами

getTime(1,30); // adds 1.5 hours to current time
getTime(2);    // adds 2 hours to current time
getTime(0,120); // same as above

даже негативное время работает

getTime(-1, -30); // subtracts 1.5 hours from current time

эта функция возвращает массив

array([Hour], [Minute], [Meridian])
durkinza
источник
Какое преимущество имеет этот 56-строчный монстр функции по сравнению с двухстрочным подходом в ответе с наибольшим количеством голосов ? -1 потому что здесь есть огромная дополнительная сложность, которую я не вижу.
Марк Амери
1

СПРБРН правильный. Для того чтобы учесть начало / конец месяца и года, вам необходимо перейти в эпоху и обратно.

Вот как вы это делаете:

var milliseconds = 0;          //amount of time from current date/time
var sec = 0;                   //(+): future
var min = 0;                   //(-): past
var hours = 2;
var days = 0;

var startDate = new Date();     //start date in local time (we'll use current time as an example)

var time = startDate.getTime(); //convert to milliseconds since epoch

//add time difference
var newTime = time + milliseconds + (1000*sec) + (1000*60*min) + (1000*60*60*hrs) + (1000*60*60*24)

var newDate = new Date(newTime);//convert back to date; in this example: 2 hours from right now


или сделать это в одной строке (где имена переменных такие же, как указано выше:

var newDate = 
    new Date(startDate.getTime() + millisecond + 
        1000 * (sec + 60 * (min + 60 * (hours + 24 * days))));
Джидда
источник
0

Это простой способ получить увеличенное или уменьшенное значение данных.

const date = new Date()
const inc = 1000 * 60 * 60 // an hour
const dec = (1000 * 60 * 60) * -1 // an hour

const _date = new Date(date)
return new Date( _date.getTime() + inc )
return new Date( _date.getTime() + dec )
Энрике Ван Клаверен
источник
-1

Немного грязно, но это работает!

Учитывая формат даты как это: 2019-04-03T15: 58

  //Get the start date.
  var start = $("#start_date").val();
  //Split the date and time.
  var startarray = start.split("T");
  var date = startarray[0];
  var time = startarray[1];

  //Split the hours and minutes.
  var timearray = time.split(":");

  var hour = timearray[0];
  var minute = timearray[1];
  //Add an hour to the hour.
  hour++;
  //$("#end_date").val = start;
  $("#end_date").val(""+date+"T"+hour+":"+minute+"");

Ваш вывод будет: 2019-04-03T16: 58

Карл дю Плесси
источник