I have a LocalDate which needs to get the first and last day of the month. How do I do that?
eg. 13/2/2014
I need to get 1/2/2014
and 28/2/2014
in LocalDate formats.
Using threeten LocalDate class.
I have a LocalDate which needs to get the first and last day of the month. How do I do that?
eg. 13/2/2014
I need to get 1/2/2014
and 28/2/2014
in LocalDate formats.
Using threeten LocalDate class.
Just use withDayOfMonth
, and lengthOfMonth()
:
LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.withDayOfMonth(1);
LocalDate end = initial.withDayOfMonth(initial.getMonth().length(initial.isLeapYear()));
The API was designed to support a solution that matches closely to business requirements
import static java.time.temporal.TemporalAdjusters.*;
LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.with(firstDayOfMonth());
LocalDate end = initial.with(lastDayOfMonth());
However, Jon's solutions are also fine.
YearMonth
For completeness, and more elegant in my opinion, see this use of YearMonth
class.
YearMonth month = YearMonth.from(date);
LocalDate start = month.atDay(1);
LocalDate end = month.atEndOfMonth();
For the first & last day of the current month, this becomes:
LocalDate start = YearMonth.now().atDay(1);
LocalDate end = YearMonth.now().atEndOfMonth();
LocalDate
with
method? –
Tantara LocalDate
instance to start with. –
Teheran date.with(previousOrSame(MONDAY))
(static import from TemporalAdjusters). Last day is date.with(nextOrSame(SUNDAY))
. Sorry for the late response. –
Teheran Jon Skeets answer is right and has deserved my upvote, just adding this slightly different solution for completeness:
import static java.time.temporal.TemporalAdjusters.lastDayOfMonth;
LocalDate initial = LocalDate.of(2014, 2, 13);
LocalDate start = initial.withDayOfMonth(1);
LocalDate end = initial.with(lastDayOfMonth());
LocalDate monthstart = LocalDate.of(year,month,1);
LocalDate monthend = monthstart.plusDays(monthstart.lengthOfMonth()-1);
If anyone comes looking for first day of previous month and last day of previous month:
public static LocalDate firstDayOfPreviousMonth(LocalDate date) {
return date.minusMonths(1).withDayOfMonth(1);
}
public static LocalDate lastDayOfPreviousMonth(LocalDate date) {
return date.withDayOfMonth(1).minusDays(1);
}
LocalDate endDate = startDate.withDayOfMonth(1).plusMonths(1).minusDays(1);
or
LocalDate startDate = LocalDate.now();
System.out.println("startDate: "+startDate);
LocalDate firstDayOfMonth_of_startDate = startDate.withDayOfMonth(1);
System.out.println("firstDayOfMonth_of_startDate: "+firstDayOfMonth_of_startDate);
LocalDate firstDayOfNextMonth_of_startDate = firstDayOfMonth_of_startDate.plusMonths(1);
System.out.println("firstDayOfNextMonth_of_startDate: "+firstDayOfNextMonth_of_startDate);
LocalDate lastDayOfTheMonth_of_startDate = firstDayOfNextMonth_of_startDate.minusDays(1);
System.out.println("lastDayOfTheMonth_of_startDate: "+lastDayOfTheMonth_of_startDate);
// or everything in one line
LocalDate endDate = startDate.withDayOfMonth(1).plusMonths(1).minusDays(1);
System.out.println("endDate: "+endDate);
and the printouts
startDate: 2021-11-05
firstDayOfMonth_of_startDate: 2021-11-01
firstDayOfNextMonth_of_startDate: 2021-12-01
lastDayOfTheMonth_of_startDate: 2021-11-30
endDate: 2021-11-30
I have written this answer just for learners who want to learn by playing with various options. I do not recommend it for production use.
import java.time.LocalDate;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
//Test
System.out.println(lastDateOfMonth(LocalDate.of(2014, 1, 13)));
System.out.println(lastDateOfMonth(LocalDate.of(2014, 2, 13)));
System.out.println(lastDateOfMonth(LocalDate.of(2016, 2, 13)));
System.out.println(lastDateOfMonth(LocalDate.of(2014, 4, 13)));
}
static LocalDate lastDateOfMonth(LocalDate date) {
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.parseDefaulting(ChronoField.DAY_OF_MONTH, 31)
.appendPattern("uuuu-MM")
.toFormatter(Locale.ENGLISH);
return LocalDate.parse(YearMonth.from(date).toString(), dtf);
}
}
Output:
2014-01-31
2014-02-28
2016-02-29
2014-04-30
The function, YearMonth#toString
returns a string in the format, uuuu-MM
, the format I have used with the DateTimeFormatterBuilder
. I have defaulted the ChronoField.DAY_OF_MONTH
to 31, the maximum number of days a month can have, and this works for all months.
Learn more about the modern Date-Time API* from Trail: Date Time.
* If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring. Note that Android 8.0 Oreo already provides support for java.time
. Check this answer and this answer to learn how to use java.time
API with JDBC.
if you want to do it only with the LocalDate-class:
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);
You can try this to avoid indicating custom date and if there is need to display start and end dates of current month:
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);
Result:
> Start of month: 2019-12-01
> End of month: 2019-12-30
Try this:
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);
you can find the desire output but need to take care of parameter true/false for getLastDayOfMonth method
that parameter denotes leap year
getLastDayOfMonth
- see my answer for a simpler approach. –
Chilli Just here to show my implementation for @herman solution
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
is exactly the wrong class to be using here. You are discarding valuable zone/offset information. –
Megalopolis Date
has nothing to do with the Question, and should generally be avoided. –
Megalopolis ZoneId.of("America/La_Paz")
. For present-day dates it will give the same result, but maybe not for historic dates or dates in a further future. –
Rittenhouse atDay(firstDayOfMonth).atStartOfDay();
and atEndOfMonth().atTime(23, 59, 59)
was exactly what i was searching for, thanks. –
Chausses use withDayOfMonth. eg. LocalDateTime.now().withDayOfMonth(1) this will give start of the month.
LocalDate
was asked about, what would be the point of using a LocalDateTime
instead? You will be getting a time on the first day of the month, but if one intended the start of that day, you are not getting that. –
Rittenhouse © 2022 - 2024 — McMap. All rights reserved.