user1746050
user1746050

Reputation: 2575

Get first and last day of month using threeten, LocalDate

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.

Upvotes: 193

Views: 200957

Answers (13)

Saurav Solanki
Saurav Solanki

Reputation: 11

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

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1499830

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

Upvotes: 278

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 78995

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.

Upvotes: 3

Viorel Stolea
Viorel Stolea

Reputation: 521

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

Upvotes: 7

dersu
dersu

Reputation: 300

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

Upvotes: 10

VSs
VSs

Reputation: 61

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

Upvotes: 1

Luis Roberto
Luis Roberto

Reputation: 472

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

Upvotes: 0

herman
herman

Reputation: 12305

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

Upvotes: 166

MrSmith42
MrSmith42

Reputation: 10151

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

Upvotes: 1

Anil Bhaskar
Anil Bhaskar

Reputation: 3978

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

Upvotes: 7

JodaStephen
JodaStephen

Reputation: 63365

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.

Upvotes: 223

Meno Hochschild
Meno Hochschild

Reputation: 44061

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

Upvotes: 29

Shekhar Rajput
Shekhar Rajput

Reputation: 27

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

Upvotes: 0

Related Questions