Hitung hari terakhir bulan ini dalam JavaScript

277

Jika Anda memberikan 0sebagai di dayValuedalam Date.setFullYearAnda mendapatkan hari terakhir bulan sebelumnya:

d = new Date(); d.setFullYear(2008, 11, 0); //  Sun Nov 30 2008

Ada referensi untuk perilaku ini di mozilla . Apakah ini fitur lintas-browser yang dapat diandalkan atau haruskah saya melihat metode alternatif?

Ken
sumber
Bukankah maksud Anda hari terakhir dari bulan yang ditentukan? Ada 30 hari di bulan November dan 31 di bulan Oktober.
Chris Serra
16
Bulan berbasis nol dalam javascript sehingga 11 adalah Desember
Greg
2
@TheCloudlessSky - coba di konsol Anda ... (2008,11,0) adalah hari ke-nol Desember, dan karenanya hari terakhir bulan November
Ken
@ Ken - Ya - Saya tidak menyadari ada "0":) ... masih terlalu pagi.
TheCloudlessSky

Jawaban:

425
var month = 0; // January
var d = new Date(2008, month + 1, 0);
alert(d); // last day in January

IE 6:                     Thu Jan 31 00:00:00 CST 2008
IE 7:                     Thu Jan 31 00:00:00 CST 2008
IE 8: Beta 2:             Thu Jan 31 00:00:00 CST 2008
Opera 8.54:               Thu, 31 Jan 2008 00:00:00 GMT-0600
Opera 9.27:               Thu, 31 Jan 2008 00:00:00 GMT-0600
Opera 9.60:               Thu Jan 31 2008 00:00:00 GMT-0600
Firefox 2.0.0.17:         Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Firefox 3.0.3:            Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Google Chrome 0.2.149.30: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)
Safari for Windows 3.1.2: Thu Jan 31 2008 00:00:00 GMT-0600 (Canada Central Standard Time)

Perbedaan output disebabkan oleh perbedaan dalam toString()implementasi, bukan karena tanggalnya berbeda.

Tentu saja, hanya karena peramban yang diidentifikasi di atas menggunakan 0 sebagai hari terakhir bulan sebelumnya tidak berarti mereka akan terus melakukannya, atau peramban yang tidak terdaftar akan melakukannya, tetapi memberikan kredibilitas pada keyakinan bahwa peramban harus bekerja dengan baik. cara yang sama di setiap browser.

Grant Wagner
sumber
19
Itu tampaknya bekerja dengan sangat baik. Karena penasaran, apa yang Anda gunakan untuk menjalankan javascript di semua mesin ini? Punya segalanya diatur atau semacam alat?
neonski
5
Anda dapat menggunakan d.getDate () untuk mendapatkan hari yang sebenarnya.
rynop
35
"hanya karena browser ... gunakan 0 sebagai hari terakhir bulan sebelumnya tidak berarti mereka akan terus melakukannya". Ya, mereka harus melakukannya oleh ECMA-262.
RobG
3
Harap dicatat bahwa menggunakan new Dateadalah begitu jauh lebih lambat dibandingkan metode perhitungan lain yang bahkan tidak muncul di chart Perf : jsperf.com/days-in-month-perf-test/6
Pergi Coding
4
Tidak berfungsi untuk saya di Chrome 48.0.2564.116. Mungkin, cara ini telah berhenti dari menjadi 'standar'.
xarlymg89
77

Saya akan menggunakan tanggal antara dengan hari pertama bulan berikutnya, dan mengembalikan tanggal dari hari sebelumnya:

int_d = new Date(2008, 11+1,1);
d = new Date(int_d - 1);
karlipoppins
sumber
Menurut spesifikasi ECMAScript , penggunaan konstruktor "Tanggal" seperti yang Anda tunjukkan valid. Setelah algoritma yang ditentukan oleh fungsi "MakeDay", itu harus menangani masalah dengan baik.
Pablo Cabrera
1
ini adalah solusi IMO terbaik. Saya mencoba jawaban yang diterima tetapi memiliki beberapa bug ketika mengambil yang terakhir dari bulan ini. Ia mengembalikan tanggal hari ini. Namun tidak yakin mengapa itu terjadi.
Gogol
1
Saya tidak dapat melaporkan bug. Ini memberi saya tanggal yang benar di semua browser:today = new Date(); new Date(today.getFullYear(), today.getMonth()+1, 0).toString();
orad
Ini menciptakan objek Tanggal untuk hari terakhir bulan dengan waktu yang ditentukan untuk milidetik terakhir (yaitu 23: 59: 59.999). Lebih baik hanya menggunakan metode di OP dan menyimpan langkah ekstra dan objek Tanggal.
RobG
@RobG: saya setuju! meskipun solusi saya mungkin lebih mudah untuk dipahami, karena gagasan menggunakan 0 untuk hari terakhir bulan itu terasa agak goyang menurut saya.
karlipoppins
72

Saya menemukan ini menjadi solusi terbaik untuk saya. Biarkan objek Date menghitungnya untuk Anda.

var today = new Date();
var lastDayOfMonth = new Date(today.getFullYear(), today.getMonth()+1, 0);

Mengatur parameter hari ke 0 berarti satu hari kurang dari hari pertama bulan yang merupakan hari terakhir dari bulan sebelumnya.

orad
sumber
1
Tidak apa-apa, saya perhatikan jawaban yang dipilih menunjukkan hal yang sama. Ini adalah cara tercepat dan paling andal serta berfungsi terlepas dari jenis kalendernya. Sebagai contoh jika Date mengimplementasikan sesuatu selain kalender Gregorian itu masih akan berfungsi. Lihat intldate.codeplex.com untuk contoh implementasi objek Date yang non-Gregorian.
orad
1
@orad: Waspadalah dalam mengklaim sesuatu "adalah yang tercepat" karena metode ini sebenarnya jauh lebih lambat daripada beberapa alternatif. Menggunakan new Dateini begitu jauh lebih lambat itu bahkan tidak muncul di chart Perf : jsperf.com/days-in-month-perf-test/6
Pergi Coding
@ TrueBlueAussie OK. Saya berasumsi bahwa itu lebih cepat karena itu asli. Tapi Anda benar, itu tidak cepat. Terima kasih untuk benar-benar mengujinya. Bagaimanapun, solusi ini bekerja paling baik untuk saya karena ringkas dan mudah dibaca dan tidak seperti semua solusi lain tidak terikat pada kalender Gregorian.
orad
"tidak seperti semua solusi lain tidak terikat pada Kalender Gregorian" !!! Algoritma ini mengembalikan nilai yang sama dengan nilai saya selama bertahun-tahun 1-4000. jsfiddle.net/2973x9m3/3 Rentang tanggal tambahan apa yang Anda klaim akan didukung (yang akan digunakan)? :)
Hilang Coding
1
Native JS Date hanya menggunakan kalender Gregorian. Tapi Anda bisa mengejeknya dengan beberapa implementasi lain untuk mendapatkan tipe kalender lain. Sebagai contoh, lihat IntlDate . Jika Anda memiliki pemilih tanggal yang menggunakan objek Tanggal untuk membuat tampilan bulanan, tidak peduli implementasi Tanggal mana (asli atau mengejek) yang digunakan selama mereka memiliki antarmuka yang sama. Jadi menggunakan antarmuka bersama memungkinkan beralih di antara berbagai jenis Kalender tanpa harus tahu berapa hari dalam sebulan di setiap kalender.
orad
25

Dalam istilah komputer, new Date()dan regular expressionsolusinya lambat! Jika Anda menginginkan one-liner super cepat (dan super-samar), coba yang satu ini (anggap mdalam Jan=1format). Saya terus mencoba berbagai perubahan kode untuk mendapatkan kinerja terbaik.

Versi tercepat saya saat ini :

Setelah melihat pertanyaan terkait ini , periksa tahun kabisat menggunakan operator bitwise (kecepatan luar biasa) dan menemukan apa yang diwakili bilangan ajaib 25 & 15, saya telah menghasilkan hibrida jawaban yang dioptimalkan ini:

function getDaysInMonth(m, y) {
    return m===2 ? y & 3 || !(y%25) && y & 15 ? 28 : 29 : 30 + (m+(m>>3)&1);
}

Mengingat bit-shifting ini jelas mengasumsikan bahwa m& yparameter Anda sama-sama bilangan bulat, karena angka yang lewat sebagai string akan menghasilkan hasil yang aneh.

JSFiddle: http://jsfiddle.net/TrueBlueAussie/H89X3/22/

Hasil JSPerf: http://jsperf.com/days-in-month-head-to-head/5

Untuk beberapa alasan, (m+(m>>3)&1)lebih efisien daripada (5546>>m&1)di hampir semua browser.

Satu-satunya kompetisi nyata untuk kecepatan adalah dari @GitaarLab, jadi saya telah membuat JSPerf head-to-head untuk kami uji: http://jsperf.com/days-in-month-head-to-head/5


Ia bekerja berdasarkan jawaban tahun kabisat saya di sini: javascript untuk menemukan tahun kabisat jawaban ini di sini Tahun kabisat periksa menggunakan operator bitwise (kecepatan luar biasa) serta logika biner berikut.

Pelajaran cepat dalam bulan biner:

Jika Anda mengartikan indeks bulan yang diinginkan (Jan = 1) dalam biner, Anda akan melihat bahwa bulan dengan 31 hari memiliki bit 3 clear dan bit 0 set, atau bit 3 set dan bit 0 clear.

Jan = 1  = 0001 : 31 days
Feb = 2  = 0010
Mar = 3  = 0011 : 31 days
Apr = 4  = 0100
May = 5  = 0101 : 31 days
Jun = 6  = 0110
Jul = 7  = 0111 : 31 days
Aug = 8  = 1000 : 31 days
Sep = 9  = 1001
Oct = 10 = 1010 : 31 days
Nov = 11 = 1011
Dec = 12 = 1100 : 31 days

Itu berarti Anda dapat menggeser nilai 3 tempat dengan >> 3, XOR bit dengan yang asli ^ mdan melihat apakah hasilnya menggunakan bit1 atau 0 dalam posisi 0& 1 . Catatan: Ternyata +sedikit lebih cepat daripada XOR ( ^) dan (m >> 3) + mmemberikan hasil yang sama di bit 0.

Hasil JSPerf : http://jsperf.com/days-in-month-perf-test/6

Goding Coding
sumber
1
@ GitaarLAB: Anda sudah menyebutkan dan ini tidak pernah persis sama dengan milik Anda, seperti yang Anda ketahui. Pembaruan tambahan untuk masing-masing algoritma tidak sama dengan "algo asli". Saya berusaha keras untuk jawaban ini juga: P
Hilang Coding
@ TrueBlueAussie: Saya hanya ingin mengarahkan pembaca di masa mendatang ke informasi kami yang lebih banyak (saya menautkan kedua jawaban kami sehingga siapa pun yang peduli atau ingin mencoba lagi dapat melihat riwayat edit kami untuk melihat kapan kami melakukan apa dan mengapa ). Saya masih ingat hari penuh kompetisi kami! :)Versi jawaban pertama yang saya poskan memang memiliki tanda kurung yang tidak diperlukan, yang dihapus (yang saya kreditkan kepada Anda) sehingga kami dapat mencukur karakter dan berakhir dengan yang ini. Aku masih bersyukur untuk hari yang menyenangkan itu, tepuk tangan!
GitaarLAB
1
Tolong sebutkan itu ydan mvariabel harus integer bukan string! Itu menyebabkan perhitungan yang salah misalnya untuk Februari mengembalikan 30. Saya harus menggunakan parseInt()fungsi untuk membuatnya berfungsi.
sebagai gantinya
21

Kolega saya menemukan hal-hal berikut yang mungkin merupakan solusi yang lebih mudah

function daysInMonth(iMonth, iYear)
{
    return 32 - new Date(iYear, iMonth, 32).getDate();
}

dicuri dari http://snippets.dzone.com/posts/show/2099

lebreeze
sumber
2
Nigel memodifikasi ini menjadi solusi yang lebih ringkas. Lihat jabatannya.
orad
Bulan berbasis nol, yaitu, Jan = 0. Sama seperti getMonth ().
Moos
16

Sedikit modifikasi pada solusi yang disediakan oleh lebreeze :

function daysInMonth(iMonth, iYear)
{
    return new Date(iYear, iMonth, 0).getDate();
}
Nigel
sumber
Ini harus return new Date(iYear, 1 + iMonth, 0).getDate();setara dengan solusi @ lebreeze.
Moos
6

Saya baru-baru ini harus melakukan sesuatu yang serupa, inilah yang saya buat:

/**
* Returns a date set to the begining of the month
* 
* @param {Date} myDate 
* @returns {Date}
*/
function beginningOfMonth(myDate){    
  let date = new Date(myDate);
  date.setDate(1)
  date.setHours(0);
  date.setMinutes(0);
  date.setSeconds(0);   
  return date;     
}

/**
 * Returns a date set to the end of the month
 * 
 * @param {Date} myDate 
 * @returns {Date}
 */
function endOfMonth(myDate){
  let date = new Date(myDate);
  date.setMonth(date.getMonth() +1)
  date.setDate(0);
  date.setHours(23);
  date.setMinutes(59);
  date.setSeconds(59);
  return date;
}

Pass it in a date, dan itu akan mengembalikan tanggal yang diatur ke awal bulan, atau akhir bulan.

The begninngOfMonthfungsi cukup jelas, tapi apa yang terjadi di dalam endOfMonthfungsi adalah bahwa aku incrementing bulan ke bulan berikutnya, dan kemudian menggunakan setDate(0)untuk memutar kembali hari ke hari terakhir dari bulan sebelumnya yang merupakan bagian dari setDate spec:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setDate https://www.w3schools.com/jsref/jsref_setdate.asp

Saya kemudian mengatur jam / menit / detik ke akhir hari, sehingga jika Anda menggunakan semacam API yang mengharapkan rentang tanggal Anda akan dapat menangkap keseluruhan hari terakhir itu. Bagian itu mungkin melampaui apa yang diminta posting asli tetapi bisa membantu orang lain mencari solusi yang sama.

Sunting: Anda juga dapat bekerja ekstra dan menetapkan milidetik setMilliseconds()jika Anda ingin menjadi lebih tepat.

Eric
sumber
4

coba yang ini.

lastDateofTheMonth = new Date(year, month, 0)

contoh:

new Date(2012, 8, 0)

keluaran:

Date {Fri Aug 31 2012 00:00:00 GMT+0900 (Tokyo Standard Time)}
artylar
sumber
5
Ingatlah, bahwa bulan-bulan itu berbasis nol, sehingga melewati "8" karena bulan itu benar-benar September, bukan Agustus.
Steve J
3

Ini bekerja untuk saya. Akan memberikan hari terakhir pada tahun dan bulan tertentu:

var d = new Date(2012,02,0);
var n = d.getDate();
alert(n);
Kreeverp
sumber
1
hati-hati dengan 0 di depan "2" itu akan ditafsirkan sebagai oktal.
Walfrat
1

Ini berfungsi dengan baik:

Date.prototype.setToLastDateInMonth = function () {

    this.setDate(1);
    this.setMonth(this.getMonth() + 1);
    this.setDate(this.getDate() - 1);

    return this;
}
Josue
sumber
1

Ini akan memberi Anda bulan saat ini hari pertama dan terakhir.

Jika Anda perlu mengubah 'tahun', hapus d.getFullYear () dan atur tahun Anda.

Jika Anda perlu mengubah 'bulan' hapus d.getMonth () dan atur tahun Anda.

var d = new Date();
var days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
var fistDayOfMonth = days[(new Date(d.getFullYear(), d.getMonth(), 1).getDay())];
	var LastDayOfMonth = days[(new Date(d.getFullYear(), d.getMonth() + 1, 0).getDay())]; 
console.log("First Day :" + fistDayOfMonth); 
console.log("Last Day:" + LastDayOfMonth);
alert("First Day :" + fistDayOfMonth); 
alert("Last Day:" + LastDayOfMonth);

Himanshu kukreja
sumber
1

Coba ini:

function _getEndOfMonth(time_stamp) {
    let time = new Date(time_stamp * 1000);
    let month = time.getMonth() + 1;
    let year = time.getFullYear();
    let day = time.getDate();
    switch (month) {
        case 1:
        case 3:
        case 5:
        case 7:
        case 8:
        case 10:
        case 12:
            day = 31;
            break;
        case 4:
        case 6:
        case 9:
        case 11:
            day = 30;
            break;
        case 2:
            if (_leapyear(year))
                day = 29;
            else
                day = 28;
            break
    }
    let m = moment(`${year}-${month}-${day}`, 'YYYY-MM-DD')
    return m.unix() + constants.DAY - 1;
}

function _leapyear(year) {
    return (year % 100 === 0) ? (year % 400 === 0) : (year % 4 === 0);
}
Yatin Darmwal
sumber
1

Fungsi di bawah ini memberikan hari terakhir bulan itu:

function getLstDayOfMonFnc(date) {
  return new Date(date.getFullYear(), date.getMonth(), 0).getDate()
}

console.log(getLstDayOfMonFnc(new Date(2016, 2, 15))) // Output : 29
console.log(getLstDayOfMonFnc(new Date(2017, 2, 15))) // Output : 28
console.log(getLstDayOfMonFnc(new Date(2017, 11, 15))) // Output : 30
console.log(getLstDayOfMonFnc(new Date(2017, 12, 15))) // Output : 31

Demikian pula kita bisa mendapatkan hari pertama bulan ini:

function getFstDayOfMonFnc(date) {
  return new Date(date.getFullYear(), date.getMonth(), 1).getDate()
}

console.log(getFstDayOfMonFnc(new Date(2016, 2, 15))) // Output : 1

Sujay UN
sumber
0
function getLastDay(y, m) {
   return 30 + (m <= 7 ? ((m % 2) ? 1 : 0) : (!(m % 2) ? 1 : 0)) - (m == 2) - (m == 2 && y % 4 != 0 || !(y % 100 == 0 && y % 400 == 0)); 
}
Ashish
sumber
0
const today = new Date();

let beginDate = new Date();

let endDate = new Date();

// fist date of montg

beginDate = new Date(

  `${today.getFullYear()}-${today.getMonth() + 1}-01 00:00:00`

);

// end date of month 

// set next Month first Date

endDate = new Date(

  `${today.getFullYear()}-${today.getMonth() + 2}-01 :23:59:59`

);

// deducting 1 day

endDate.setDate(0);
chou
sumber
0

atur bulan Anda harus berkencan dan kemudian atur hari ke nol, jadi bulan dimulai dari 1 - 31 dalam fungsi tanggal lalu dapatkan hari terakhir ^^

var last = new Date(new Date(new Date().setMonth(7)).setDate(0)).getDate();
console.log(last);

ahmed samra
sumber
0

Berikut adalah jawaban yang menghemat GMT dan waktu tanggal awal

var date = new Date();

var first_date = new Date(date); //Make a copy of the date we want the first and last days from
first_date.setUTCDate(1); //Set the day as the first of the month

var last_date = new Date(first_date); //Make a copy of the calculated first day
last_date.setUTCMonth(last_date.getUTCMonth() + 1); //Add a month
last_date.setUTCDate(0); //Set the date to 0, this goes to the last day of the previous month

console.log(first_date.toJSON().substring(0, 10), last_date.toJSON().substring(0, 10)); //Log the dates with the format yyyy-mm-dd

Tofandel
sumber
0

Saya tahu ini hanya masalah semantik, tetapi saya akhirnya menggunakannya dalam bentuk ini.

var lastDay = new Date(new Date(2008, 11+1,1) - 1).getDate();
console.log(lastDay);

Karena fungsi diselesaikan dari argumen di dalam, di luar, ia berfungsi sama.

Anda kemudian dapat mengganti tahun, dan bulan / tahun dengan rincian yang diperlukan, apakah itu dari tanggal saat ini. Atau bulan / tahun tertentu.

Rudi Strydom
sumber
0

Jika Anda membutuhkan akhir bulan dalam milidetik (misalnya dalam stempel waktu):

d = new Date()
console.log(d.toString())
d.setDate(1)
d.setHours(23, 59, 59, 999)
d.setMonth(d.getMonth() + 1)
d.setDate(d.getDate() - 1)
console.log(d.toString())

Gungnir
sumber