Bagaimana cara menggunakan javascript untuk menghitung hari dalam setahun, dari 1 - 366? Sebagai contoh:
- 3 Jan harus 3 .
- 1 Februari seharusnya 32 tahun .
javascript
Kirk Woll
sumber
sumber
var days = new Date().getFullYear() % 4 == 0 ? 366 : 365;
Jawaban:
Mengikuti hasil edit OP:
Sunting: Kode di atas akan gagal jika
now
tanggal antara 26 Maret dan 29 Oktober dannow
waktu sebelum 1AM (mis. 00:59:59). Hal ini karena kode tidak memperhitungkan waktu musim panas. Anda harus mengkompensasi ini:sumber
Math.floor
secara konsisten memberi saya hasil 1 hari lebih sedikit dari yang diharapkan setelah hari tertentu di bulan April.Math.ceil
bekerja seperti yang diharapkan, tetapi saya telah melihat disarankan agar Anda menggunakanMath.round
daripada keduanya.new Date(2014, 0, 1)
, dan bukannew Date(2014, 0, 0)
seperti yang Anda miliki di sini. Apakah itu disengaja? Mungkin itulah yang menyebabkan libur satu hari dannew Date(2014, 0, 0)
akan kembali12/31/2013
..setUTCHours
danDate.UTC()
untuk solusi yang lebih andal.ceil
daripadafloor
, ini akan memberi Anda sistem penomoran di mana 1 Jan = 1. Jika Anda ingin 1 Jan = 0 (seperti yangfloor
akan 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):
sumber
getDay()
perlu diubah menjadigetDate()
. 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:
Anda dapat mengujinya dengan yang berikut:
Keluaran mana untuk tahun kabisat 2016 (diverifikasi menggunakan http://www.epochconverter.com/days/2016 ):
sumber
function doyToDate(doy, year) { return new Date(year, 0, doy); }
new Date(8640000000000000)
, yang masih kurang dariNumber.MAX_SAFE_INTEGER
. lihat jawaban ini: stackoverflow.com/a/11526569/18511sumber
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 object
mencakup 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 tahun
0
ada dan merupakan tahun kabisat dan tahun negatif didukung ) hari dalam setahun berdasarkan tahun , bulan dan hari .Perhatikan bahwa dalam
AD/BC
notasi, tahun 0 M / SM tidak ada: sebagai gantinya tahun1 BC
adalah 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).
Ini adalah versi dengan validasi rentang yang benar .
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=3
dan3
hanya 2 bit, maka12*2=24
bit, kita dapat menyimpan semua 12 bulan. Karena penjumlahan bisa lebih cepat daripada pengurangan, kami menambahkan offset (bukan menguranginya31
). 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
false
nilai 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<12
menjadim>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? .
sumber
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; };
+1
darithis.getMonth()+1
jika 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 - 2016
tahun - 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:
sumber
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:
Edit setelah pembaruan:
Dalam hal ini, menurut saya tidak ada metode bawaan; Anda harus melakukan ini:
(Ya, saya benar-benar melakukannya tanpa menyalin atau menempel. Jika ada cara mudah saya akan marah)
sumber
:)
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) ataunew Date(new Date().getYear(), 0, 1, 0, 0, 0)
(Google Apps Script), dari milidetik dari jam ke-23 hari ini, yang ditemukan dengannew Date().setHours(23)
. Tujuan menyetel tanggal saat ini ke jam ke-23 adalah untuk memastikan bahwa hari dalam setahun dibulatkan dengan benarMath.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.
sumber
.setHours
metode 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:
sumber
Metode ini memperhitungkan masalah zona waktu dan waktu musim panas
(diambil dari sini )
Lihat juga biola ini
sumber
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.
sumber
inilah solusi saya
sumber
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
.sumber
Saya ingin memberikan solusi yang menghitung dengan menambahkan hari untuk setiap bulan sebelumnya:
Dengan cara ini Anda tidak perlu mengelola detail tahun kabisat dan penghematan siang hari.
sumber
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.
sumber
Anda dapat melewatkan parameter sebagai nomor tanggal dalam
setDate
fungsi:sumber
Ini mungkin berguna bagi mereka yang membutuhkan hari dalam setahun sebagai string dan memiliki jQuery UI yang tersedia.
Anda dapat menggunakan jQuery UI Datepicker:
Di bawahnya berfungsi dengan cara yang sama seperti beberapa jawaban yang telah disebutkan (
(date_ms - first_date_of_year_ms) / ms_per_day
):sumber
Bagi kita yang menginginkan solusi alternatif yang cepat.
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.
sumber
sumber
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:
sumber
Itu selalu membuat saya khawatir saat mencampur matematika dengan fungsi tanggal (sangat mudah melewatkan beberapa detail tahun kabisat lainnya). Katakanlah Anda memiliki:
Saya akan menyarankan menggunakan yang berikut ini, hari-hari akan disimpan dalam
day
: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).
sumber
/ * GUNAKAN SKRIP INI * /
sumber