Wie berechne ich mit Javascript den Tag des Jahres von 1 bis 366? Beispielsweise:
- Der 3. Januar sollte der 3. Januar sein .
- Der 1. Februar sollte 32 sein .
Wie berechne ich mit Javascript den Tag des Jahres von 1 bis 366? Beispielsweise:
Antworten:
Folgende OP-Bearbeitung:
var now = new Date();
var start = new Date(now.getFullYear(), 0, 0);
var diff = now - start;
var oneDay = 1000 * 60 * 60 * 24;
var day = Math.floor(diff / oneDay);
console.log('Day of year: ' + day);
Bearbeiten: Der obige Code schlägt fehl, wenn nowein Datum zwischen dem 26. März und dem 29. Oktober liegt und nowdie Zeit vor 1 Uhr morgens liegt (z. B. 00:59:59). Dies liegt daran, dass der Code die Sommerzeit nicht berücksichtigt. Sie sollten dies kompensieren :
var now = new Date();
var start = new Date(now.getFullYear(), 0, 0);
var diff = (now - start) + ((start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000);
var oneDay = 1000 * 60 * 60 * 24;
var day = Math.floor(diff / oneDay);
console.log('Day of year: ' + day);
Math.floorgab mir durchweg ein Ergebnis von 1 Tag weniger als erwartet nach einem bestimmten Tag im April. Math.ceilhat wie erwartet funktioniert, aber ich habe gesehen, dass empfohlen wird, dass Sie Math.roundanstelle von beiden verwenden.
new Date(2014, 0, 1), und nicht new Date(2014, 0, 0)wie Sie hier haben. Ist das beabsichtigt? Vielleicht ist es das, was dafür verantwortlich ist, dass wir eines Tages frei sind und new Date(2014, 0, 0)zurückkehren werden 12/31/2013.
.setUTCHoursund Date.UTC()für eine zuverlässigere Lösung.
ceilanstatt floor, dies gibt Ihnen ein Nummerierungssystem, bei dem der 1. Januar = 1. Wenn Sie den 1. Januar = 0 möchten (wie floores Ihnen geben würde), subtrahieren Sie einfach 1 von Ihrem Endergebnis.
var diff = now - start + (start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000;
Dies funktioniert bei Änderungen der Sommerzeit in allen Ländern (der oben genannte "Mittag" funktioniert in Australien nicht):
Date.prototype.isLeapYear = function() {
var year = this.getFullYear();
if((year & 3) != 0) return false;
return ((year % 100) != 0 || (year % 400) == 0);
};
// Get Day of Year
Date.prototype.getDOY = function() {
var dayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
var mn = this.getMonth();
var dn = this.getDate();
var dayOfYear = dayCount[mn] + dn;
if(mn > 1 && this.isLeapYear()) dayOfYear++;
return dayOfYear;
};
getDay()muss in geändert werden getDate(). Ersteres gibt den Wochentag zurück (0 = Sonntag..6 = Samstag), nicht den Tag.
Ich finde es sehr interessant, dass niemand UTC in Betracht gezogen hat, da es nicht der Sommerzeit unterliegt. Daher schlage ich Folgendes vor:
function daysIntoYear(date){
return (Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - Date.UTC(date.getFullYear(), 0, 0)) / 24 / 60 / 60 / 1000;
}
Sie können es folgendermaßen testen:
[new Date(2016,0,1), new Date(2016,1,1), new Date(2016,2,1), new Date(2016,5,1), new Date(2016,11,31)]
.forEach(d =>
console.log(`${d.toLocaleDateString()} is ${daysIntoYear(d)} days into the year`));
Welche Ergebnisse für das Schaltjahr 2016 (überprüft mit http://www.epochconverter.com/days/2016 ):
1/1/2016 is 1 days into the year
2/1/2016 is 32 days into the year
3/1/2016 is 61 days into the year
6/1/2016 is 153 days into the year
12/31/2016 is 366 days into the year
function doyToDate(doy, year) { return new Date(year, 0, doy); }
Date.prototype.dayOfYear= function(){
var j1= new Date(this);
j1.setMonth(0, 0);
return Math.round((this-j1)/8.64e7);
}
alert(new Date().dayOfYear())
Glücklicherweise gibt diese Frage nicht an, ob die Nummer des aktuellen Tages erforderlich ist, sodass Platz für diese Antwort bleibt.
Auch einige Antworten (auch auf andere Fragen) hatten Schaltjahrprobleme oder verwendeten das Date-Objekt. Obwohl die javascript Date objectetwa 285.616 Jahre Abdeckungen (100.000.000 Tage) auf beiden Seiten vom 1. Januar 1970 wurde ich mit allen möglichen unerwarteten Zeitpunkt satt Inkonsistenzen in verschiedenen Browsern (insbesondere die Jahre 0 bis 99). Ich war auch neugierig, wie man es berechnet.
So habe ich eine einfache und vor allem schrieb kleinen Algorithmus zur Berechnung der korrekten ( proleptische Gregorian / astronomisches / ISO 8601: 2004 (Abschnitt 4.3.2.1), so Jahr0 existiert und ein Schaltjahr und Tag des Jahres negative Jahre unterstützt werden ) basierend auf Jahr , Monat und Tag .
Beachten Sie, dass in der AD/BCNotation das Jahr 0 AD / BC nicht existiert: Stattdessen 1 BCist das Jahr das Schaltjahr! WENN Sie die BC-Notation berücksichtigen müssen, subtrahieren Sie einfach zuerst ein Jahr vom (ansonsten positiven) Jahreswert !!
Ich habe (für Javascript) den Kurzschluss-Bitmasken-Modulo-Schaltjahr-Algorithmus modifiziert und mir eine magische Zahl ausgedacht , um eine bitweise Suche nach Offsets durchzuführen (ohne Jan und Februar, sodass 10 * 3 Bits benötigt werden (30 Bits sind weniger als) 31 Bit, damit wir sicher ein anderes Zeichen in der Bitverschiebung speichern können, anstatt >>>)).
Beachten Sie, dass weder Monat noch Tag sein dürfen 0. Das bedeutet , dass , wenn Sie diese Gleichung müssen nur für den aktuellen Tag (Fütterung es mit .getMonth()) brauchen Sie nur das entfernen --aus --m.
Beachten Sie, dass dies ein gültiges Datum voraussetzt (obwohl die Fehlerprüfung nur einige Zeichen mehr ist).
function dayNo(y,m,d){
return --m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+d;
}
<!-- some examples for the snippet -->
<input type=text value="(-)Y-M-D" onblur="
var d=this.value.match(/(-?\d+)[^\d]+(\d\d?)[^\d]+(\d\d?)/)||[];
this.nextSibling.innerHTML=' Day: ' + dayNo(+d[1], +d[2], +d[3]);
" /><span></span>
<br><hr><br>
<button onclick="
var d=new Date();
this.nextSibling.innerHTML=dayNo(d.getFullYear(), d.getMonth()+1, d.getDate()) + ' Day(s)';
">get current dayno:</button><span></span>
Hier ist die Version mit korrekter Bereichsvalidierung.
function dayNo(y,m,d){
return --m>=0 && m<12 && d>0 && d<29+(
4*(y=y&3||!(y%25)&&y&15?0:1)+15662003>>m*2&3
) && m*31-(m>1?(1054267675>>m*3-6&7)-y:0)+d;
}
<!-- some examples for the snippet -->
<input type=text value="(-)Y-M-D" onblur="
var d=this.value.match(/(-?\d+)[^\d]+(\d\d?)[^\d]+(\d\d?)/)||[];
this.nextSibling.innerHTML=' Day: ' + dayNo(+d[1], +d[2], +d[3]);
" /><span></span>
Wieder eine Zeile, aber ich habe sie zur besseren Lesbarkeit (und folgenden Erläuterungen) in drei Zeilen aufgeteilt.
Die letzte Zeile ist identisch mit der obigen Funktion, jedoch wird der (identische) Schaltjahr-Algorithmus in einen vorherigen Kurzschlussabschnitt (vor der Berechnung der Tageszahl) verschoben, da auch bekannt sein muss, wie viele Tage ein Monat in einem hat gegebenes (Schalt-) Jahr.
Die mittlere Zeile berechnet die korrekte Versatzzahl (für die maximale Anzahl von Tagen) für einen bestimmten Monat in einem bestimmten (Schalt-) Jahr unter Verwendung einer anderen magischen Zahl: Da 31-28=3und 3nur 2 Bits und dann 12*2=24Bits sind, können wir alle 12 Monate speichern. Da die Addition schneller als die Subtraktion sein kann, addieren wir den Offset (anstatt ihn zu subtrahieren 31). Um einen Schaltjahr-Entscheidungszweig für Februar zu vermeiden, ändern wir diese magische Suchnummer im laufenden Betrieb.
Damit bleibt uns die (ziemlich offensichtliche) erste Zeile: Sie überprüft, ob Monat und Datum innerhalb der gültigen Grenzen liegen, und stellt sicher, dass bei einem falseBereichsfehler ein Rückgabewert angezeigt wird (beachten Sie, dass diese Funktion auch 0 nicht zurückgeben kann, da 1 Januar 0000 ist noch Tag 1.) und bietet eine einfache Fehlerprüfung : if(r=dayNo(/*y, m, d*/)){}.
Wenn auf diese Weise verwendet werden (wo Monat und Tag können nicht sein 0), dann kann man ändern , --m>=0 && m<12um m>0 && --m<12(Speicher ein anderes Zeichen).
Der Grund , warum ich das Snippet getippt in seiner derzeitigen Form ist , dass für die Monatswerte-0 basiert, man muss nur das Entfernen --von--m .
Extra:
Beachten Sie, dass Sie den Algorithmus für diesen Tag pro Monat nicht verwenden, wenn Sie nur den maximalen Tag pro Monat benötigen. In diesem Fall gibt es einen effizienteren Algorithmus (da wir nur leepYear benötigen, wenn der Monat Februar ist). Als Antwort auf diese Frage habe ich Folgendes gepostet: Wie lässt sich die Anzahl der Tage in einem Monat am besten mit Javascript bestimmen? .
Date.prototype.dayNo = function(){ var y = this.getFullYear(); var m = this.getMonth()+1; var d = this.getDate(); return --m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+d; };
+1aus , this.getMonth()+1wenn Sie entfernen die --aus --m. EDIT Also, ich würde (für eine Bibliothek) tun:Date.prototype.dayNo = function(){ var y=this.getFullYear(), m=this.getMonth(); return m*31-(m>1?(1054267675>>m*3-6&7)-(y&3||!(y%25)&&y&15?0:1):0)+this.getDate(); };
2^31 - 2016js in den nächsten Jahren wahrscheinlich etwas veraltet sein wird.
:)Aber bis dahin wird es zumindest vorhersehbare und konsistente Ergebnisse liefern, haha. EDIT , nur aus theoretischen Gründen, mit dem langsameren konventionellen All-Modulo-Algo für Leapyear kann der Bereich auf 2 ^ 53 erweitert werden. Der Monatssuchalgo ist nicht der begrenzende Faktor.
Wenn Sie das Rad nicht neu erfinden möchten, können Sie die hervorragende Bibliothek date-fns (node.js) verwenden:
var getDayOfYear = require('date-fns/get_day_of_year')
var dayOfYear = getDayOfYear(new Date(2017, 1, 1)) // 1st february => 32
Nun, wenn ich Sie richtig verstehe, wollen Sie 366 in einem Schaltjahr, sonst 365, oder? Ein Jahr ist ein Schaltjahr, wenn es gleichmäßig durch 4 teilbar ist, aber nicht durch 100, es sei denn, es ist auch durch 400 teilbar:
function daysInYear(year) {
if(year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) {
// Leap year
return 366;
} else {
// Not a leap year
return 365;
}
}
In diesem Fall glaube ich nicht, dass es eine eingebaute Methode gibt. Sie müssen dies tun:
function daysInFebruary(year) {
if(year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) {
// Leap year
return 29;
} else {
// Not a leap year
return 28;
}
}
function dateToDay(date) {
var feb = daysInFebruary(date.getFullYear());
var aggregateMonths = [0, // January
31, // February
31 + feb, // March
31 + feb + 31, // April
31 + feb + 31 + 30, // May
31 + feb + 31 + 30 + 31, // June
31 + feb + 31 + 30 + 31 + 30, // July
31 + feb + 31 + 30 + 31 + 30 + 31, // August
31 + feb + 31 + 30 + 31 + 30 + 31 + 31, // September
31 + feb + 31 + 30 + 31 + 30 + 31 + 31 + 30, // October
31 + feb + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, // November
31 + feb + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, // December
];
return aggregateMonths[date.getMonth()] + date.getDate();
}
(Ja, das habe ich tatsächlich gemacht, ohne zu kopieren oder einzufügen. Wenn es einen einfachen Weg gibt, werde ich verrückt sein.)
:)
Dies ist eine einfache Methode, um den aktuellen Tag im Jahr zu ermitteln, und es sollten problemlos Schaltjahre berücksichtigt werden:
Javascript:
Math.round((new Date().setHours(23) - new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0))/1000/60/60/24);
Javascript in Google Apps Script:
Math.round((new Date().setHours(23) - new Date(new Date().getYear(), 0, 1, 0, 0, 0))/1000/60/60/24);
Die Hauptaktion dieses Codes besteht darin, die Anzahl der im aktuellen Jahr verstrichenen Millisekunden zu ermitteln und diese Zahl dann in Tage umzuwandeln. Die Anzahl der im aktuellen Jahr verstrichenen Millisekunden kann ermittelt werden, indem die Anzahl der Millisekunden der ersten Sekunde des ersten Tages des aktuellen Jahres, die mit new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0)(Javascript) oder new Date(new Date().getYear(), 0, 1, 0, 0, 0)(Google Apps Script) ermittelt wurde, von den Millisekunden abgezogen wird der 23. Stunde des aktuellen Tages, die mit gefunden wurde new Date().setHours(23). Mit der Einstellung des aktuellen Datums auf die 23. Stunde soll sichergestellt werden, dass der Tag des Jahres korrekt gerundet wird Math.round().
Sobald Sie die Anzahl der Millisekunden des aktuellen Jahres haben, können Sie diese Zeit in Tage umrechnen, indem Sie durch 1000 dividieren, um Millisekunden in Sekunden umzuwandeln, dann durch 60 teilen, um Sekunden in Minuten umzuwandeln, und dann durch 60 teilen, um Minuten in Stunden umzurechnen. und schließlich durch 24 teilen, um Stunden in Tage umzuwandeln.
Hinweis: Dieser Beitrag wurde bearbeitet, um Unterschiede zwischen JavaScript und JavaScript zu berücksichtigen, die in Google Apps Script implementiert sind. Außerdem wurde mehr Kontext für die Antwort hinzugefügt.
.setHoursMethode für das erste Datumsobjekt verwendet und die Uhrzeit mit dem zweiten Datumsobjekt angegeben habe, wirkt sich eine Änderung von 1 Stunde gegenüber der Sommerzeit nicht auf die Zeiten der in dieser Berechnung verwendeten Datumsobjekte aus.
Ich denke, das ist einfacher:
var date365 = 0;
var currentDate = new Date();
var currentYear = currentDate.getFullYear();
var currentMonth = currentDate.getMonth();
var currentDay = currentDate.getDate();
var monthLength = [31,28,31,30,31,30,31,31,30,31,30,31];
var leapYear = new Date(currentYear, 1, 29);
if (leapYear.getDate() == 29) { // If it's a leap year, changes 28 to 29
monthLength[1] = 29;
}
for ( i=0; i < currentMonth; i++ ) {
date365 = date365 + monthLength[i];
}
date365 = date365 + currentDay; // Done!
Diese Methode berücksichtigt Zeitzonenprobleme und Sommerzeit
function dayofyear(d) { // d is a Date object
var yn = d.getFullYear();
var mn = d.getMonth();
var dn = d.getDate();
var d1 = new Date(yn,0,1,12,0,0); // noon on Jan. 1
var d2 = new Date(yn,mn,dn,12,0,0); // noon on input date
var ddiff = Math.round((d2-d1)/864e5);
return ddiff+1;
}
(nahm von hier )
Siehe auch diese Geige
Math.round ((neues Datum (). SetHours (23) - neues Datum (neues Datum (). GetFullYear (), 0, 1, 0, 0, 0)) / 1000/86400);
optimiert die Antwort weiter.
Darüber hinaus kann durch Ändern von setHours (23) oder der vorletzten Null später auf einen anderen Wert ein Tag des Jahres in Bezug auf eine andere Zeitzone bereitgestellt werden. Zum Beispiel, um eine in Amerika befindliche Ressource aus Europa abzurufen.
Math.floor((Date.now() - Date.parse(new Date().getFullYear(), 0, 0)) / 86400000)
Das ist meine Lösung
Ich habe eine lesbare erstellt, die den Trick sehr schnell erledigt und JS-Datumsobjekte mit unterschiedlichen Zeitzonen verarbeitet.
Ich habe einige Testfälle für Zeitzonen, Sommerzeit, Schaltsekunden und Schaltjahre aufgenommen.
PS ECMA-262 ignoriert im Gegensatz zu UTC Schaltsekunden. Wenn Sie dies in eine Sprache konvertieren, die echte UTC verwendet, können Sie einfach 1 hinzufügen oneDay.
// returns 1 - 366
findDayOfYear = function (date) {
var oneDay = 1000 * 60 * 60 * 24; // A day in milliseconds
var og = { // Saving original data
ts: date.getTime(),
dom: date.getDate(), // We don't need to save hours/minutes because DST is never at 12am.
month: date.getMonth()
}
date.setDate(1); // Sets Date of the Month to the 1st.
date.setMonth(0); // Months are zero based in JS's Date object
var start_ts = date.getTime(); // New Year's Midnight JS Timestamp
var diff = og.ts - start_ts;
date.setDate(og.dom); // Revert back to original date object
date.setMonth(og.month); // This method does preserve timezone
return Math.round(diff / oneDay) + 1; // Deals with DST globally. Ceil fails in Australia. Floor Fails in US.
}
// Tests
var pre_start_dst = new Date(2016, 2, 12);
var on_start_dst = new Date(2016, 2, 13);
var post_start_dst = new Date(2016, 2, 14);
var pre_end_dst_date = new Date(2016, 10, 5);
var on_end_dst_date = new Date(2016, 10, 6);
var post_end_dst_date = new Date(2016, 10, 7);
var pre_leap_second = new Date(2015, 5, 29);
var on_leap_second = new Date(2015, 5, 30);
var post_leap_second = new Date(2015, 6, 1);
// 2012 was a leap year with a leap second in june 30th
var leap_second_december31_premidnight = new Date(2012, 11, 31, 23, 59, 59, 999);
var january1 = new Date(2016, 0, 1);
var january31 = new Date(2016, 0, 31);
var december31 = new Date(2015, 11, 31);
var leap_december31 = new Date(2016, 11, 31);
alert( ""
+ "\nPre Start DST: " + findDayOfYear(pre_start_dst) + " === 72"
+ "\nOn Start DST: " + findDayOfYear(on_start_dst) + " === 73"
+ "\nPost Start DST: " + findDayOfYear(post_start_dst) + " === 74"
+ "\nPre Leap Second: " + findDayOfYear(pre_leap_second) + " === 180"
+ "\nOn Leap Second: " + findDayOfYear(on_leap_second) + " === 181"
+ "\nPost Leap Second: " + findDayOfYear(post_leap_second) + " === 182"
+ "\nPre End DST: " + findDayOfYear(pre_end_dst_date) + " === 310"
+ "\nOn End DST: " + findDayOfYear(on_end_dst_date) + " === 311"
+ "\nPost End DST: " + findDayOfYear(post_end_dst_date) + " === 312"
+ "\nJanuary 1st: " + findDayOfYear(january1) + " === 1"
+ "\nJanuary 31st: " + findDayOfYear(january31) + " === 31"
+ "\nNormal December 31st: " + findDayOfYear(december31) + " === 365"
+ "\nLeap December 31st: " + findDayOfYear(leap_december31) + " === 366"
+ "\nLast Second of Double Leap: " + findDayOfYear(leap_second_december31_premidnight) + " === 366"
);
Ich möchte eine Lösung bereitstellen, die Berechnungen durchführt und die Tage für jeden vorherigen Monat hinzufügt:
function getDayOfYear(date) {
var month = date.getMonth();
var year = date.getFullYear();
var days = date.getDate();
for (var i = 0; i < month; i++) {
days += new Date(year, i+1, 0).getDate();
}
return days;
}
var input = new Date(2017, 7, 5);
console.log(input);
console.log(getDayOfYear(input));
Auf diese Weise müssen Sie die Details der Schaltjahre und der Sommerzeit nicht verwalten.
Eine Alternative mit UTC-Zeitstempeln. Wie andere angemerkt haben, ist der Tag, an dem der 1. Monat angezeigt wird, 1 statt 0. Der Monat beginnt jedoch bei 0.
var now = Date.now();
var year = new Date().getUTCFullYear();
var year_start = Date.UTC(year, 0, 1);
var day_length_in_ms = 1000*60*60*24;
var day_number = Math.floor((now - year_start)/day_length_in_ms)
console.log("Day of year " + day_number);
Sie können Parameter als Datumsnummer in der setDateFunktion übergeben:
var targetDate = new Date();
targetDate.setDate(1);
// Now we can see the expected date as: Mon Jan 01 2018 01:43:24
console.log(targetDate);
targetDate.setDate(365);
// You can see: Mon Dec 31 2018 01:44:47
console.log(targetDate)
Dies kann für diejenigen nützlich sein, die den Tag des Jahres als Zeichenfolge benötigen und über eine jQuery-Benutzeroberfläche verfügen.
Sie können jQuery UI Datepicker verwenden:
day_of_year_string = $.datepicker.formatDate("o", new Date())
Darunter funktioniert es genauso wie bei einigen der bereits erwähnten Antworten ( (date_ms - first_date_of_year_ms) / ms_per_day):
function getDayOfTheYearFromDate(d) {
return Math.round((new Date(d.getFullYear(), d.getMonth(), d.getDate()).getTime()
- new Date(d.getFullYear(), 0, 0).getTime()) / 86400000);
}
day_of_year_int = getDayOfTheYearFromDate(new Date())
Für diejenigen unter uns, die eine schnelle alternative Lösung suchen.
(function(){"use strict";
function daysIntoTheYear(dateInput){
var fullYear = dateInput.getFullYear()|0;
// "Leap Years are any year that can be exactly divided by 4 (2012, 2016, etc)
// except if it can be exactly divided by 100, then it isn't (2100, 2200, etc)
// except if it can be exactly divided by 400, then it is (2000, 2400)"
// (https://www.mathsisfun.com/leap-years.html).
var isLeapYear = ((fullYear & 3) | (fullYear/100 & 3)) === 0 ? 1 : 0;
// (fullYear & 3) = (fullYear % 4), but faster
//Alternative:var isLeapYear=(new Date(currentYear,1,29,12)).getDate()===29?1:0
var fullMonth = dateInput.getMonth()|0;
return ((
// Calculate the day of the year in the Gregorian calendar
// The code below works based upon the facts of signed right shifts
// • (x) >> n: shifts n and fills in the n highest bits with 0s
// • (-x) >> n: shifts n and fills in the n highest bits with 1s
// (This assumes that x is a positive integer)
(31 & ((-fullMonth) >> 4)) + // January // (-11)>>4 = -1
((28 + isLeapYear) & ((1-fullMonth) >> 4)) + // February
(31 & ((2-fullMonth) >> 4)) + // March
(30 & ((3-fullMonth) >> 4)) + // April
(31 & ((4-fullMonth) >> 4)) + // May
(30 & ((5-fullMonth) >> 4)) + // June
(31 & ((6-fullMonth) >> 4)) + // July
(31 & ((7-fullMonth) >> 4)) + // August
(30 & ((8-fullMonth) >> 4)) + // September
(31 & ((9-fullMonth) >> 4)) + // October
(30 & ((10-fullMonth) >> 4)) + // November
// There are no months past December: the year rolls into the next.
// Thus, fullMonth is 0-based, so it will never be 12 in Javascript
(dateInput.getDate()|0) // get day of the month
)&0xffff);
}
// Demonstration:
var date = new Date(2100, 0, 1)
for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0))
console.log(date.getMonth()+":\tday "+daysIntoTheYear(date)+"\t"+date);
date = new Date(1900, 0, 1);
for (var i=0; i<12; i=i+1|0, date.setMonth(date.getMonth()+1|0))
console.log(date.getMonth()+":\tday "+daysIntoTheYear(date)+"\t"+date);
// Performance Benchmark:
console.time("Speed of processing 65536 dates");
for (var i=0,month=date.getMonth()|0; i<65536; i=i+1|0)
date.setMonth(month=month+1+(daysIntoTheYear(date)|0)|0);
console.timeEnd("Speed of processing 65536 dates");
})();
Die Größe der Monate des Jahres und die Art und Weise, wie Schaltjahre funktionieren, passen perfekt dazu, unsere Zeit mit der Sonne in Einklang zu halten. Heck, es funktioniert so perfekt, dass wir nur hier und da nur Sekunden einstellen . Unser derzeitiges System der Schaltjahre ist seit dem 24. Februar 1582 in Kraft in Kraft und wird wahrscheinlich auf absehbare Zeit in Kraft bleiben.
Die Sommerzeit kann sich jedoch stark ändern. Es kann sein, dass in 20 Jahren ein Land die Zeit um einen ganzen Tag oder ein anderes Extrem für die Sommerzeit ausgleicht. Ein ganzer DST-Tag wird mit ziemlicher Sicherheit nie stattfinden, aber die DST ist dennoch sehr in der Luft und unentschlossen. Somit ist die obige Lösung nicht nur sehr, sehr schnell, sondern auch zukunftssicher.
Das obige Code-Snippet läuft sehr schnell. Mein Computer kann 65536 Daten in ~ 52 ms in Chrome verarbeiten.
const dayOfYear = date => {
const myDate = new Date(date);
const year = myDate.getFullYear();
const firstJan = new Date(year, 0, 1);
const differenceInMillieSeconds = myDate - firstJan;
return (differenceInMillieSeconds / (1000 * 60 * 60 * 24) + 1);
};
const result = dayOfYear("2019-2-01");
console.log(result);
Dies ist eine Lösung, die die problematischen Probleme mit Datumsobjekten und Zeitzonen vermeidet. Es ist erforderlich, dass Ihr Eingabedatum das Format "JJJJ-TT-MM" hat. Wenn Sie das Format ändern möchten, ändern Sie die Funktion date_str_to_parts:
function get_day_of_year(str_date){
var date_parts = date_str_to_parts(str_date);
var is_leap = (date_parts.year%4)==0;
var acct_for_leap = (is_leap && date_parts.month>2);
var day_of_year = 0;
var ary_months = [
0,
31, //jan
28, //feb(non leap)
31, //march
30, //april
31, //may
30, //june
31, //july
31, //aug
30, //sep
31, //oct
30, //nov
31 //dec
];
for(var i=1; i < date_parts.month; i++){
day_of_year += ary_months[i];
}
day_of_year += date_parts.date;
if( acct_for_leap ) day_of_year+=1;
return day_of_year;
}
function date_str_to_parts(str_date){
return {
"year":parseInt(str_date.substr(0,4),10),
"month":parseInt(str_date.substr(5,2),10),
"date":parseInt(str_date.substr(8,2),10)
}
}
Ich mache mir immer Sorgen, wenn ich Mathematik mit Datumsfunktionen mische (es ist so leicht, ein Schaltjahr und andere Details zu übersehen). Angenommen, Sie haben:
var d = new Date();
Ich würde vorschlagen, Folgendes zu verwenden: Tage werden gespeichert in day:
for(var day = d.getDate(); d.getMonth(); day += d.getDate())
d.setDate(0);
Ich kann keinen Grund erkennen, warum dies nicht gut funktionieren würde (und ich wäre nicht so besorgt über die wenigen Iterationen, da dies nicht so intensiv genutzt wird).
/ * BENUTZEN SIE DIESES SCRIPT * /
var today = new Date();
var first = new Date(today.getFullYear(), 0, 1);
var theDay = Math.round(((today - first) / 1000 / 60 / 60 / 24) + .5, 0);
alert("Today is the " + theDay + (theDay == 1 ? "st" : (theDay == 2 ? "nd" : (theDay == 3 ? "rd" : "th"))) + " day of the year");
var days = new Date().getFullYear() % 4 == 0 ? 366 : 365;