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.

Respostas:


179

Basta usar withDayOfMonthe lengthOfMonth():

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

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.


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

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

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

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

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

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


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

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

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.