perhitungan hari terakhir bulan


144

Saya mengalami masalah dengan perhitungan kapan Hari Terakhir Bulan berikutnya untuk pemberitahuan yang dijadwalkan akan dikirim.

Ini kode saya:

RecurrenceFrequency recurrenceFrequency = notification.getRecurrenceFrequency();
Calendar nextNotifTime = Calendar.getInstance();

Inilah garis yang menyebabkan masalah yang saya yakini:

nextNotifTime.add(recurrenceFrequency.getRecurrencePeriod(), 
                  recurrenceFrequency.getRecurrenceOffset());

Bagaimana saya bisa menggunakan Kalender untuk mengatur hari terakhir bulan berikutnya untuk notifikasi?


1
Atur ke hari pertama bulan berikutnya dan kemudian mundur satu hari.
Tagihan

Sebuah SSCCE akan membuat lebih mudah untuk menjawab pertanyaan ini. Masalah apa yang sebenarnya Anda lihat?
DNA

Jawaban:


347
Calendar.getInstance().getActualMaximum(Calendar.DAY_OF_MONTH);

Ini mengembalikan maksimum aktual untuk bulan ini. Misalnya sekarang Februari tahun kabisat, jadi mengembalikan 29 sebagai int.


terima kasih, saya perlu mendapatkan maks untuk bulan berikutnya, tetapi masih harus bekerja bahwa itu bisa menjadi hari pertama bulan itu juga, karena bagian itu berfungsi sekarang. terima kasih sekali lagi atas waktu dan usaha Anda
OakvilleWork

4
Bukan masalah untuk mendapatkan ActualMaximumsetiap kencan. Cukup putar instance kalender ke tanggal yang diperlukan sebelum menelepon getActualMaximum. Tanggal pertama dapat diperoleh dengangetActualMinimum()
AlexR

ok terima kasih banyak Alex, jadi jika saya ingin memutar contoh untuk satu bulan ke depan dan mencari tahu getActualMaximum untuk bulan itu bagaimana saya melakukannya ?? Cheers
OakvilleWork

apakah ini Alex? nextNotifTime.roll (Calendar.MONTH, true); nextNotifTime.getActualMaximum (Calendar.DAY_OF_MONTH);
OakvilleWork

juga saya mengatur siap tanggal waktu setelah ini: nextNotification.setReadyDateTime(nextNotifTime.getTime()); karena itu harus saya tidak melakukan ini sebagai gantinya: nextNotifTime.roll(Calendar.MONTH, true); nextNotifTime.getActualMaximum(Calendar.DAY_OF_MONTH); nextNotifTime.setTime(Calendar.DAY_OF_MONTH); ?
OakvilleWork

61

java.time.temporal.TemporalAdjusters.lastDayOfMonth ()

Menggunakan java.timeperpustakaan yang dibangun ke Java 8, Anda dapat menggunakan TemporalAdjusterantarmuka. Kami menemukan sebuah implementasi siap untuk digunakan dalam TemporalAdjusterskelas utilitas: lastDayOfMonth.

import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

LocalDate now = LocalDate.now(); //2015-11-23
LocalDate lastDay = now.with(TemporalAdjusters.lastDayOfMonth()); //2015-11-30

Jika Anda perlu menambahkan informasi waktu, Anda dapat menggunakan yang tersedia LocalDateuntuk LocalDateTimekonversi seperti

lastDay.atStartOfDay(); //2015-11-30T00:00

Jawaban yang bagus. Tetapi bagian terakhir itu lemah, menyarankan penggunaan LocalDateTime. Kelas itu tidak memiliki konsep zona waktu atau offset-dari-UTC. Jadi itu tidak dapat menentukan kapan hari tertentu di tempat tertentu benar-benar dimulai. Kelas itu hanya berfungsi untuk 24 jam sehari, bukan hari biasa. Untuk hari nyata, menentukan zona waktu: ZonedDateTime zdt = now.atStartOfDay( ZoneId.of( "Asia/Tokyo" ) ) ;. Beberapa hari di beberapa tempat dapat dimulai pada waktu yang berbeda, seperti 01:00, karena anomali seperti Daylight Saving Time (DST).
Basil Bourque

35

Dan untuk mendapatkan hari terakhir sebagai objek Date:

Calendar cal = Calendar.getInstance();
cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));

Date lastDayOfMonth = cal.getTime();

22

Anda dapat mengatur kalender menjadi yang pertama bulan berikutnya dan kemudian kurangi satu hari.

Calendar nextNotifTime = Calendar.getInstance();
nextNotifTime.add(Calendar.MONTH, 1);
nextNotifTime.set(Calendar.DATE, 1);
nextNotifTime.add(Calendar.DATE, -1);

Setelah menjalankan kode ini nextNotifTime akan ditetapkan ke hari terakhir bulan ini. Ingatlah bahwa jika hari ini adalah hari terakhir dalam bulan, efek bersih dari kode ini adalah bahwa objek Kalender tetap tidak berubah.


17

Berikut ini akan selalu memberikan hasil yang tepat:

    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.MONTH, ANY_MONTH);
    cal.set(Calendar.YEAR, ANY_YEAR);
    cal.set(Calendar.DAY_OF_MONTH, 1);// This is necessary to get proper results
    cal.set(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
    cal.getTime();

Kenapa itu perlu? Bisakah Anda ceritakan :)
Frank Fang

1
Yap, baru saja tes gagal karena alasan tepat di atas. Masalahnya adalah bahwa kecuali DAY_OF_MONTH diatur, default akan menjadi saat ini.
ppearcy

7

Menggunakan java.timeperpustakaan terbaru di sini adalah solusi terbaik:

LocalDate date = LocalDate.now();
LocalDate endOfMonth = date.with(TemporalAdjusters.lastDayOfMonth());

Atau, Anda dapat melakukan:

LocalDate endOfMonth = date.withDayOfMonth(date.lengthOfMonth());


2

Lihatlah getActualMaximum(int field) metode objek Kalender.

Jika Anda menetapkan objek Kalender Anda berada di bulan yang Anda cari tanggal terakhir, maka getActualMaximum(Calendar.DAY_OF_MONTH)akan memberi Anda hari terakhir.


2
        SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
        Date date = sdf.parse("11/02/2016");

        Calendar calendar = Calendar.getInstance();  
        calendar.setTime(date);  

        System.out.println("First Day Of Month : " + calendar.getActualMinimum(Calendar.DAY_OF_MONTH));  
        System.out.println("Last Day of Month  : " + calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); 

1

Penggunaan ekstensi tanggal Kotlin menggunakan java.util.Calendar

fun Date.toEndOfMonth(): Date {
    return Calendar.getInstance().apply {
        time = this@toEndOfMonth
    }.toEndOfMonth().time
}

fun Calendar.toEndOfMonth(): Calendar {
    set(Calendar.DAY_OF_MONTH, getActualMaximum(Calendar.DAY_OF_MONTH))
    return this
}

Anda dapat memanggil toEndOfMonthfungsi pada setiap objek Date likeDate().toEndOfMonth()


4
Kelas-kelas yang mengerikan ini digantikan tahun yang lalu oleh kelas java.time modern dengan adopsi JSR 310. Menyarankan kelas-kelas warisan ini pada tahun 2019 adalah saran yang buruk.
Basil Bourque

Itu bukan saran yang buruk. Java.time modern hanya tersedia untuk Android untuk API 26+. Kami masih bergantung pada java.util. * Ketika mendukung (tidak demikian) perangkat lama.
Rafael Chagas
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.