Get first and last day of month using threeten, LocalDate

JavaDateJava Time

Java Problem Overview


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.

Java Solutions


Solution 1 - Java

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

Solution 2 - Java

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.

Solution 3 - Java

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

Solution 4 - Java

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

Solution 5 - Java

 LocalDate monthstart = LocalDate.of(year,month,1);
 LocalDate monthend = monthstart.plusDays(monthstart.lengthOfMonth()-1);

Solution 6 - Java

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

Solution 7 - Java

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

Solution 8 - Java

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

Solution 9 - Java

Yet another solution for the last day of the month:

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

ONLINE DEMO

How does it work?

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.

Solution 10 - Java

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

Solution 11 - Java

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

Solution 12 - Java

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser1746050View Question on Stackoverflow
Solution 1 - JavaJon SkeetView Answer on Stackoverflow
Solution 2 - JavaJodaStephenView Answer on Stackoverflow
Solution 3 - JavahermanView Answer on Stackoverflow
Solution 4 - JavaMeno HochschildView Answer on Stackoverflow
Solution 5 - JavadersuView Answer on Stackoverflow
Solution 6 - JavaAnil BhaskarView Answer on Stackoverflow
Solution 7 - JavaViorel StoleaView Answer on Stackoverflow
Solution 8 - JavaVSsView Answer on Stackoverflow
Solution 9 - JavaArvind Kumar AvinashView Answer on Stackoverflow
Solution 10 - JavaMrSmith42View Answer on Stackoverflow
Solution 11 - JavaShekhar RajputView Answer on Stackoverflow
Solution 12 - JavaLuis RobertoView Answer on Stackoverflow