Uzyskaj pierwszy i ostatni dzień miesiąca za pomocą trzynaście, LocalDate


127

Mam LocalDate, który musi otrzymać pierwszy i ostatni dzień miesiąca. W jaki sposób mogę to zrobić?

na przykład. 13/2/2014 Muszę pobrać 1/2/2014i 28/2/2014w formatach LocalDate .

Korzystanie z trzech klas LocalDate.

Odpowiedzi:


180

Po prostu użyj withDayOfMonthi lengthOfMonth():

LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.withDayOfMonth(1);
LocalDate end = initial.withDayOfMonth(initial.lengthOfMonth());

3
FYI zobacz inne odpowiedzi
assylias

147

Interfejs API został zaprojektowany do obsługi rozwiązania, które jest ściśle dopasowane do wymagań biznesowych

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

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

Jednak rozwiązania Jona są również w porządku.


5
Idąc z tym, wykorzystuje zasoby API specjalnie stworzone do obsługi tego konkretnego problemu.
jpangamarca,

90

YearMonth

Aby uzyskać kompletność i moim zdaniem bardziej eleganckie, zobacz użycie YearMonthklasy.

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

Dla pierwszego i ostatniego dnia bieżącego miesiąca jest to:

LocalDate start = YearMonth.now().atDay(1);
LocalDate end   = YearMonth.now().atEndOfMonth();

8
Najlepsze rozwiązanie ze wszystkich.
Agustí Sánchez

Dodatkowe informacje: YearMonth yearMonth = YearMonth.parse ("202004", DateTimeFormatter.ofPattern ("rrrrMM"));
egemen

jakie są zalety tego w porównaniu z LocalDate withmetodą?
AndrewBloom,

@AndrewBloom nie musisz używać funkcji statycznej, aby uzyskać ostatni dzień miesiąca, a przynajmniej w drugim przykładzie nie musisz mieć LocalDateinstancji, aby zacząć.
herman

18

Odpowiedź Jona Skeetsa jest poprawna i zasłużyła na moją opinię, dodając tylko to nieco inne rozwiązanie dla kompletności:

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

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

2
Drogi przeciwniku, szczerze mówiąc, nie rozumiem negatywnego głosu, ponieważ moja odpowiedź była nawet jeden dzień wcześniej niż JodaStephen i wskazywała na głównie interesującą nową część, a mianowicie regulator czasowy na koniec miesiąca. To znaczy, że nie „skopiowałem” odpowiedzi od nikogo innego.
Meno Hochschild

Świetna odpowiedź! To rozwiązanie jest lepsze, ponieważ jest zalecane w dokumentach : „... znalezienie pierwszego lub ostatniego dnia miesiąca”
peterchaula

4

Jeśli ktoś przyjdzie szukać pierwszego dnia poprzedniego miesiąca i ostatniego dnia poprzedniego miesiąca :

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


public static LocalDate lastDayOfPreviousMonth(LocalDate date) {
        return date.withDayOfMonth(1).minusDays(1);
    }

Dobry kod, ale w przepełnieniu stosu odpowiedź powinna odnosić się do specyfiki pytania.
Basil Bourque

Dziękuję, zgadzam się. Czasami znajdujemy powiązany kod w wątku, ponieważ również tego szukałem. Po prostu umieściłem to dla takich użytkowników. Mam nadzieję, że wszystko w porządku. Dzięki.
Anil Bhaskar

3
 LocalDate monthstart = LocalDate.of(year,month,1);
 LocalDate monthend = monthstart.plusDays(monthstart.lengthOfMonth()-1);

Proszę opisz swoją odpowiedź
smilyface

1

Możesz spróbować tego, aby uniknąć wskazywania niestandardowej daty i jeśli istnieje potrzeba wyświetlenia daty rozpoczęcia i zakończenia bieżącego miesiąca:

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

Wynik:

>     Start of month: 2019-12-01
>     End of month: 2019-12-30

1
Wydaje mi się to trochę zbyt skomplikowane. Nie daje też prawidłowego wyniku. Ostatni dzień tego miesiąca to 31.12.2019, ale Twój fragment zostanie wydrukowany 30.12.2019.
Ole VV

0

Spróbuj tego:

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

możesz znaleźć pożądane wyjście, ale musisz zadbać o parametr true / false dla metody getLastDayOfMonth

ten parametr oznacza rok przestępny


Nie ma potrzeby używania getLastDayOfMonth- zobacz moją odpowiedź, aby uzyskać prostsze podejście.
Jon Skeet

0

jeśli chcesz to zrobić tylko z klasą 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);

0

Tylko tutaj, aby pokazać moją implementację rozwiązania @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();
}

LocalDateTimejest dokładnie niewłaściwą klasą do użycia w tym miejscu. Odrzucasz cenne informacje o strefie / przesunięciu.
Basil Bourque

Pytanie zawiera tylko wartość daty, a nie wartości daty i czasu, których tutaj szukasz. A okropna klasa dziedzictwa Datenie ma nic wspólnego z pytaniem i generalnie należy jej unikać.
Basil Bourque

1
Dla strefy czasowej La Paz użyj bardziej poprawnej ZoneId.of("America/La_Paz"). Dla dat dzisiejszych da ten sam wynik, ale może nie dla dat historycznych lub dat w dalszej przyszłości.
Ole VV
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.