Ich arbeite an einem Projekt, bei dem das JavaScript-Datum nicht groß genug ist.
Ich möchte mehrere Ereignisse auf derselben Zeitachse platzieren. Einige haben Monat und Tag, andere nicht. Daher ist es nicht möglich, nur das Jahr zu verwenden. Ich möchte in der Lage sein, die Mondlandung und den Urknall auf derselben Achse zu haben.
Es wäre sehr hilfreich, wenn ich die Funktionalität des vorhandenen Date-Objekts nutzen könnte. Es geht nur 270.000 Jahre zurück und ich muss den ganzen Weg zurück zum Urknall (vor 13.800.000.000 Jahren) gehen. Ich brauche die Daten nicht, um Sekunden oder Millisekunden zu enthalten.
Wie kann ich das Date-Objekt um die Darstellung solcher Daten erweitern?
Ich habe versucht, Bibliotheken oder native Funktionen dafür zu finden, aber ohne Glück. Ich suchte auch nach einer JavaScript-Implementierung des Date-Objekts, die ich ändern konnte, aber ich hatte auch hier kein Glück.
Aktualisieren:
Ich habe mit der remdevtec-Lösung angefangen, sie aber ziemlich oft modifiziert. Ich wollte, dass die Daten in numerischer Reihenfolge angezeigt werden, um das Sortieren und Ordnen der Daten zu vereinfachen.
Ich habe also den Millisekundenwert als Stunden behandelt, wenn das Jahr vor -100.000 liegt. Dies ist, was ich bisher bekommen habe, und es funktioniert in unserem Projekt, aber wenn ich mehr Zeit habe, werde ich es aufräumen und auf Github legen.
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;
}
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";
};
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();
};
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();
};
Antworten:
Beachten Sie, dass sich der Gregorianische Kalender in Zyklen von 400 Jahren und damit in Zyklen von 240.000 Jahren bewegt. Daher können Sie die 60000-Millisekunden-Darstellung von
Date
, die Sie nicht verwenden möchten, verwenden, um in 240000-Jahres-Zyklen (bis zu 60000 solcher Zyklen) zurückzukehren. Dies kann Sie zu ungefähr 14,4 Milliarden v. Chr. (Kurz vor Urknall :)) mit winziger Auflösung führen.Das folgende Beispiel berücksichtigt nicht alle Funktionen des Date-Objekts. Ich glaube jedoch, dass es bei weiterer Implementierung möglich ist, ähnliche Funktionen zu haben. Zum Beispiel ist ein BigDate
x
größer als ein anderes BigDate,y
wenn beide DatenAC
undx.original > y.original
oder oderx.isAC()
aber!y.isAC()
sind oder wenn beide Daten so sindBC
, dass entwederx.getFullYear() < y.getFullYear()
oderx.getFullYear() === y.getFullYear() && x.original > y.original
.BigDate-Nutzung:
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..
Und hier kommt das Fleisch:
// 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; }
Einige Demos (können auch zum Produzieren
BigDate.prototype.toString()
usw. verwendet werden):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";
Der resultierende Inhalt wäre:
4847996014 Jan 28 8: 21 BC
Hier ist eine JSFiddle .
Klärung
In Bezug auf (berechtigte) Designkommentare ist mir bewusst, dass das
BigDate
oben dargestellte Objekt eine schlechte Schnittstelle und ein schlechtes Design aufweist. Das Objekt wird nur als Beispiel für den Verbrauch der nicht verwendeten Informationen von Sekunden und Millisekunden dargestellt, um die Frage zu beantworten. Ich hoffe, dieses Beispiel hilft, die Technik zu verstehen.quelle
getSeconds()
Verwendungsvorschlags.BigDate
Instanz, sondern versteckt ihn im umschlossenenDate
Objekt? Außerdem sollten Sie einen nützlichen Konstruktor verfügbar machen, anstatt die Leute mit "Faktoren" herumspielen zu lassen.Date
ohne besonderen Grund in die Sekunden- und Millisekundenfelder des Objekts gestopft wird (ohnehin kein erklärter Grund). Warum nicht den Offset in separate Felder nebeneinander setzenthis.original
? Ganz zu schweigen von zukünftigen großen Daten, die nicht ohne Unterbrechung dargestellt werden könnenisAC()
. Wie von anderen Kommentatoren festgestellt wurde, ist dies ein schlechtes Design und IMO sollte in seinem aktuellen Zustand nicht die am höchsten bewertete / akzeptierte Antwort sein.Wenn Sie nur Jahre darstellen müssen, kann eine einfache Zahl ausreichen: Sie kann bis zu +/- 9007199254740991 darstellen.
Sie können es in eine benutzerdefinierte Klasse einbinden, um Datumsfunktionen bereitzustellen.
quelle
Wickeln Sie das Datum ein
Erstellen Sie eine eigene Klasse, die die Date-Klasse erweitert, indem Sie ein langes Ganzzahlfeld "Jahresversatz" hinzufügen.
Aktualisieren Sie alle Methoden, die Sie zum Anwenden des diesjährigen Versatzes verwenden möchten. Sie können fast alles unverändert lassen, da Sie die Komplexität der Handhabung von Zeit und Tagen nicht berühren. Vielleicht reicht es sogar aus, wenn Sie die Konstruktoren und Zeichenfolgenformatierungsroutinen so ändern, dass "Ihr" Jahr darin enthalten ist.
quelle
Das ECMAScript sagt:
Sie können also eine benutzerdefinierte Methode für Datumsangaben erstellen, bei der Sie den ganzzahligen Wert als Jahr verwenden können. Praktisch gesehen ist der Ecmascript-Bereich für Daten jedoch gut genug, um alle praktischen Daten aufzunehmen. Derjenige, den Sie erreichen möchten, ergibt keinen wirklichen praktischen Sinn / Sinn, da selbst einer nicht sicher ist, ob er der babylonischen Astrologie folgt ?
quelle