การคำนวณวันสุดท้ายของเดือน


144

ฉันมีปัญหากับการคำนวณว่าวันสุดท้ายของเดือนถัดไปสำหรับการแจ้งเตือนที่กำหนดเวลาการส่ง

นี่คือรหัสของฉัน:

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

นี่คือสายที่ทำให้เกิดปัญหาที่ฉันเชื่อว่า:

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

ฉันจะใช้ปฏิทินเพื่อตั้งค่าวันสุดท้ายของเดือนถัดไปให้ถูกต้องได้อย่างไร


1
ตั้งเป็นวันแรกของเดือนถัดไปจากนั้นย้อนกลับหนึ่งวัน
Bill

SSCCEจะทำให้มันง่ายที่จะตอบคำถามนี้ คุณเห็นปัญหาอะไรจริง
DNA

คำตอบ:


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

สิ่งนี้จะคืนค่าสูงสุดที่แท้จริงสำหรับเดือนปัจจุบัน intยกตัวอย่างเช่นมันเป็นเดือนกุมภาพันธ์ของปีอธิกสุรทินในขณะนี้ดังนั้นมันกลับเป็น 29


ขอบคุณฉันต้องได้รับประโยชน์สูงสุดสำหรับเดือนถัดไป แต่ก็ยังต้องทำงานที่สามารถเป็นวันแรกของเดือนได้เช่นกันส่วนที่ใช้งานได้ในขณะนี้ ขอบคุณอีกครั้งสำหรับเวลาและความพยายามของคุณ
OakvilleWork

4
ไม่มีปัญหาที่จะได้รับActualMaximumทุกวัน getActualMaximumม้วนเพียงเช่นปฏิทินวันที่จำเป็นก่อนที่จะเรียก วันแรกสามารถรับได้โดยgetActualMinimum()
AlexR

โอเคขอบคุณมากอเล็กซ์ดังนั้นถ้าฉันต้องการที่จะม้วนอินสแตนซ์ไปหนึ่งเดือนข้างหน้าและหา getActualMaximum สำหรับเดือนนั้นฉันจะทำอย่างไร ?? ไชโย
OakvilleWork

นี่จะเป็นอเล็กซ์ไหม nextNotifTime.roll (Calendar.MONTH จริง); nextNotifTime.getActualMaximum (Calendar.DAY_OF_MONTH);
OakvilleWork

ผมก็ตั้งเวลาวันพร้อมหลังจากนี้nextNotification.setReadyDateTime(nextNotifTime.getTime()); ดังนั้นผมไม่ควรทำเช่นนี้แทน: nextNotifTime.roll(Calendar.MONTH, true); nextNotifTime.getActualMaximum(Calendar.DAY_OF_MONTH); nextNotifTime.setTime(Calendar.DAY_OF_MONTH); ?
OakvilleWork

61

java.time.temporal.TemporalAdjusters.lastDayOfMonth ()

เมื่อใช้java.timeไลบรารีที่สร้างขึ้นใน Java 8 คุณสามารถใช้TemporalAdjusterอินเตอร์เฟสได้ เราพบว่าการดำเนินการพร้อมสำหรับการใช้งานในระดับยูทิลิตี้:TemporalAdjusterslastDayOfMonth

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

หากคุณต้องการเพิ่มข้อมูลเวลาคุณสามารถใช้LocalDateการLocalDateTimeแปลงใด ๆ ที่มีให้

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

คำตอบที่ดี. LocalDateTimeแต่ที่ส่วนสุดท้ายจะอ่อนแอแนะนำการใช้งานของ คลาสนั้นไม่มีแนวคิดเกี่ยวกับเขตเวลาหรือออฟเซ็ตจาก UTC ดังนั้นจึงไม่สามารถระบุได้ว่าวันใดวันหนึ่งในสถานที่เฉพาะเริ่มต้นจริง ชั้นเรียนนั้นใช้งานได้เฉพาะวันธรรมดาทั่วไป 24 ชั่วโมงไม่ใช่วันโลกแห่งความจริง ZonedDateTime zdt = now.atStartOfDay( ZoneId.of( "Asia/Tokyo" ) ) ;สำหรับวันจริงระบุโซนเวลา: บางวันในบางแห่งอาจเริ่มในเวลาอื่นเช่น 01:00 เนื่องจากความผิดปกติเช่น Daylight Saving Time (DST)
Basil Bourque

35

และรับวันสุดท้ายเป็นวัตถุวันที่:

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

Date lastDayOfMonth = cal.getTime();

22

คุณสามารถตั้งค่าปฏิทินเป็นเดือนแรกของเดือนถัดไปแล้วลบวัน

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

หลังจากเรียกใช้รหัสนี้ถัดไป NotifTime จะถูกตั้งค่าเป็นวันสุดท้ายของเดือนปัจจุบัน โปรดทราบว่าวันนี้เป็นวันสุดท้ายของเดือนผลกระทบสุทธิของรหัสนี้คือวัตถุในปฏิทินยังคงไม่เปลี่ยนแปลง


17

การติดตามจะให้ผลลัพธ์ที่เหมาะสมเสมอ:

    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();

ทำไมถึงจำเป็น? คุณบอกฉันได้ไหม :)
Frank Fang

1
ใช่เพิ่งมีการทดสอบล้มเหลวด้วยเหตุผลที่แน่นอนข้างต้น ปัญหาคือว่าถ้าไม่ได้ตั้งค่า DAY_OF_MONTH ไว้ระบบจะใช้ค่าเริ่มต้นเป็นค่าปัจจุบัน
ppearcy

7

การใช้java.timeห้องสมุดล่าสุดที่นี่เป็นทางออกที่ดีที่สุด:

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

หรือคุณสามารถทำได้:

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


2

ดูgetActualMaximum(int field)วิธีการของวัตถุปฏิทิน

หากคุณตั้งค่าให้วัตถุในปฏิทินของคุณเป็นเดือนที่คุณต้องการค้นหาวันที่สุดท้ายgetActualMaximum(Calendar.DAY_OF_MONTH)คุณจะได้รับวันสุดท้าย


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

การใช้ส่วนขยายวันที่ Kotlin โดยใช้ 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
}

คุณสามารถเรียกtoEndOfMonthใช้ฟังก์ชันในแต่ละวัตถุวันที่ได้Date().toEndOfMonth()


4
คลาสที่น่ากลัวเหล่านี้ถูกแทนที่เมื่อหลายปีก่อนโดยคลาสjava.time ที่ทันสมัยโดยใช้ JSR 310 การแนะนำคลาสเรียนดั้งเดิมเหล่านี้ในปี 2019 เป็นคำแนะนำที่ไม่ดี
Basil Bourque

มันไม่ใช่คำแนะนำที่ไม่ดี java.time ที่ทันสมัยพร้อมใช้งานสำหรับ Android สำหรับ API 26+ เท่านั้น เรายังคงพึ่งพาjava.util. *เมื่อสนับสนุนอุปกรณ์เก่า (ไม่เช่นนั้น)
Rafael Chagas
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.