Ajout d'heures à l'objet Date JavaScript?

402

Cela m'étonne que l'objet Date de JavaScript n'implémente aucune fonction d'ajout d'aucune sorte.

Je veux simplement une fonction qui puisse le faire:

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

function Date.prototype.addHours(h) {

   // how do I implement this?  

}

Je voudrais simplement quelques indications dans une direction.

  • Dois-je faire une analyse de chaîne?

  • Puis-je utiliser setTime?

  • Que diriez-vous des millisecondes?

Comme ça:

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

Cela semble vraiment hackeux - et ça marche même?

Jeff Meatball Yang
la source

Réponses:

425

JavaScript lui-même a de terribles API de date / heure. Néanmoins, vous pouvez le faire en JavaScript pur:

Date.prototype.addHours = function(h) {
  this.setTime(this.getTime() + (h*60*60*1000));
  return this;
}
Jason Harwig
la source
Fonctionne comme un charme! Merci
moreirapontocom
si, par exemple, vous ajoutiez une heure pour la reporter au lendemain, est-ce que cela la rattraperait et incrémenterait tout correctement (jour, mois, année)?
cdoern
@cdoern Je pense que oui, puisque getTime () renverra des millisecondes et que vous
ajouterez
370
Date.prototype.addHours= function(h){
    this.setHours(this.getHours()+h);
    return this;
}

Tester:

alert(new Date().addHours(4));
kennebec
la source
25
Je ne pense pas que cela fonctionne --- testez-le sur quelque chose avec l'heure 23, par exemple? La réponse de Jason Harwig est ce qui m'est venu à l'esprit.
Domenic
11
C'est une mauvaise pratique d'ajouter des choses à un prototype d'objet en Javascript, et Domenic est correct, cela ne fonctionne pas. La solution de Jason Harwig ci-dessous est meilleure.
iKode
19
@Domenic Cela fonctionne très bien avec 23:00, testé dans la console JavaScript de Firefox 10, Chrome 21 et IE 8/9 Voici le code que j'ai utilisé pour tester: 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) Cela fonctionne également très bien avec setMinutes ()
tanguy_k
4
J'ai rencontré des problèmes avec cette solution - L'incrémentation de 1 a échoué pour moi au point de passage à l'heure d'été (déplacer l'horloge d'une heure).
andrewb
2
J'ai également été mordu par cela - je parcourais des heures en utilisant setHours (getHours-1): maintenant, à la première heure DST, cela finit par être une boucle infinie. Alors, vérifiez le résultat!
cfstras
165

Le code ci-dessous est d'ajouter 4 heures à ce jour (exemple la date du jour)

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

Cela ne provoquera pas d'erreur si vous essayez d'ajouter 4 à 23 (voir la documentation ):

Si un paramètre que vous spécifiez est en dehors de la plage attendue, setHours () tente de mettre à jour les informations de date dans l'objet Date en conséquence

SuperNova
la source
Je ne l'ai pas vu et j'ai fait une réponse en double. J'aime cette méthode. Précis et utile.
Gandalf le Blanc
Cela ne semble pas fonctionner lorsque les heures sont décimales (pas un entier)
gregmagdits
3
C'est la meilleure réponse ici ... ajouter "addHours" au prototype Date est inquiétant car à un moment donné, JS pourrait ajouter le support de cette fonction et vous avez alors un prototype conflictuel. Cela vous donne une fonctionnalité avec l'utilisation de presque autant de code.
Kris Boyd
surpris, mais il incrémente en fait des jours, des mois s'il le faut, un lien vers les documents serait utile
2oppin
4
Bien que l'utilisation de valeurs d'heure> 23 ne brise pas cela, il est néanmoins cassé aux limites de l'heure d'été . Étant donné qu'il est cassé, il n'y a aucune raison de l'utiliser; préférez setTimeou setUTCHour.
Mark Amery
40

Il est probablement préférable de rendre la méthode addHours immuable en renvoyant une copie de l'objet Date plutôt que de muter son paramètre.

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

De cette façon, vous pouvez chaîner un tas d'appels de méthode sans vous soucier de l'état.

Tahir Hassan
la source
Cette fonction a les mêmes problèmes énoncés ici stackoverflow.com/questions/1050720/...~~V~~number=plural~~singular~~3rd Ce n'est pas vraiment si cela fonctionne sur certains navigateurs, mais d' autres endroits qui utilisent Javascript voir cela comme un problème. peigner votre solution avec celle-ci stackoverflow.com/a/1050782/295535 semble être la meilleure solution
Ressu
1
Vous devriez envisager de changer le nom de la fonction, car le mot add*est couramment utilisé pour muter l'objet lui-même.
mr5
@ mr5 - pas sûr de cela, addest DateTimebeaucoup utilisé dans la classe de framework .NET , et a la même signification que le +(plus) en mathématiques.
Tahir Hassan
1
currentDate.addHours(1)<- De mon instinct de programmation, je m'attends à ce que la currentDatevaleur change, mais dans votre implémentation, ce ne serait pas le cas. Quant à savoir pourquoi je
propose
1
@TahirHassan n'a rien à voir avec les détails techniques mais à choisir le bon mot à utiliser pour le nom de la fonction. Je préfère toujours la version mutable lorsque la fonction est préfixée avecadd
mr5
23

La version suggérée par kennebec échouera lors du passage vers ou depuis l'heure d'été, car c'est le numéro de l'heure qui est défini.

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

ajoutera des hheures aux particularités thisindépendantes du système de temps. La méthode de Jason Harwig fonctionne également.

petter
la source
19

Vous pouvez utiliser la bibliothèque momentjs http://momentjs.com/ .

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

Je pense également que l'objet d'origine ne doit pas être modifié. Donc, pour économiser de la main-d'œuvre future, voici une solution combinée basée sur les réponses de Jason Harwig et Tahir Hasan :

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

Il y a un ajout dans la bibliothèque Datejs .

Et voici les méthodes de date JavaScript . kennebec a judicieusement mentionné getHours () et setHours ();

Nosredna
la source
Notez que cette bibliothèque semble être en état alpha.
Sam
4

Vérifiez si ce n'est pas déjà défini, sinon définissez-le sur le prototype Date:

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

Une autre façon de gérer cela est de convertir la date en unixtime (epoch), puis d'ajouter l'équivalent en (milli) secondes, puis de la reconvertir. De cette façon, vous pouvez gérer les transitions de jour et de mois, comme ajouter 4 heures à 21, ce qui devrait se traduire par le lendemain, 01h00.

SPRBRN
la source
Vous avez raison - mais vous avez également quelques années de retard. La réponse de Jason Harwig a montré cette méthode 2 ans avant vous; cette réponse n'ajoute rien de nouveau.
Mark Amery
3

Pour une simple fonction d'ajout / soustraction d'heure / minute en javascript, essayez ceci:

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

Cela peut être utilisé sans paramètres pour obtenir l'heure actuelle

getTime();

ou avec des paramètres pour obtenir l'heure avec les minutes / heures ajoutées

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

même le temps négatif fonctionne

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

cette fonction renvoie un tableau de

array([Hour], [Minute], [Meridian])
durkinza
la source
Quel avantage ce monstre de 56 lignes d'une fonction a-t-il sur l' approche à deux lignes dans la réponse la plus votée ? -1 car il y a une énorme complexité supplémentaire ici sans aucun avantage que je puisse voir.
Mark Amery
1

SPRBRN est correct. Afin de prendre en compte le début / la fin du mois et de l'année, vous devez vous convertir en Epoch et inversement.

Voici comment procéder:

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


ou faites-le sur une seule ligne (où les noms de variables sont les mêmes que ci-dessus:

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

C'est un moyen facile d'obtenir une valeur de données incrémentée ou décrémentée.

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
la source
-1

Un peu en désordre, mais ça marche!

Étant donné un format de date comme celui-ci: 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+"");

Votre sortie serait: 2019-04-03T16: 58

Carl Du Plessis
la source