75 votes

Comment utiliser Date en Javascript pour les dates préhistoriques ?

Je travaille sur un projet où la date JavaScript n'est pas assez grande.

Je veux placer plusieurs événements sur le même axe temporel. Certains d'entre eux ont un mois et un jour, d'autres non, donc l'année n'est pas une option. Je veux pouvoir placer l'alunissage et le big bang sur le même axe.

Cela m'aiderait beaucoup si je pouvais utiliser la fonctionnalité de l'objet Date existant. Il ne remonte qu'à 270 000 ans et je dois remonter jusqu'au big bang (il y a 13 800 000 000 d'années). Je n'ai pas besoin que les dates contiennent des secondes ou des millisecondes.

Comment puis-je étendre l'objet Date pour inclure la représentation de telles dates ?

J'ai essayé de trouver des bibliothèques ou des fonctions natives pour cela, mais sans succès. J'ai également commencé à chercher une implémentation JavaScript de l'objet Date que je pourrais modifier, mais là non plus je n'ai pas eu de chance.

Mise à jour :

J'ai commencé avec la solution de remdevtec mais j'ai fini par la modifier assez souvent. Je voulais que les dates soient dans l'ordre numérique pour faciliter le tri et l'ordre des dates.

Ce que j'ai fait, c'est que si l'année est antérieure à -100 000, je traite la valeur en millisecondes comme des heures. C'est ce que j'ai obtenu jusqu'à présent, et cela fonctionne dans notre projet, mais si j'ai plus de temps, je vais le nettoyer et le mettre sur github.

JSFiddle

function BigDate(date){
    if(!date){
        this.original = new Date(); 
    }else if(date instanceof BigDate){
        this.original = date.original;
    }else{
        this.original = new Date(date);  
    }
    this.yearBreakpoint = -100000;
    this.breakPoint = Date.UTC(this.yearBreakpoint,0,0).valueOf();
    this.factor = 360000;//needed for our project to make extra space on our axis
}

BigDate.UTC = function (year, month, day, hour, minute, second, millisecond) {
    var temp = new BigDate();
    if(year < -temp.yearBreakpoint){
        temp.setUTCFullYear(year);
        return temp;
    }else{
        temp.original = Date.UTC(year,month,day,hour,minute,second,millisecond);
    }
    return temp.valueOf();
};

BigDate.now = function (){
    var temp = new BigDate();
    temp.original = Date.now();
    return temp.valueOf();
};

BigDate.parse = function (val){
    throw "not implemnted";
};

//custom functions

BigDate.prototype.getUTCDate = function () {
   if(this.valueOf() < this.breakPoint){
       return 0;
   }
   return this.original.getUTCDate();
};
BigDate.prototype.getUTCDay = function () {
   if(this.valueOf() < this.breakPoint){
        return 0;
    }
    return this.original.getUTCDay();
};
BigDate.prototype.getUTCFullYear = function () {
    if(this.valueOf() < this.breakPoint){
        return (this.valueOf() - this.breakPoint) / this.factor;
    }
    return this.original.getUTCFullYear();
};
BigDate.prototype.getUTCHours = function () {
    if(this.valueOf() < this.breakPoint){
        return 0;
    }
    return this.original.getUTCHours();
};
BigDate.prototype.getUTCMilliseconds = function () {
    if(this.valueOf() < this.breakPoint){
        return 0;
    }
    return this.original.getUTCMilliseconds();
};
BigDate.prototype.getUTCMinutes = function () {
    if(this.valueOf() < this.breakPoint){
        return 0;
    }
    return this.original.getUTCMinutes();
};
BigDate.prototype.getUTCMonth = function () {
    if(this.valueOf() < this.breakPoint){
        return 0;
    }
    return this.original.getUTCMonth();
};
BigDate.prototype.getUTCSeconds = function () {
    if(this.valueOf() < this.breakPoint){
        return 0;
    }
    return this.original.getUTCSeconds();
};

BigDate.prototype.setUTCDate = function (val) {
    if(val >= this.yearBreakpoint){
      return this.original.setUTCDate(val);
   }
};
BigDate.prototype.setUTCFullYear = function (val) {
    if(val < this.yearBreakpoint){
        this.original.setTime((parseInt(val) * this.factor) + this.breakPoint);
    }else{
        this.original.setUTCFullYear(val);
    }
    return this.valueOf();
};
BigDate.prototype.setUTCHours = function (val) {
    if(val >= this.yearBreakpoint){
      return this.original.setUTCHours(val);
    }
};
BigDate.prototype.setUTCMilliseconds = function (val) {
    if(val >= this.yearBreakpoint){
      return this.original.setUTCMilliseconds(val);
    }
};
BigDate.prototype.setUTCMinutes = function (val) {
    if(val >= this.yearBreakpoint){
        return this.original.setUTCMinutes(val);
    }
};
BigDate.prototype.setUTCMonth = function (val) {
    if(val >= this.yearBreakpoint){
      return   this.original.setUTCMonth(val);
    }
};
BigDate.prototype.setUTCSeconds = function (val) {
    if(val >= this.yearBreakpoint){
       return  this.original.setUTCSeconds(val);
    }
};

BigDate.prototype.setTime = function (val) {
    this.original.setTime(val);
    return this.valueOf();
};
BigDate.prototype.valueOf = function () {
    return this.original.valueOf();
};

BigDate.prototype.toDateString = function () {
    if(this.valueOf() < this.breakPoint){
        return "Jan 01 " + this.getUTCFullYear();
    }
    return this.original.toDateString();
};
BigDate.prototype.toISOString = function () {
    if(this.valueOf() < this.breakPoint){
        return this.getUTCFullYear() + "-01-01T00:00:00.000Z";
    }
    return this.original.toISOString();
};

BigDate.prototype.toJSON = function () {
    throw "not implemnted";
};
BigDate.prototype.toLocaleDateString = function () {
    throw "not implemnted";
};
BigDate.prototype.toLocaleTimeString = function () {
    throw "not implemnted";
};
BigDate.prototype.toLocaleString = function () {
    throw "not implemnted";
};
BigDate.prototype.toTimeString = function () {
    throw "not implemnted";
};
BigDate.prototype.toUTCString = function () {
    if(this.valueOf() < this.breakPoint){
        return "01 Jan "+ this.getFullYear() +" 00:00:00 GMT";
    }
    return this.original.toUTCString();
};

/**
 * Don't need no timezones
 */

BigDate.prototype.getDate = function () {
    return this.getUTCDate();
};
BigDate.prototype.getDay = function () {
    return this.getUTCDay();
};
BigDate.prototype.getFullYear = function () {
    return this.getUTCFullYear();
};
BigDate.prototype.getHours = function () {
    return this.getUTCHours();
};
BigDate.prototype.getMilliseconds = function() {
    return this.getUTCMilliseconds();
};
BigDate.prototype.getMinutes = function() { 
    return this.getUTCMinutes();
};
BigDate.prototype.getMonth = function () {
    return this.getUTCMonth();
};
BigDate.prototype.getSeconds = function () {
    return this.getUTCSeconds();
};
BigDate.prototype.getTimezoneOffset = function () {
    return 0;
};
BigDate.prototype.getTime = function () {
    return this.valueOf();
};

BigDate.prototype.setDate = function (val) {
    return this.setUTCDate(val);
};
BigDate.prototype.setFullYear = function (val) {
    return this.setUTCFullYear(val);
};
BigDate.prototype.setHours = function (val) {
    return this.setUTCHours(val);
};
BigDate.prototype.setMilliseconds = function (val) {
    return this.setUTCMilliseconds(val);
};
BigDate.prototype.setMinutes = function (val) {
    return this.setUTCMinutes(val);
};
BigDate.prototype.setMonth = function (val) {
    return this.setUTCMonth(val);
};
BigDate.prototype.setSeconds = function (val) {
    return this.setUTCSeconds(val);
};

BigDate.prototype.toString = function () {
    return this.toUTCString();
};

81voto

remdevtec Points 1630

Je n'ai pas besoin que les dates contiennent des secondes ou des millisecondes.

Notez que le calendrier grégorien se déplace par cycles de 400 ans, donc par cycles de 240 000 ans. Vous pouvez donc prendre la représentation de 60000 millisecondes de Date que vous ne voulez pas utiliser, pour revenir en arrière par cycles de 240000 ans (jusqu'à 60000 cycles). Cela peut vous amener à environ un an 14,4 milliards d'années avant Jésus-Christ (juste avant le Big Bang :) ), avec une résolution infime.

L'exemple suivant ne prend pas en compte toutes les fonctionnalités de l'objet Date. Cependant, avec une implémentation plus poussée, je pense qu'il est possible d'avoir des fonctionnalités similaires. Par exemple, un objet BigDate, x est plus grand qu'un autre BigDate, y si les deux dates sont AC et x.original > y.original ou si x.isAC() mais !y.isAC() ou si les deux dates sont BC de telle sorte que soit x.getFullYear() < y.getFullYear() ou x.getFullYear() === y.getFullYear() && x.original > y.original .

Utilisation de BigDate :

var time = new Date (
  [year /*range: 0-239999*/], 
  [month /*range: 0-11*/], 
  [day of month /*range: 1-31*/], 
  [hours /*range: 0-23*/], 
  [minutes /*range: 0-59*/], 
  [a factor of 240,000,000 years to go back (from the first parameter year) /*range: 0-59*/],
  [a factor of 240,000 years to go back (from the first parameter year) /*range: 0-999*/]); 
var bigDate = new BigDate(time);

HTML

<span id="years"></span>
<span id="months"></span>
<span id="date"></span>
<span id="hours"></span>
<span id="minutes"></span>
<span id="acbc"></span>

JAVASCRIPT

function BigDate (date) { this.original = date; }    

// set unchanged methods,
BigDate.prototype.getMinutes = function () { return this.original.getMinutes(); }
BigDate.prototype.getHours = function () { return this.original.getHours(); }
BigDate.prototype.getDate = function () { return this.original.getDate(); }
BigDate.prototype.getMonth = function () { return this.original.getMonth(); }

// implement other BigDate methods..

Et voilà la viande :

// now return non-negative year
BigDate.prototype.getFullYear = function () {  
  var ms = this.original.getSeconds() * 1000 + this.original.getMilliseconds();
  if (ms === 0) return this.original.getFullYear();
  else return (ms * 240000) - this.original.getFullYear();
}

// now add AC/BC method
BigDate.prototype.isAC = function () {
  var result = this.original.getSeconds() === 0 &&
    this.original.getMilliseconds() === 0;
  return result;
}

Certaines démonstrations (peuvent aussi bien être utilisées pour produire de la BigDate.prototype.toString() etc.) :

var years = document.getElementById("years");
var months = document.getElementById("months");
var date = document.getElementById("date");
var hours = document.getElementById("hours");
var minutes = document.getElementById("minutes");
var acbc = document.getElementById("acbc");

// SET A TIME AND PRESENT IT
var time = new Date (2016, 1, 28, 8, 21, 20, 200); 
var bigDate = new BigDate(time);
var monthsName = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
years.innerHTML = bigDate.getFullYear();
months.innerHTML = monthsName[bigDate.getMonth()];    
date.innerHTML = bigDate.getDate();
hours.innerHTML = bigDate.getHours() + ":";
minutes.innerHTML = bigDate.getMinutes();
acbc.innerHTML = (bigDate.isAC()) ? "AC":"BC";

Le contenu résultant serait : 4847996014 Jan 28 8: 21 BC

Voici un JSFiddle .

Clarification

En ce qui concerne les commentaires (justifiés) sur la conception, je suis conscient que la BigDate présenté ci-dessus témoigne d'une interface et d'une conception médiocres. L'objet est présenté uniquement à titre d'exemple de consommer les informations inutilisées des secondes et millisecondes pour satisfaire la question. J'espère que cet exemple vous aidera à comprendre la technique.

31voto

Aaron Points 5138

Si vous n'avez besoin de représenter que des années, un simple nombre peut suffire : il peut représenter jusqu'à +/- 9007199254740991.

Vous pourriez l'intégrer dans une classe personnalisée pour lui fournir des fonctions de date.

18voto

Peteris Points 355

Emballez la date

Créez votre propre classe qui étend la classe Date en ajoutant un champ entier long "décalage d'année".

Mettez à jour toutes les méthodes que vous souhaitez utiliser pour appliquer ce décalage d'année - vous pouvez laisser presque tout en l'état, puisque vous ne touchez pas aux complexités de la gestion de l'heure et des jours ; il vous suffira peut-être même de modifier les constructeurs et les routines de formatage des chaînes pour y inclure "votre" année.

11voto

Rahul Tripathi Points 1

Le site ECMAScript dit :

Un objet Date contient un nombre indiquant un instant particulier dans le temps, à la milliseconde près. à la milliseconde près. Un tel nombre est appelé une valeur temporelle. A valeur temporelle peut aussi être NaN, indiquant que l'objet Date ne représente pas un ne représente pas un instant précis du temps.

Le temps est mesuré en ECMAScript en millisecondes depuis le 01 janvier 1970. UTC. Les secondes intercalaires sont ignorées dans les valeurs de temps. On suppose qu'il y a qu'il y a exactement 86 400 000 millisecondes par jour. Valeurs numériques ECMAScript peuvent représenter tous les nombres entiers compris entre -9 007 199 254 740 992 et -9 007 199 254 740 992. 9,007,199,254,740,992 ; cette plage suffit pour mesurer les temps à la précision de la milliseconde pour tout instant. milliseconde pour tout instant situé à l'intérieur d'une période d'environ 285 616 ans, en avant ou en arrière, à partir du 01 janvier 1970 UTC.

La plage de temps réelle supportée par les objets Date de l'ECMAScript est légèrement plus petite : exactement -100 000 000 jours à 100 000 000 jours mesurés par rapport à minuit au début du 01 janvier 1970. UTC. Cela donne une plage de 8 640 000 000 000 000 000 de millisecondes de part et d'autre du 01 janvier 1970 UTC. de part et d'autre du 01 janvier 1970 UTC.

Le moment exact de minuit au début du 01 janvier 1970 UTC est représenté par la valeur +0.

Vous pouvez donc créer une méthode personnalisée pour les dates où vous pouvez utiliser la valeur entière comme année. Mais d'un point de vue pratique, la plage de dates Ecmascript est suffisante pour contenir toutes les dates pratiques. Celle que vous essayez d'obtenir n'a pas de sens pratique réel, car on ne sait même pas si elle suit les règles de l'art. L'astrologie babylonienne ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X