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.

user1746050
źródło

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());
Jon Skeet
źródło
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.

JodaStephen
źródło
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();
Hermana
źródło
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());
Meno Hochschild
źródło
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);
    }
Anil Bhaskar
źródło
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);
dersu
źródło
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
VS
źródło
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

Shekhar Rajput
źródło
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);
MrSmith42
źródło
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();
}
Luis Roberto
źródło
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