Dapatkan hari pertama dan terakhir bulan menggunakan tiga, LocalDate

127

Saya memiliki LocalDate yang perlu mendapatkan hari pertama dan terakhir setiap bulan. Bagaimana aku melakukan itu?

misalnya. 13/2/2014 Saya perlu mendapatkan 1/2/2014dan 28/2/2014dalam format LocalDate .

Menggunakan tiga kelas LocalDate.

pengguna1746050
sumber

Jawaban:

180

Cukup gunakan withDayOfMonth, dan lengthOfMonth():

LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.withDayOfMonth(1);
LocalDate end = initial.withDayOfMonth(initial.lengthOfMonth());
Jon Skeet
sumber
3
FYI melihat jawaban lain
assylias
147

API dirancang untuk mendukung solusi yang sesuai dengan kebutuhan bisnis

import static java.time.temporal.TemporalAdjusters.*;

LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.with(firstDayOfMonth());
LocalDate end = initial.with(lastDayOfMonth());

Namun, solusi Jon juga bagus.

JodaStephen
sumber
5
Dengan yang ini, menggunakan sumber daya API yang secara khusus dibuat untuk menangani masalah khusus ini.
jpangamarca
87

YearMonth

Untuk kelengkapan, dan lebih elegan menurut saya, lihat penggunaan YearMonthclass ini.

YearMonth month = YearMonth.from(date);
LocalDate start = month.atDay(1);
LocalDate end   = month.atEndOfMonth();

Untuk hari pertama & terakhir bulan ini, ini menjadi:

LocalDate start = YearMonth.now().atDay(1);
LocalDate end   = YearMonth.now().atEndOfMonth();
herman
sumber
8
Solusi terbaik dari semuanya.
Agustí Sánchez
Info tambahan: YearMonth yearMonth = YearMonth.parse ("202004", DateTimeFormatter.ofPattern ("yyyyMM"));
egemen
Apa kelebihannya dibandingkan dengan LocalDate withmetode?
AndrewBloom
@AndrewBloom Anda tidak perlu menggunakan fungsi statis untuk mendapatkan hari terakhir setiap bulan, dan setidaknya di contoh kedua, Anda tidak perlu memiliki LocalDateinstance untuk memulai.
herman
18

Jawaban Jon Skeets benar dan pantas mendapat suara positif saya, hanya menambahkan solusi yang sedikit berbeda ini untuk kelengkapan:

import static java.time.temporal.TemporalAdjusters.lastDayOfMonth;

LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.withDayOfMonth(1);
LocalDate end = initial.with(lastDayOfMonth());
Meno Hochschild
sumber
2
Dear downvoter, sejujurnya, saya tidak mengerti downvote karena jawaban saya bahkan satu hari sebelum JodaStephen dan menunjuk pada part baru yang paling menarik, yaitu temporal adjuster untuk akhir bulan. Artinya saya belum "menyalin" jawaban dari orang lain.
Meno Hochschild
Jawaban yang bagus! Solusi ini lebih baik karena direkomendasikan di dokumen : "... menemukan hari pertama atau terakhir setiap bulan"
peterchaula
4

Jika ada yang datang mencari hari pertama bulan sebelumnya dan hari terakhir bulan sebelumnya :

public static LocalDate firstDayOfPreviousMonth(LocalDate date) {
        return date.minusMonths(1).withDayOfMonth(1);
    }


public static LocalDate lastDayOfPreviousMonth(LocalDate date) {
        return date.withDayOfMonth(1).minusDays(1);
    }
Anil Bhaskar
sumber
Kode yang bagus, tetapi dalam Stack Overflow, sebuah Answer harus membahas pertanyaan spesifik.
Basil Bourque
Terima kasih, saya setuju. Terkadang kami menemukan kode terkait di utas, karena saya juga mencari ini. Saya hanya menaruhnya untuk pengguna seperti itu. Semoga tidak apa-apa. Terima kasih.
Anil Bhaskar
3
 LocalDate monthstart = LocalDate.of(year,month,1);
 LocalDate monthend = monthstart.plusDays(monthstart.lengthOfMonth()-1);
dersu
sumber
Tolong jelaskan jawaban Anda
wajah tersenyum
1

Anda dapat mencoba ini untuk menghindari menunjukkan tanggal kustom dan jika perlu menampilkan tanggal mulai dan akhir bulan ini:

    LocalDate start = LocalDate.now().minusDays(LocalDate.now().getDayOfMonth()-1);
    LocalDate end = LocalDate.now().minusDays(LocalDate.now().getDayOfMonth()).plusMonths(1);
    System.out.println("Start of month: " + start);
    System.out.println("End of month: " + end);

Hasil:

>     Start of month: 2019-12-01
>     End of month: 2019-12-30
VSs
sumber
1
Sepertinya agak terlalu rumit bagiku. Itu juga tidak memberikan hasil yang benar. Hari terakhir bulan ini adalah 31-12-2019, tetapi cuplikan Anda dicetak pada 2019-12-30.
Ole VV
0

Coba ini:

LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.withDayOfMonth(1);         
LocalDate end = initial.withDayOfMonth(initial.getMonthOfYear().getLastDayOfMonth(false));
System.out.println(start);
System.out.println(end);

Anda dapat menemukan keluaran yang diinginkan tetapi perlu menjaga parameter true / false untuk metode getLastDayOfMonth

parameter itu menunjukkan tahun kabisat

Shekhar Rajput
sumber
Tidak perlu menggunakan getLastDayOfMonth- lihat jawaban saya untuk pendekatan yang lebih sederhana.
Jon Skeet
0

jika Anda ingin melakukannya hanya dengan kelas LocalDate:

LocalDate initial = LocalDate.of(2014, 2, 13);

LocalDate start = LocalDate.of(initial.getYear(), initial.getMonthValue(),1);

// Idea: the last day is the same as the first day of next month minus one day.
LocalDate end = LocalDate.of(initial.getYear(), initial.getMonthValue(), 1).plusMonths(1).minusDays(1);
MrSmith42
sumber
0

Hanya di sini untuk menunjukkan implementasi saya untuk solusi @herman

ZoneId americaLaPazZone = ZoneId.of("UTC-04:00");

static Date firstDateOfMonth(Date date) {
  LocalDate localDate = convertToLocalDateWithTimezone(date);
  YearMonth baseMonth = YearMonth.from(localDate);
  LocalDateTime initialDate = baseMonth.atDay(firstDayOfMonth).atStartOfDay();
  return Date.from(initialDate.atZone(americaLaPazZone).toInstant());
}

static Date lastDateOfMonth(Date date) {
  LocalDate localDate = convertToLocalDateWithTimezone(date);
  YearMonth baseMonth = YearMonth.from(localDate);
  LocalDateTime lastDate = baseMonth.atEndOfMonth().atTime(23, 59, 59);
  return Date.from(lastDate.atZone(americaLaPazZone).toInstant());
}

static LocalDate convertToLocalDateWithTimezone(Date date) {
  return LocalDateTime.from(date.toInstant().atZone(americaLaPazZone)).toLocalDate();
}
Luis Roberto
sumber
LocalDateTimeadalah kelas yang salah untuk digunakan di sini. Anda membuang informasi zona / offset yang berharga.
Basil Bourque
Pertanyaan meminta nilai tanggal-saja, bukan nilai tanggal-dengan-waktu yang Anda cari di sini. Dan kelas warisan yang mengerikan Datetidak ada hubungannya dengan Pertanyaan tersebut, dan umumnya harus dihindari.
Basil Bourque
1
Untuk zona waktu La Paz, gunakan yang lebih tepat ZoneId.of("America/La_Paz"). Untuk tanggal hari ini akan memberikan hasil yang sama, tetapi mungkin tidak untuk tanggal bersejarah atau tanggal di masa mendatang.
Ole VV