Bagaimana cara menggunakan javascript untuk menghitung hari dalam setahun, dari 1 - 366? Sebagai contoh:
- 3 Jan harus 3 .
- 1 Februari seharusnya 32 tahun .
Bagaimana cara menggunakan javascript untuk menghitung hari dalam setahun, dari 1 - 366? Sebagai contoh:
Jawaban:
Mengikuti hasil edit OP:
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);
Sunting: Kode di atas akan gagal jika nowtanggal antara 26 Maret dan 29 Oktober dan nowwaktu sebelum 1AM (mis. 00:59:59). Hal ini karena kode tidak memperhitungkan waktu musim panas. Anda harus mengkompensasi ini:
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.floorsecara konsisten memberi saya hasil 1 hari lebih sedikit dari yang diharapkan setelah hari tertentu di bulan April. Math.ceilbekerja seperti yang diharapkan, tetapi saya telah melihat disarankan agar Anda menggunakan Math.rounddaripada keduanya.
new Date(2014, 0, 1), dan bukan new Date(2014, 0, 0)seperti yang Anda miliki di sini. Apakah itu disengaja? Mungkin itulah yang menyebabkan libur satu hari dan new Date(2014, 0, 0)akan kembali 12/31/2013.
.setUTCHoursdan Date.UTC()untuk solusi yang lebih andal.
ceildaripada floor, ini akan memberi Anda sistem penomoran di mana 1 Jan = 1. Jika Anda ingin 1 Jan = 0 (seperti yang floorakan Anda berikan), kurangi 1 dari hasil akhir Anda.
var diff = now - start + (start.getTimezoneOffset() - now.getTimezoneOffset()) * 60 * 1000;
Ini berfungsi di seluruh perubahan Waktu Musim Panas di semua negara ("siang" di atas tidak berfungsi di Australia):
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()perlu diubah menjadi getDate(). Yang pertama mengembalikan hari dalam seminggu (0 = Sunday..6 = Sabtu), bukan hari.
Saya merasa sangat menarik bahwa tidak ada yang mempertimbangkan untuk menggunakan UTC karena tidak tunduk pada DST. Oleh karena itu, saya mengusulkan yang berikut:
function daysIntoYear(date){
return (Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()) - Date.UTC(date.getFullYear(), 0, 0)) / 24 / 60 / 60 / 1000;
}
Anda dapat mengujinya dengan yang berikut:
[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`));
Keluaran mana untuk tahun kabisat 2016 (diverifikasi menggunakan 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); }
new Date(8640000000000000), yang masih kurang dari Number.MAX_SAFE_INTEGER. lihat jawaban ini: stackoverflow.com/a/11526569/18511
Date.prototype.dayOfYear= function(){
var j1= new Date(this);
j1.setMonth(0, 0);
return Math.round((this-j1)/8.64e7);
}
alert(new Date().dayOfYear())
Untungnya pertanyaan ini tidak menentukan jika jumlah yang saat ini hari diperlukan, meninggalkan ruang untuk jawaban ini.
Juga beberapa jawaban (juga pada pertanyaan lain) memiliki masalah tahun kabisat atau menggunakan objek Tanggal. Meskipun javascript Date objectmencakup kira-kira 285616 tahun (100.000.000 hari) di kedua sisi tanggal 1 Januari 1970, saya muak dengan semua jenis inkonsistensi tanggal yang tidak terduga di berbagai browser (terutama tahun 0 hingga 99). Saya juga penasaran bagaimana cara menghitungnya.
Jadi saya menulis yang sederhana dan di atas segalanya, algoritma kecil untuk menghitung hari yang benar ( Proleptic Gregorian / Astronomical / ISO 8601: 2004 (klausul 4.3.2.1), jadi tahun0 ada dan merupakan tahun kabisat dan tahun negatif didukung ) hari dalam setahun berdasarkan tahun , bulan dan hari .
Perhatikan bahwa dalam AD/BCnotasi, tahun 0 M / SM tidak ada: sebagai gantinya tahun 1 BCadalah tahun kabisat! JIKA Anda perlu menghitung notasi BC maka kurangi satu tahun dari nilai tahun (jika tidak positif) dulu !!
Saya memodifikasi (untuk javascript) algoritma bitmask-modulo leapYear sirkuit pendek dan menghasilkan angka ajaib untuk melakukan pencarian offset bit-bijaksana (yang tidak termasuk jan dan feb, sehingga membutuhkan 10 * 3 bit (30 bit kurang dari 31 bit, jadi kita dapat dengan aman menyimpan karakter lain di bitshift alih-alih >>>)).
Perhatikan bahwa tidak ada bulan atau hari yang mungkin 0. Itu berarti bahwa jika Anda perlu persamaan ini hanya untuk saat hari (makan menggunakan .getMonth()) Anda hanya perlu untuk menghapus --dari --m.
Perhatikan bahwa ini mengasumsikan tanggal yang valid (meskipun pengecekan kesalahan hanya beberapa karakter lagi).
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>
Ini adalah versi dengan validasi rentang yang benar .
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>
Sekali lagi, satu baris, tetapi saya membaginya menjadi 3 baris agar mudah dibaca (dan penjelasan berikut).
Baris terakhir identik dengan fungsi di atas, namun algoritma leapYear (identik) dipindahkan ke bagian hubung singkat sebelumnya (sebelum penghitungan angka hari), karena diperlukan juga untuk mengetahui berapa hari dalam sebulan dalam diberikan tahun (kabisat).
Garis tengah menghitung jumlah offset yang benar (untuk jumlah hari maksimum) untuk bulan tertentu dalam tahun (kabisat) tertentu menggunakan angka ajaib lain: karena 31-28=3dan 3hanya 2 bit, maka 12*2=24bit, kita dapat menyimpan semua 12 bulan. Karena penjumlahan bisa lebih cepat daripada pengurangan, kami menambahkan offset (bukan menguranginya 31). Untuk menghindari cabang keputusan tahun kabisat untuk bulan Februari, kami memodifikasi nomor pencarian ajaib itu dengan cepat.
Itu membuat kita dengan baris pertama (cukup jelas): ia memeriksa bahwa bulan dan tanggal berada dalam batas yang valid dan memastikan kita dengan falsenilai yang dikembalikan pada kesalahan rentang (perhatikan bahwa fungsi ini juga tidak dapat mengembalikan 0, karena 1 jan 0000 masih hari 1.), menyediakan mudah pengecekan error: if(r=dayNo(/*y, m, d*/)){}.
Jika digunakan dengan cara ini (di mana bulan dan hari mungkin tidak 0), maka seseorang dapat mengubahnya --m>=0 && m<12menjadi m>0 && --m<12(menyimpan karakter lain).
Alasan saya mengetik potongan dalam bentuknya saat ini adalah karena untuk nilai bulan berbasis 0, seseorang hanya perlu menghapus --dari --m.
Ekstra:
Catatan, jangan gunakan algoritme hari per bulan ini jika Anda hanya membutuhkan maksimal hari per bulan. Dalam hal ini ada algoritma yang lebih efisien (karena kita hanya perlu leepTahun ketika bulan Februari) saya posting sebagai jawaban pertanyaan ini: Apa cara terbaik untuk menentukan jumlah hari dalam sebulan dengan javascript? .
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; };
+1dari this.getMonth()+1jika Anda menghapus --dari --m. EDIT Jadi, saya akan melakukan (untuk perpustakaan):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 - 2016tahun - tahun dari sekarang js mungkin akan sedikit ketinggalan jaman.
:)Tapi sampai saat itu, setidaknya akan memberikan hasil yang dapat diprediksi dan konsisten haha. EDIT , hanya demi teori, menggunakan algo all-modulo konvensional yang lebih lambat untuk leapyear, kisaran dapat diperpanjang hingga 2 ^ 53. Algo pencarian bulan bukanlah faktor pembatas.
Jika Anda tidak ingin menemukan kembali roda, Anda dapat menggunakan pustaka tanggal-fns (node.js) yang sangat baik:
var getDayOfYear = require('date-fns/get_day_of_year')
var dayOfYear = getDayOfYear(new Date(2017, 1, 1)) // 1st february => 32
Nah, jika saya mengerti Anda dengan benar, Anda menginginkan 366 pada tahun kabisat, 365 sebaliknya, bukan? Setahun adalah tahun kabisat jika habis dibagi 4 tetapi tidak habis dibagi 100 kecuali habis dibagi 400:
function daysInYear(year) {
if(year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0)) {
// Leap year
return 366;
} else {
// Not a leap year
return 365;
}
}
Dalam hal ini, menurut saya tidak ada metode bawaan; Anda harus melakukan ini:
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();
}
(Ya, saya benar-benar melakukannya tanpa menyalin atau menempel. Jika ada cara mudah saya akan marah)
:)
Ini adalah cara sederhana untuk menemukan hari saat ini dalam satu tahun, dan harus memperhitungkan tahun kabisat tanpa masalah:
Javascript:
Math.round((new Date().setHours(23) - new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0))/1000/60/60/24);
Javascript di Google Apps Script:
Math.round((new Date().setHours(23) - new Date(new Date().getYear(), 0, 1, 0, 0, 0))/1000/60/60/24);
Tindakan utama dari kode ini adalah menemukan jumlah milidetik yang telah berlalu dalam tahun ini dan kemudian mengonversinya menjadi hari. Jumlah milidetik yang telah berlalu di tahun ini dapat ditemukan dengan mengurangkan jumlah milidetik dari detik pertama hari pertama tahun berjalan, yang diperoleh dengan new Date(new Date().getYear()+1900, 0, 1, 0, 0, 0)(Javascript) atau new Date(new Date().getYear(), 0, 1, 0, 0, 0)(Google Apps Script), dari milidetik dari jam ke-23 hari ini, yang ditemukan dengan new Date().setHours(23). Tujuan menyetel tanggal saat ini ke jam ke-23 adalah untuk memastikan bahwa hari dalam setahun dibulatkan dengan benar Math.round().
Setelah Anda mengetahui jumlah milidetik tahun ini, Anda dapat mengonversi waktu ini menjadi hari dengan membaginya dengan 1000 untuk mengubah milidetik menjadi detik, kemudian membaginya dengan 60 untuk mengubah detik menjadi menit, kemudian membaginya dengan 60 untuk mengubah menit menjadi jam, dan akhirnya membaginya dengan 24 untuk mengubah jam menjadi hari.
Catatan: Posting ini telah diedit untuk menjelaskan perbedaan antara JavaScript dan JavaScript yang diterapkan di Google Apps Script. Juga, lebih banyak konteks ditambahkan untuk jawabannya.
.setHoursmetode pada objek tanggal pertama dan menentukan waktu hari dengan objek tanggal kedua, perubahan 1 jam dari waktu musim panas tidak akan memengaruhi waktu objek Tanggal yang digunakan dalam perhitungan ini.
Saya pikir ini lebih mudah:
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!
Metode ini memperhitungkan masalah zona waktu dan waktu musim panas
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;
}
(diambil dari sini )
Lihat juga biola ini
Math.round ((Tanggal baru (). SetHours (23) - Tanggal baru (Tanggal baru (). GetFullYear (), 0, 1, 0, 0, 0)) / 1000/86400);
lebih mengoptimalkan jawabannya.
Selain itu, dengan mengubah setHours (23) atau nol terakhir-tapi-dua kemudian ke nilai lain dapat memberikan hari-tahun-tahun yang terkait dengan zona waktu lain. Misalnya, untuk mengambil sumber daya dari Eropa yang terletak di Amerika.
Math.floor((Date.now() - Date.parse(new Date().getFullYear(), 0, 0)) / 86400000)
inilah solusi saya
Saya telah membuat satu yang mudah dibaca dan akan melakukan trik dengan sangat cepat, serta menangani objek JS Date dengan zona waktu yang berbeda.
Saya telah menyertakan beberapa kasus uji untuk zona waktu, DST, detik kabisat, dan tahun kabisat.
PS ECMA-262 mengabaikan detik kabisat, tidak seperti UTC. Jika Anda mengonversinya ke bahasa yang menggunakan UTC nyata, Anda cukup menambahkan 1 ke 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"
);
Saya ingin memberikan solusi yang menghitung dengan menambahkan hari untuk setiap bulan sebelumnya:
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));
Dengan cara ini Anda tidak perlu mengelola detail tahun kabisat dan penghematan siang hari.
Alternatif menggunakan stempel waktu UTC. Juga seperti yang dicatat orang lain, hari yang menunjukkan tanggal 1 sebulan adalah 1 daripada 0. Namun bulan itu dimulai dari 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);
Anda dapat melewatkan parameter sebagai nomor tanggal dalam setDatefungsi:
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)
Ini mungkin berguna bagi mereka yang membutuhkan hari dalam setahun sebagai string dan memiliki jQuery UI yang tersedia.
Anda dapat menggunakan jQuery UI Datepicker:
day_of_year_string = $.datepicker.formatDate("o", new Date())
Di bawahnya berfungsi dengan cara yang sama seperti beberapa jawaban yang telah disebutkan ( (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())
Bagi kita yang menginginkan solusi alternatif yang cepat.
(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");
})();
Ukuran bulan dalam setahun dan cara Tahun Kabisat bekerja sangat cocok untuk menjaga waktu kita tetap sejalan dengan matahari. Heck, ini bekerja dengan sangat sempurna sehingga yang pernah kita lakukan hanyalah menyesuaikan beberapa detik di sana-sini . Sistem tahun kabisat kita saat ini telah berlaku sejak 24 Februari 1582 , dan kemungkinan besar akan tetap berlaku di masa mendatang.
DST, bagaimanapun, sangat bisa berubah. Mungkin 20 tahun dari sekarang, beberapa negara mungkin mengimbangi waktu satu hari penuh atau beberapa ekstrim lainnya untuk DST. Seluruh hari DST hampir pasti tidak akan pernah terjadi, tetapi DST masih sangat terbuka dan ragu-ragu. Dengan demikian, solusi di atas adalah bukti masa depan selain sangat sangat cepat.
Potongan kode di atas berjalan sangat cepat. Komputer saya dapat memproses 65536 tanggal dalam ~ 52ms di Chrome.
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);
Ini adalah solusi yang menghindari masalah objek Tanggal dan zona waktu yang merepotkan, yang mengharuskan tanggal masukan Anda dalam format "yyyy-dd-mm". Jika Anda ingin mengubah format, ubah fungsi 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)
}
}
Itu selalu membuat saya khawatir saat mencampur matematika dengan fungsi tanggal (sangat mudah melewatkan beberapa detail tahun kabisat lainnya). Katakanlah Anda memiliki:
var d = new Date();
Saya akan menyarankan menggunakan yang berikut ini, hari-hari akan disimpan dalam day:
for(var day = d.getDate(); d.getMonth(); day += d.getDate())
d.setDate(0);
Tidak dapat melihat alasan mengapa ini tidak akan berfungsi dengan baik (dan saya tidak akan terlalu khawatir tentang beberapa iterasi karena ini tidak akan digunakan secara intensif).
/ * GUNAKAN SKRIP INI * /
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;