Получите первый и последний день месяца, используя 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.