Reputation: 340
I am having quarter end date of last quarter let it be 30-09-20
, the requirement is to find end date of next quarter i.e 31-12-20
. I am using below code to do the same but is it giving wrong output in some scenarios. This solution should be correct for all quarters.
String str = "30-09-20";
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yy");
Date date = format.parse(str);
Date newDate = DateUtils.addMonths(date, 3);
System.out.println(newDate);//Dec 30 - It should be 31 Dec
Upvotes: 5
Views: 5070
Reputation: 338181
Use YearQuarter
class from ThreeTen-Extra.
YearQuarter // A class available in the ThreeTen-Extra library.
.from( // Factory method rather than calling `new`.
LocalDate.of( 2020 , Month.SEPTEMBER , 30 ) // Returns a `LocalDate` object, represent a date-only value without a time-of-day and without a time zone.
) // Returns a `YearQuarter` object.
.plusQuarters( 1 ) // Perform date-math, resulting in a new `YearQuarter` object (per immutable objects pattern).
.atEndOfQuarter() // Determine the date of last day of this year-quarter.
.toString() // Generate text in standard ISO 8601 format.
2020-12-31
org.threeten.extra.YearQuarter
The ThreeTen-Extra library provides classes that extend the functionality of the java.time classes built into Java 8 and later. One of its classes is YearQuarter
to represent a specific quarter in a specific year. The quarters are defined by calendar-year: Jan-Mar, Apr-June, July-Sept, Oct-Dec.
LocalDate localDate = LocalDate.of( 2020 , Month.SEPTEMBER , 30 ) ;
YearQuarter yearQuarter = YearQuarter.from( localDate ) ;
Move to the next quarter by adding one quarter to our current year-quarter.
The java.time and ThreeTen-Extra classes use immutable objects. So rather than alter ("mutate") the original object, when adding we produce a new object.
YearQuarter followingYearQuarter = yearQuarter.plusQuarters( 1 ) ;
Determine the last day of that quarter.
LocalDate lastDateOfFollowingYearQuarter = followingYearQuarter.atEndOfQuarter() ;
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.*
classes.
Where to obtain the java.time classes?
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval
, YearWeek
, YearQuarter
, and more.
Upvotes: 5
Reputation: 24443
Here is my version (hopefully more readable) of finding the last day of next quarter for any date:
public LocalDate lastDayOfNextQuarter(LocalDate date) {
Month firstMonthOfCurrentQuarter = date.getMonth().firstMonthOfQuarter();
LocalDate lastMonthOfCurrentQuarter = date.with(firstMonthOfCurrentQuarter.plus(2));
LocalDate lastMonthOfNextQuarter = lastMonthOfCurrentQuarter.plusMonths(3);
return lastMonthOfNextQuarter.with(lastDayOfMonth());
}
And a corresponding test method:
@ParameterizedTest
@CsvSource({"2020-01-01,2020-06-30", "2020-02-01,2020-06-30", "2020-03-01,2020-06-30", "2020-04-10,2020-09-30",
"2020-05-10,2020-09-30", "2020-06-10,2020-09-30", "2020-07-20,2020-12-31", "2020-08-20,2020-12-31",
"2020-09-30,2020-12-31", "2020-10-30,2021-03-31", "2020-11-30,2021-03-31", "2020-12-31,2021-03-31"})
public void testLastDayOfNextQuarter(LocalDate input, LocalDate expected) {
LocalDate result = timeUtils.lastDayOfNextQuarter(input);
assertEquals(expected, result);
}
Upvotes: 2
Reputation: 59950
To answer your question, I think you are looking for this :
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yy");
LocalDate end = LocalDate.parse("30-09-20", formatter)
.plusMonths(3) // add three months to your date
.with(TemporalAdjusters.lastDayOfMonth()); // with the last day of the month
Note: don't use the legacy Date library, you tagged your question Java-8 which mean you can use java-time API.
@deHaar have reason, to get the end date of curent quarter, I would suggest to use :
public LocalDate lastDayFromDateQuarter(String date) {
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yy");
LocalDate ld = LocalDate.parse(date, formatter);
int quarter = ld.get(IsoFields.QUARTER_OF_YEAR); // Get the Quarter, 1, 2, 3, 4
// Then create a new date with new quarter * 3 and last day of month
return ld.withMonth(quarter * 3).with(TemporalAdjusters.lastDayOfMonth());
}
To get the last day of the next quarter, then you just can add three months to your date like so :
public static LocalDate lastDayFromDateQuarter(String date) {
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yy");
LocalDate ld = LocalDate.parse(date, formatter);
int quarter = ld.get(IsoFields.QUARTER_OF_YEAR);
return ld.withMonth(quarter * 3)
.plusMonths(3)
.with(TemporalAdjusters.lastDayOfMonth());
}
Upvotes: 12
Reputation: 862
You can use a Calendar instance to get the last day of the month.
String str = "30-12-20";
SimpleDateFormat format = new SimpleDateFormat("dd-MM-yy");
Date date = format.parse(str);
Date newDate = DateUtils.addMonths(date, 3);
Calendar cal = new GregorianCalendar();
cal.setTime(newDate);
System.out.println(cal.getActualMaximum(Calendar.DAY_OF_MONTH));
Upvotes: 0
Reputation: 1512
You can manipulate quarter easily with TemporalAdjusters. See below:
LocalDate localDate = LocalDate.now();
LocalDate firstDayOfQuarter = localDate.with(IsoFields.DAY_OF_QUARTER, 1);
System.out.println(firstDayOfQuarter);
LocalDate lastDayOfQuarter = firstDayOfQuarter.plusMonths(2).with(TemporalAdjusters.lastDayOfMonth());
System.out.println(lastDayOfQuarter);
LocalDate firstDateOfNextQuarter = lastDayOfQuarter.plusDays(1);
LocalDate lastDayOfNextQuarter = firstDateOfNextQuarter.plusMonths(2).with(TemporalAdjusters.lastDayOfMonth());
System.out.println(lastDayOfNextQuarter);
Output:
2020-01-01
2020-03-31
2020-06-30
Upvotes: 1