ayın son günü hesaplaması


144

Gönderilmesi planlanan bir bildirim için ayın bir sonraki son gününün ne zaman hesaplanacağıyla ilgili sorunlar yaşıyorum.

İşte benim kod:

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

Bu, inandığım sorunlara neden olan çizgi:

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

Takvimi, bildirim için bir sonraki ayın son gününü doğru bir şekilde ayarlamak için nasıl kullanabilirim?


1
Bir sonraki ayın ilk gününe ayarlayın ve bir gün geri alın.
Bill

Bir SSCCE bu soruya cevap vermeyi kolaylaştıracaktır. Aslında hangi problemi görüyorsunuz?
DNA

Yanıtlar:


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

Bu, geçerli ay için gerçek maksimum değeri döndürür. Mesela artık sıçrama yılının şubat ayı, yani 29 olarak geri dönüyor int.


teşekkürler, ancak önümüzdeki ay için maksimum almak gerekir, ancak yine de bu bölüm çalışıyor gibi ayın ilk günü de olabilir çalışması gerekiyor. zaman ve çaba için tekrar teşekkürler
OakvilleWork

4
ActualMaximumHer tarih için bir sorun değil . Takvim örneğini aramadan önce istenen tarihe yuvarlamanız yeterlidir getActualMaximum. İlk tarihgetActualMinimum()
AlexR

Tamam çok teşekkürler Alex, öyleyse örneği bir ay ileri götürmek ve o ay için getActualMaximum bulmak istiyorsanız nasıl bunu? şerefe
OakvilleWork

bu olur mu Alex? nextNotifTime.roll (Calendar.MONTH, doğru); nextNotifTime.getActualMaximum (Calendar.DAY_OF_MONTH);
OakvilleWork

Ayrıca Bundan sonra hazır tarih zamanını ayarlamak: nextNotification.setReadyDateTime(nextNotifTime.getTime()); bu nedenle bunun yerine bu yapmaması gereken: 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.timeJava 8'de yerleşik olan kitaplığı kullanarak TemporalAdjusterarayüzü kullanabilirsiniz . Biz kullanılmak üzere bir uygulama hazır bulmak TemporalAdjustersyarar sınıfının: 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

Zaman bilgisi eklemeniz gerekiyorsa, dönüşüm LocalDateiçin kullanılabilir herhangi birLocalDateTime

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

İyi cevap. Ancak bu son kısım zayıf olduğunu, kullanımını önermektedir LocalDateTime. Bu sınıf herhangi bir saat dilimi veya UTC'den sapma kavramından yoksundur. Bu nedenle, belirli bir yerde belirli bir günün ne zaman başladığını belirleyemez. Bu sınıf, gerçek dünyadaki günler için değil, yalnızca 24 saat açık genel günler için geçerlidir. Gerçek gün boyunca bir saat dilimi belirtin: ZonedDateTime zdt = now.atStartOfDay( ZoneId.of( "Asia/Tokyo" ) ) ;. Bazı yerlerdeki bazı günler, Yaz Saati Uygulaması (DST) gibi anormallikler nedeniyle 01:00 gibi farklı bir saatte başlayabilir.
Basil Bourque

35

Ve son günü Date nesnesi olarak almak için:

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

Date lastDayOfMonth = cal.getTime();

22

Takvimi bir sonraki ayın ilk gününe ayarlayabilir ve ardından bir gün çıkarabilirsiniz.

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

Bu kodu çalıştırdıktan sonra nextNotifTime geçerli ayın son gününe ayarlanacaktır. Bugün ayın son günü ise, bu kodun net etkisinin Takvim nesnesinin değişmeden kaldığını unutmayın.


17

Aşağıdakiler her zaman uygun sonuçlar verecektir:

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

Neden gerekli? Bana söyler misiniz :)
Frank Fang

1
Evet, yukarıdaki tam da bu nedenle testler başarısız oldu. Sorun, DAY_OF_MONTH ayarlanmadığı sürece, varsayılan olarak geçerli olacaktır.
ppearcy

7

java.timeBurada en son kütüphaneyi kullanmak en iyi çözümdür:

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

Alternatif olarak şunları yapabilirsiniz:

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


2

getActualMaximum(int field)Takvim nesnesinin yöntemine bakın .

Takvim nesnenizi son tarihi aradığınız ay getActualMaximum(Calendar.DAY_OF_MONTH)olacak şekilde ayarlarsanız, size son günü verir.


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 tarih uzatma uygulaması kullanarak 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
}

toEndOfMonthHer Date nesnesindeki işlevi aşağıdaki gibi çağırabilirsinizDate().toEndOfMonth()


4
Bu korkunç sınıflar, yıllar önce JSR 310'un benimsenmesiyle modern java.time sınıfları tarafından desteklendi . 2019'da bu eski sınıfları önermek kötü bir tavsiye.
Basil Bourque

Kötü bir tavsiye değil. Modern java.time , Android için yalnızca API 26+ için kullanılabilir. Eski cihazları desteklerken (öyle değil) hala java.util * 'e güveniyoruz .
Rafael Chagas
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.