Get first and last day of month using threeten, LocalDate
Asked Answered
G

13

187

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.

Gilliam answered 6/3, 2014 at 11:55 Comment(1)
Use: LocalDate start = YearMonth.now().atDay(1); LocalDate end = YearMonth.now().atEndOfMonth(); OR: LocalDate startDay = Year.of(2020).atMonth(11).atDay(1); LocalDate endDay = Year.of(2020).atMonth(11).atEndOfMonth();Broadfaced
C
271

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()));
Chilli answered 6/3, 2014 at 12:0 Comment(1)
FYI see other answersTowrey
L
219

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.

Landsturm answered 7/3, 2014 at 1:47 Comment(1)
Going with this one, uses the API resources specifically made to handle this particular problem.Loup
T
162

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();
Teheran answered 18/4, 2018 at 9:21 Comment(6)
Best solution of all.Colpin
Extra info: YearMonth yearMonth = YearMonth.parse("202004",DateTimeFormatter.ofPattern("yyyyMM"));Ridglea
what are the advantages of it compared to LocalDate with method?Tantara
@Tantara you don't need to use a static function to get the last day of the month, and at least in the second example, you don't need to have a LocalDate instance to start with.Teheran
is there something similar for getting the first/last day of the week?Oriel
@Oriel if your week is Monday-to-Sunday, first day is date.with(previousOrSame(MONDAY)) (static import from TemporalAdjusters). Last day is date.with(nextOrSame(SUNDAY)). Sorry for the late response.Teheran
C
28

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());
Cheerio answered 6/3, 2014 at 14:22 Comment(2)
Dear downvoter, honestly, I don't understand the downvote because my answer was even one day before that of JodaStephen and pointed to the mainly interesting new part, namely the temporal adjuster for the end of month. That is I have not "copied" the answer from anyone else.Cheerio
Great answer! This solution is better because it's recommended in the docs: "...finding the first or last day of the month"Vermeil
M
10
 LocalDate monthstart = LocalDate.of(year,month,1);
 LocalDate monthend = monthstart.plusDays(monthstart.lengthOfMonth()-1);
Mitchiner answered 17/1, 2020 at 15:26 Comment(1)
Please describe your answerNausea
G
7

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);
    }
Giorgione answered 27/12, 2018 at 16:39 Comment(2)
Good code, but in Stack Overflow an Answer should address the specifics of the Question.Megalopolis
Thank you, I agree. Sometimes we find related code in the thread, as I came looking for this as well. I just put it for such users. Hope that is okay. Thanks.Giorgione
S
7
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
Sneaker answered 4/11, 2021 at 16:25 Comment(1)
I updated my response. see aboveSneaker
T
3

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.

Thurmond answered 5/11, 2021 at 17:54 Comment(0)
A
1

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);
Abiding answered 21/2, 2019 at 17:2 Comment(0)
C
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
Correct answered 4/12, 2019 at 12:49 Comment(2)
It seems a bit overcomplicated to me. It also doesn’t give the correct result. The last day of this month is 2019-12-31, but your snippet printed 2019-12-30.Rittenhouse
The answer itself is wrong, December ends on the 31st and not the 30th.Meagher
L
0

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

Lauraine answered 6/3, 2014 at 12:46 Comment(2)
There's no need to use getLastDayOfMonth - see my answer for a simpler approach.Chilli
@Shekhar Rajput The question is about LocalDate from JDK not from JODA! Pay more attention!Meagher
T
0

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();
}
Thimbu answered 21/9, 2019 at 3:24 Comment(4)
LocalDateTime is exactly the wrong class to be using here. You are discarding valuable zone/offset information.Megalopolis
The Question asks for a date-only value, not the date-with-time values you seek here. And the terrible legacy class Date has nothing to do with the Question, and should generally be avoided.Megalopolis
For La Paz time zone please use the more correct 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
well, atDay(firstDayOfMonth).atStartOfDay(); and atEndOfMonth().atTime(23, 59, 59) was exactly what i was searching for, thanks.Chausses
G
0

use withDayOfMonth. eg. LocalDateTime.now().withDayOfMonth(1) this will give start of the month.

Geez answered 4/8, 2022 at 10:40 Comment(2)
Thanks for wanting to contribute. When a 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
User was asking for LocalDate and not LocalDateTime please update your answer accordinglyBuatti

© 2022 - 2024 — McMap. All rights reserved.