How to get the first date and last date of current quarter in java.util.Date
As others mentioned, you are using outmoded classes. Sun/Oracle decided to supplant the old date-time classes with the java.time framework, a vast improvement.
Avoid the old date-time classes. They really are poorly designed, confusing, and troublesome.
java.time
The java.time framework is built into Java 8. For Java 6 & 7, use the back-port, ThreeTen-Backport. For Android, the adaptation of that back-port, ThreeTenABP.
The java.time framework is inspired by the highly successful Joda-Time library, defined by JSR 310, and extended by the ThreeTen-Extra project. See Oracle Tutorial.
LocalDate
For a date-only value, without time-of-day and without time zone, use LocalDate
built-in as part of java.time. To get the current date requires a time zone as the date varies around the world (a new day dawns earlier in the east).
ZoneId zoneId = ZoneId.of ( "America/Montreal" );
LocalDate today = LocalDate.now ( zoneId );
Quarter
& YearQuarter
The ThreeTen-Extra project mentioned above serves as the proving ground for possible future features to be added to java.time. To use this library, add its jar file to your project (or use Maven etc.). If you really don’t want to add a library, see an alternate solution Answer by dheeran.
This library currently includes the Quarter
and YearQuarter
classes that you might find particularly useful. Safer to pass around objects of these types in your code rather than use strings and numbers to represent your quarters.
YearQuarter currentQuarter = YearQuarter.now ( zoneId );
The YearQuarter
has many useful methods, including asking for its dates.
LocalDate start = currentQuarter.atDay ( 1 );
LocalDate stop = currentQuarter.atEndOfQuarter ();
Dump to console.
System.out.println ( "today: " + today + " currentQuarter: " + currentQuarter + " start: " + start + " stop: " + stop );
today: 2016-04-08 currentQuarter: 2016-Q2 start: 2016-04-01 stop: 2016-06-30
If you really do not want to add the ThreeTen-Extra library as I recommended, see the Answer by Pavel for another solution using only the built-in java.time classes. But if you are doing much work with quarters, I am sure you’ll find ThreeTen-Extra to be well worth the trouble of adding a library to your project.
Conversion
If you must use java.util.Date to work with old code not yet updated to java.time, you can convert back and forth. Find new methods added to the old classes for conversion.
Unfortunately, the old classes lack any clean way to represent a date-only value. So there is no perfectly clean way to go to/from a LocalDate
.
java.sql.Date
The java.sql.Date
class pretends to be a date-only but actually contains a time-of-day adjusted to 00:00:00.0
. This class awkwardly inherits from java.util.Date
but the doc clearly warns against using that fact; you are supposed to treat the two as separate unrelated classes.
java.sql.Date sqlDate_quarterStart = java.sql.Date.valueOf( start );
java.util.Date
A java.util.Date
represents both a date and time-of-day, effectively in UTC. We can first adjust our LocalDate
into the first moment of a day to get a date with time-of-day, a ZonedDateTime
. From there we can ask for an Instant
which is a moment on the timeline in UTC. The old .Date class has a static from( Instant )
conversion method.
ZonedDateTime zdt = start.atStartOfDay( zoneId ); // First moment of the day on a certain date.
Instant instant = zdt.toInstant(); // Moment on the timeline in UTC.
java.util.Date utilDate = java.util.Date.from( instant );
About java.time
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
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
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?
- Java SE 8, Java SE 9, Java SE 10, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
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.
It's pretty simple with LocalDate
LocalDate inputDate = LocalDate.parse("2018-09-04");
LocalDate firstDayOfQuarter = inputDate.withMonth(inputDate.get(IsoFields.QUARTER_OF_YEAR) * 3 - 2).with(TemporalAdjusters.firstDayOfMonth());
LocalDate lastDayOfQuarter = inputDate.withMonth(inputDate.get(IsoFields.QUARTER_OF_YEAR) * 3).with(TemporalAdjusters.lastDayOfMonth());
Cheers!
Pure Java-8+ solution:
LocalDate localDate = LocalDate.now();
LocalDate firstDayOfQuarter = localDate.with(localDate.getMonth().firstMonthOfQuarter())
.with(TemporalAdjusters.firstDayOfMonth());
LocalDate lastDayOfQuarter = firstDayOfQuarter.plusMonths(2)
.with(TemporalAdjusters.lastDayOfMonth());
Here is solution in Java 7 or older (otherwise, I suggest to check other answers):
private static Date getFirstDayOfQuarter(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.MONTH, cal.get(Calendar.MONTH)/3 * 3);
return cal.getTime();
}
private static Date getLastDayOfQuarter(Date date) {
Calendar cal = Calendar.getInstance();
cal.setTime(date);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.MONTH, cal.get(Calendar.MONTH)/3 * 3 + 2);
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
return cal.getTime();
}
Note 1: Months in java.util.Calendar are represented as integers starting from 0 (Jan) through 11 (Dec)
Note 2: division of integers in Java results in floor value (another integer value). So 2/3 = 0, 4/3 = 1 and so forth.
So, cal.get(Calendar.MONTH)/3 * 3
calculates zero-based index of quarter: 0(Q1), 1(Q2), 2(Q3), 3(Q4).
Example: Feb in Calendar is 1. So, 1 / 3 * 3 = 0.
If Feb date is supplied, then start of the quarter is 1st of Jan (because we got 0) and the end of quarter is last day of month 0 + 2 = 2 (Mar)