Obtenha o primeiro e o último dia do mês usando três, LocalDate

126

Eu tenho um LocalDate que precisa ser o primeiro e o último dia do mês. Como faço isso?

por exemplo. 13/2/2014 Eu preciso obter 1/2/2014e 28/2/2014nos formatos LocalDate .

Usando três classes LocalDate.

user1746050
fonte

Respostas:

179

Basta usar withDayOfMonthe lengthOfMonth():

LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.withDayOfMonth(1);
LocalDate end = initial.withDayOfMonth(initial.lengthOfMonth());
Jon Skeet
fonte
3
Para sua informação, vejo outras respostas
assylias
147

A API foi projetada para oferecer suporte a uma solução que corresponda intimamente aos requisitos de negócios

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

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

No entanto, as soluções de Jon também são boas.

JodaStephen
fonte
5
Indo com este, usa os recursos da API feitos especificamente para lidar com este problema específico.
jpangamarca
87

YearMonth

Para completude, e mais elegante na minha opinião, veja este uso de YearMonthclasse.

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

Para o primeiro e último dia do mês atual, isso se torna:

LocalDate start = YearMonth.now().atDay(1);
LocalDate end   = YearMonth.now().atEndOfMonth();
Herman
fonte
8
Melhor solução de todas.
Agustí Sánchez
Informações extras: YearMonth yearMonth = YearMonth.parse ("202004", DateTimeFormatter.ofPattern ("aaaaMM"));
egemen
quais são as vantagens disso em comparação com o LocalDate withmétodo?
AndrewBloom
@AndrewBloom você não precisa usar uma função estática para obter o último dia do mês, e pelo menos no segundo exemplo, você não precisa ter um LocalDate instância para começar.
herman
18

A resposta de Jon Skeets está certa e mereceu meu voto positivo, apenas adicionando esta solução ligeiramente diferente para completude:

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
fonte
2
Caro downvoter, honestamente, não entendo o downvote porque minha resposta foi até um dia antes da de JodaStephen e apontou para a parte nova principalmente interessante, ou seja, o ajustador temporal para o final do mês. Isto é, não "copiei" a resposta de mais ninguém.
Meno Hochschild
Ótima resposta! Esta solução é melhor porque é recomendada na documentação : "... encontrando o primeiro ou último dia do mês"
peterchaula
4

Se alguém vier procurar o primeiro dia do mês anterior e o último dia do mês anterior :

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
fonte
Bom código, mas no Stack Overflow uma resposta deve abordar os detalhes da pergunta.
Basil Bourque
Obrigado, eu concordo. Às vezes, encontramos código relacionado na discussão, pois também vim procurando por isso. Acabei de colocá-lo para esses usuários. Espero que esteja tudo bem. Obrigado.
Anil Bhaskar
3
 LocalDate monthstart = LocalDate.of(year,month,1);
 LocalDate monthend = monthstart.plusDays(monthstart.lengthOfMonth()-1);
Dersu
fonte
Descreva sua resposta
smilyface
1

Você pode tentar fazer isso para evitar a indicação de data personalizada e se houver necessidade de exibir as datas de início e término do mês atual:

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

Resultado:

>     Start of month: 2019-12-01
>     End of month: 2019-12-30
VSs
fonte
1
Parece um pouco complicado demais para mim. Também não dá o resultado correto. O último dia deste mês é 31/12/2019, mas seu snippet foi impresso em 30/12/2019.
Ole VV
0

Experimente isto:

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

você pode encontrar a saída desejada, mas precisa cuidar do parâmetro true / false para getLastDayOfMonth método

esse parâmetro denota ano bissexto

Shekhar Rajput
fonte
Não há necessidade de usar getLastDayOfMonth- veja minha resposta para uma abordagem mais simples.
Jon Skeet
0

se você quiser fazer isso apenas com a classe 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
fonte
0

Só aqui para mostrar minha implementação para a solução @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
fonte
LocalDateTimeé exatamente a classe errada para usar aqui. Você está descartando informações valiosas de zona / deslocamento.
Basil Bourque
A pergunta pede um valor apenas de data, não os valores de data com hora que você procura aqui. E a terrível classe de legado Datenão tem nada a ver com a Questão e geralmente deve ser evitada.
Basil Bourque
1
Para o fuso horário de La Paz, use o mais correto ZoneId.of("America/La_Paz"). Para as datas atuais, ele dará o mesmo resultado, mas talvez não para datas históricas ou datas em um futuro futuro.
Ole VV