¿Agregar horas al objeto de fecha de JavaScript?

401

Me sorprende que el objeto Date de JavaScript no implemente una función add de ningún tipo.

Simplemente quiero una función que pueda hacer esto:

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

function Date.prototype.addHours(h) {

   // how do I implement this?  

}

Simplemente me gustaría algunos consejos en una dirección.

  • ¿Necesito hacer un análisis de cadenas?

  • ¿Puedo usar setTime?

  • ¿Qué tal milisegundos?

Me gusta esto:

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

Sin embargo, esto parece realmente hackeo, ¿e incluso funciona?

Jeff Meatball Yang
fuente

Respuestas:

424

JavaScript en sí tiene terribles API de fecha / hora. No obstante, puede hacer esto en JavaScript puro:

Date.prototype.addHours = function(h) {
  this.setTime(this.getTime() + (h*60*60*1000));
  return this;
}
Jason Harwig
fuente
¡Funciona de maravilla! Gracias
moreirapontocom
si, por ejemplo, está agregando una hora haciendo que se transfiera al día siguiente, ¿esto lo atraparía e incrementaría todo correctamente (día mes año)?
cdoern
@cdoern, creo que lo haría, ya que getTime () devolverá milisegundos y solo agregará más milisegundos a eso
1993
370
Date.prototype.addHours= function(h){
    this.setHours(this.getHours()+h);
    return this;
}

Prueba:

alert(new Date().addHours(4));
Kennebec
fuente
25
No creo que esto funcione --- ¿probarlo en algo con la hora 23, por ejemplo? La respuesta de Jason Harwig es lo que me vino a la mente.
Domenic
11
Es una mala práctica agregar cosas a un prototipo de objeto en Javascript, y Domenic es correcto, esto no funciona. La solución de Jason Harwig a continuación es mejor.
iKode
19
@Domenic Esto funciona bien con las 23:00, probado dentro de la consola de JavaScript de Firefox 10, Chrome 21 y IE 8/9 Aquí el código que he usado para probar: 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) También funciona bien con setMinutes ()
tanguy_k
44
Encontré problemas con esta solución: el aumento en 1 falló para mí en el punto de cambio de horario de verano (avance del reloj una hora).
andrewb
2
También me mordió esto: estaba recorriendo las horas usando setHours (getHours-1): ahora, en la primera hora del horario de verano, esto termina siendo un ciclo infinito. ¡Entonces, verifique el resultado!
cfstras
165

El siguiente código es para agregar 4 horas hasta la fecha (por ejemplo, la fecha de hoy)

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

No causará error si intentas agregar 4 a 23 (ver los documentos ):

Si un parámetro que especifica está fuera del rango esperado, setHours () intenta actualizar la información de fecha en el objeto Fecha en consecuencia

SuperNova
fuente
No vi esto e hice una respuesta duplicada. Me gusta este metodo. Preciso y útil.
Gandalf el Blanco
Esto no parece funcionar cuando las horas son un decimal (no un entero)
gregmagdits
3
Esta es la mejor respuesta aquí ... agregar "addHours" al prototipo de Date es preocupante porque en algún momento JS podría agregar soporte para esa función y luego tienes un prototipo conflictivo. Esto le brinda una funcionalidad al usar casi la misma cantidad de código.
Kris Boyd
sorprendido, pero en realidad día de incremento, meses si es necesario, un enlace a la documentación sería útil
2oppin
44
Si bien el uso de valores de hora> 23 no rompe esto, sin embargo, se rompe en los límites de horario de verano . Dado que está roto, no hay razón para usarlo; prefiero setTimeo setUTCHour.
Mark Amery
40

Probablemente sea mejor hacer que el método addHours sea inmutable devolviendo una copia del objeto Date en lugar de mutar su parámetro.

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

De esta manera, puede encadenar un montón de llamadas a métodos sin preocuparse por el estado.

Tahir Hassan
fuente
Esta función tiene los mismos problemas que se indican aquí stackoverflow.com/questions/1050720/... No se trata realmente de si funciona en ciertos navegadores, pero otros lugares que usan Javascript ven esto como un problema. peinar su solución con este stackoverflow.com/a/1050782/295535 parece ser la mejor solución
Ressu
1
Debería considerar cambiar el nombre de la función, ya que la palabra add*se usa comúnmente para mutar el objeto en sí.
Mr5
@ mr5: no estoy seguro de eso, addse usa mucho en la DateTimeclase .NET framework y tiene el mismo significado que el +(más) en matemáticas.
Tahir Hassan
1
currentDate.addHours(1)<- Desde mi instinto de programación, espero que el currentDatevalor cambie, pero en su implementación, no lo haría. En cuanto a por qué estoy sugiriendo cambiar el nombre o cambiar su firma a algo
mr5
1
@TahirHassan no tiene nada que ver con los detalles técnicos, sino con la elección de la palabra correcta para el nombre de la función. Todavía prefiero la versión mutable cuando la función tiene el prefijoadd
mr5
23

La versión sugerida por kennebec fallará al cambiar hacia o desde el horario de verano, ya que es el número de hora que se establece.

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

agregará hhoras a las thispeculiaridades del sistema de tiempo independiente. El método de Jason Harwig también funciona.

petter
fuente
19

Puede usar momentjs http://momentjs.com/ Library.

var moment = require('moment');
foo = new moment(something).add(10, 'm').toDate();
Cmag
fuente
7

También creo que el objeto original no debe modificarse. Entonces, para ahorrar mano de obra futura, aquí hay una solución combinada basada en las respuestas de Jason Harwig y Tahir Hasan :

Date.prototype.addHours= function(h){
    var copiedDate = new Date();
    copiedDate.setTime(this.getTime() + (h*60*60*1000)); 
    return copiedDate;
}
Edward Olamisan
fuente
5

Hay un complemento en la biblioteca Datejs .

Y aquí están los métodos de fecha de JavaScript . Kennebec mencionó sabiamente getHours () y setHours ();

Nosredna
fuente
Tenga en cuenta que esa biblioteca parece estar en estado alfa.
Sam
4

Compruebe si aún no está definido; de lo contrario, lo define en el prototipo de fecha:

if (!Date.prototype.addHours) {
    Date.prototype.addHours = function(h) {
        this.setHours(this.getHours() + h);
        return this;
    };
}
Mikael Engver
fuente
3

Otra forma de manejar esto es convertir la fecha a unixtime (epoch), luego agregar el equivalente en (mili) segundos, luego convertirlo nuevamente. De esta forma, puede manejar las transiciones de día y mes, como agregar 4 horas a 21, lo que debería resultar en el día siguiente, 01:00.

SPRBRN
fuente
Tienes razón, pero también llegas un par de años tarde. La respuesta de Jason Harwig mostró este método 2 años antes que tú; Esta respuesta no agrega nada nuevo.
Mark Amery
3

Para una función simple de agregar / restar hora / minuto en javascript, intente esto:

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);
};

Esto se puede usar sin parámetros para obtener la hora actual

getTime();

o con parámetros para obtener el tiempo con los minutos / horas agregados

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

incluso el tiempo negativo funciona

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

esta función devuelve una matriz de

array([Hour], [Minute], [Meridian])
Durkinza
fuente
¿Qué ventaja tiene este monstruo de 56 líneas de una función sobre el enfoque de dos líneas en la respuesta más votada ? -1 porque hay una enorme complejidad adicional aquí sin ningún beneficio que pueda ver.
Mark Amery
1

SPRBRN es correcto. Para contabilizar el inicio / fin del mes y año, debe convertir a Epoch y viceversa.

Así es como lo haces:

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


o hágalo en una línea (donde los nombres de las variables son los mismos que los anteriores:

var newDate = 
    new Date(startDate.getTime() + millisecond + 
        1000 * (sec + 60 * (min + 60 * (hours + 24 * days))));
JED
fuente
0

Esta es una manera fácil de obtener un valor de datos incrementado o disminuido.

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 )
Henrique Van Klaveren
fuente
-1

Un poco desordenado, pero funciona!

Dado un formato de fecha como este: 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+"");

Su salida sería: 2019-04-03T16: 58

Carl Du Plessis
fuente