Obtenga el primer y último día del mes usando threeten, LocalDate

127

Tengo un LocalDate que debe obtener el primer y último día del mes. ¿Cómo puedo hacer eso?

p.ej. 13/2/2014 Necesito obtener 1/2/2014y 28/2/2014en formatos LocalDate .

Usando la clase Threeten LocalDate.

usuario1746050
fuente

Respuestas:

180

Solo usa withDayOfMonthy lengthOfMonth():

LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.withDayOfMonth(1);
LocalDate end = initial.withDayOfMonth(initial.lengthOfMonth());
Jon Skeet
fuente
3
Para su información vea otras respuestas
assylias
147

La API se diseñó para admitir una solución que se ajusta a los requisitos comerciales.

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

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

Sin embargo, las soluciones de Jon también están bien.

JodaStephen
fuente
5
Siguiendo con este, utiliza los recursos de la API creados específicamente para manejar este problema en particular.
jpangamarca
87

YearMonth

Para completar, y más elegante en mi opinión, vea este uso de YearMonthclase.

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

Para el primer y último día del mes actual, esto se convierte en:

LocalDate start = YearMonth.now().atDay(1);
LocalDate end   = YearMonth.now().atEndOfMonth();
Germán
fuente
8
La mejor solución de todas.
Agustí Sánchez
Información adicional: YearMonth yearMonth = YearMonth.parse ("202004", DateTimeFormatter.ofPattern ("aaaaMM"));
egemen
¿Cuáles son sus ventajas en comparación con el LocalDate withmétodo?
AndrewBloom
@AndrewBloom no necesita usar una función estática para obtener el último día del mes, y al menos en el segundo ejemplo, no necesita tener una LocalDateinstancia para comenzar.
herman
18

La respuesta de Jon Skeets es correcta y ha merecido mi voto a favor, simplemente agregando esta solución ligeramente diferente para completar:

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
fuente
2
Estimado votante en contra, honestamente, no entiendo el voto en contra porque mi respuesta fue incluso un día antes que la de JodaStephen y señaló la parte nueva principalmente interesante, a saber, el ajustador temporal para el final del mes. Es decir, no he "copiado" la respuesta de nadie más.
Meno Hochschild
¡Gran respuesta! Esta solución es mejor porque se recomienda en los documentos : "... encontrando el primer o último día del mes"
peterchaula
4

Si alguien viene buscando el primer día del mes anterior y el último día del mes 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
fuente
Buen código, pero en Stack Overflow una Respuesta debe abordar los detalles de la Pregunta.
Basil Bourque
Gracias, estoy de acuerdo. A veces encontramos código relacionado en el hilo, ya que vine a buscarlo también. Solo lo puse para tales usuarios. Espero que esté bien. Gracias.
Anil Bhaskar
3
 LocalDate monthstart = LocalDate.of(year,month,1);
 LocalDate monthend = monthstart.plusDays(monthstart.lengthOfMonth()-1);
dersu
fuente
Por favor describa su respuesta
smilyface
1

Puede intentar esto para evitar indicar una fecha personalizada y si es necesario mostrar las fechas de inicio y finalización del mes actual:

    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
VS
fuente
1
Me parece un poco complicado. Tampoco da el resultado correcto. El último día de este mes es 2019-12-31, pero su fragmento impreso 2019-12-30.
Ole VV
0

Prueba esto:

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

puede encontrar la salida deseada pero debe cuidar el parámetro true / false para el método getLastDayOfMonth

ese parámetro denota año bisiesto

Shekhar Rajput
fuente
No es necesario usarlo getLastDayOfMonth; vea mi respuesta para un enfoque más simple.
Jon Skeet
0

si desea hacerlo solo con la clase 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
fuente
0

Solo aquí para mostrar mi implementación para la solución @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
fuente
LocalDateTimees exactamente la clase incorrecta para usar aquí. Está descartando información valiosa de zona / compensación.
Basil Bourque
La pregunta solicita un valor de solo fecha, no los valores de fecha con hora que busca aquí. Y la terrible clase del legado Dateno tiene nada que ver con la Pregunta y, en general, debería evitarse.
Basil Bourque
1
Para la zona horaria de La Paz, utilice la más correcta ZoneId.of("America/La_Paz"). Para las fechas actuales dará el mismo resultado, pero tal vez no para fechas históricas o fechas en un futuro posterior.
Ole VV