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

127

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

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

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

user1746050
источник

Ответы:

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

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

JodaStephen
источник
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
Vss
источник
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);
MrSmith42
источник
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"). Для сегодняшних дат это даст тот же результат, но, возможно, не для исторических дат или дат в будущем.
Оле ВВ