Получите первый и последний день месяца, используя threeten, LocalDate


127

У меня есть LocalDate, которому нужно получить первый и последний день месяца. Как я могу это сделать?

например. 13/2/2014 Мне нужно получить 1/2/2014и 28/2/2014в форматах LocalDate .

Использование трех десятков классов LocalDate.

Ответы:


182

Просто используйте withDayOfMonth, и lengthOfMonth():

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

3
К вашему сведению, я вижу другие ответы
assylias 08

147

API был разработан для поддержки решения, максимально соответствующего бизнес-требованиям.

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

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

Однако решения Джона тоже хороши.


5
В этом случае используются ресурсы API, специально созданные для решения этой конкретной проблемы.
jpangamarca

90

YearMonth

Для полноты и элегантности, на мой взгляд, см. Использование YearMonthкласса.

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

Для первого и последнего дня текущего месяца это будет:

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

8
Лучшее решение из всех.
Agustí Sánchez,

Дополнительная информация: YearMonth yearMonth = YearMonth.parse ("202004", DateTimeFormatter.ofPattern ("yyyyMM"));
egemen

в чем его преимущества по сравнению с LocalDate withметодом?
AndrewBloom

@AndrewBloom вам не нужно использовать статическую функцию для получения последнего дня месяца, и, по крайней мере, во втором примере вам не нужно иметь LocalDateэкземпляр для начала.
Herman

18

Ответ Джона Скитса правильный и заслужил мое одобрение, просто добавив это немного другое решение для полноты:

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
Уважаемый, отрицательный голос, честно говоря, я не понимаю отрицательного голоса, потому что мой ответ был даже на день раньше, чем ответ JodaStephen, и указал на в основном интересную новую часть, а именно на временный регулятор на конец месяца. То есть я ни у кого не «копировал» ответ.
Мено Хохшильд

Отличный ответ! Это решение лучше, потому что оно рекомендовано в документации : «... найти первый или последний день месяца»
peterchaula

4

Если кто-то приходит и ищет первый день предыдущего месяца и последний день предыдущего месяца :

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


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

Хороший код, но в ответе на переполнение стека следует учитывать особенности вопроса.
Basil Bourque

Спасибо, согласен. Иногда мы находим связанный код в потоке, поскольку я тоже искал его. Я как раз для таких пользователей ставил. Надеюсь, что все в порядке. Спасибо.
Анил Бхаскар

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

Опишите, пожалуйста, свой ответ
smilyface

1

Вы можете попробовать это, чтобы не указывать произвольную дату и если необходимо отображать даты начала и окончания текущего месяца:

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

Результат:

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

1
Мне это кажется немного сложным. Это тоже не дает правильного результата. Последний день этого месяца - 31 декабря 2019 года, но ваш фрагмент напечатан 30 декабря 2019 года.
Ole VV

0

Попробуй это:

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

вы можете найти желаемый результат, но вам нужно позаботиться о параметре true / false для метода getLastDayOfMonth

этот параметр обозначает високосный год


Нет необходимости использовать getLastDayOfMonth- см. Мой ответ для более простого подхода.
Джон Скит

0

если вы хотите сделать это только с 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

Просто здесь, чтобы показать мою реализацию решения @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();
}

LocalDateTime- это совершенно неправильный класс для использования здесь. Вы отбрасываете ценную информацию о зоне / смещении.
Basil

Вопрос запрашивает значение только даты, а не значения даты со временем, которые вы здесь ищете. И ужасный класс наследия Dateне имеет ничего общего с Вопросом, и его обычно следует избегать.
Basil

1
Для часового пояса Ла-Пас используйте более правильный ZoneId.of("America/La_Paz"). Для сегодняшних дат это даст тот же результат, но, возможно, не для исторических дат или дат в будущем.
Оле ВВ
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.