50

Given a java.util.Date object how do I go about finding what Quarter it's in?

Assuming Q1 = Jan Feb Mar, Q2 = Apr, May, Jun, etc.

Allain Lalonde
  • 91,574
  • 70
  • 187
  • 238

14 Answers14

69

Since Java 8, the quarter is accessible as a field using classes in the java.time package.

import java.time.LocalDate;
import java.time.temporal.IsoFields;

LocalDate myLocal = LocalDate.now();
int quarter = myLocal.get(IsoFields.QUARTER_OF_YEAR);

In older versions of Java, you could use:

import java.util.Date;

Date myDate = new Date();
int quarter = (myDate.getMonth() / 3) + 1;

Be warned, though that getMonth was deprecated early on:

As of JDK version 1.1, replaced by Calendar.get(Calendar.MONTH).

Instead you could use a Calendar object like this:

import java.util.Calendar;
import java.util.GregorianCalendar;

Calendar myCal = new GregorianCalendar();
int quarter = (myCal.get(Calendar.MONTH) / 3) + 1;
kometen
  • 6,536
  • 6
  • 41
  • 51
Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
54

In Java 8 and later, the java.time classes have a more simple version of it. Use LocalDate and IsoFields

LocalDate.now().get(IsoFields.QUARTER_OF_YEAR)
abdolence
  • 2,369
  • 1
  • 21
  • 29
14

You are going to have to write your own code because the term "Quarter" is different for each business. Can't you just do something like:

Calendar c = /* get from somewhere */
int month = c.get(Calendar.MONTH);

return (month >= Calendar.JANUARY && month <= Calendar.MARCH)     ? "Q1" :
       (month >= Calendar.APRIL && month <= Calendar.JUNE)        ? "Q2" :
       (month >= Calendar.JULY && month <= Calendar.SEPTEMBER)    ? "Q3" :
                                                                    "Q4";
Tim Frey
  • 9,901
  • 9
  • 44
  • 60
10

Since quarters are a localized (Western) concept, specify a Locale rather than using the platform default:

Calendar cal = Calendar.getInstance(Locale.US);
/* Consider whether you need to set the calendar's timezone. */
cal.setTime(date);
int month = cal.get(Calendar.MONTH); /* 0 through 11 */
int quarter = (month / 3) + 1;

This will avoid getting the thirteenth month (Calendar.UNDECIMBER) on non-Western calendars, and any skew caused by their shorter months.

erickson
  • 265,237
  • 58
  • 395
  • 493
  • So I think this depends on how your library treats months. In Jodatime I think March is 3, whereas in something else, that field might be 2. It all depends on whether January starts a 0 or 1. – obesechicken13 Sep 23 '15 at 14:59
  • @obesechicken13 This was core Java, `java.util.Calendar`, and there's no variation, the first month is always 0. `Calendar` (and Joda) are obsolete with Java 8 though. – erickson Sep 23 '15 at 16:32
  • I'm not sure if Calendar is obsolete. None of its method seem to be deprecated. Also what do you mean by Joda becoming obsolete with Java 8? Do you mean LocalDateTime is better and if so what are the advantages of LocalDateTime over Joda? – obesechicken13 Sep 24 '15 at 19:24
  • 2
    @obesechicken13 No, the classes aren't annotated with `@Deprecated`, but the recommendation from from [the Joda-Time home page:](http://www.joda.org/joda-time/#Why_Joda_Time) "The standard date and time classes prior to Java SE 8 are poor. ... **Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310).**" Also, "Note that Joda-Time is considered to be a largely “finished” project. No major enhancements are planned. **If using Java SE 8, please migrate to java.time (JSR-310).**" – erickson Sep 24 '15 at 21:21
5

If you have

private static final int[] quarters = {1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4};

Then current quarter is

private static final int thisQuarter = quarters[thisMonth];

Where thisMonth is

private static final int thisMonth = cal.get(Calendar.MONTH);
James Raitsev
  • 92,517
  • 154
  • 335
  • 470
4

tl;dr

YearQuarter
.from(
    LocalDate.of( 2018 , 1 , 23 ) 
)

ThreeTen-Extra

The Answer by abdmob is correct: Using java.time is the wise way to go.

In addition, the ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time.

Its useful classes include:

Current quarter

To get the current quarter, specify a time zone. Determining a quarter means determining a date. And determining a date means specifying a time zone. For any given moment, the date varies around the globe by zone. Specify by using a proper time zone name in form of continent/region. Never use the 3-4 letter abbreviations such as EST or IST.

ZoneId z = ZoneId.of( "America/Montreal" );
YearQuarter yq = YearQuarter.now( z );

Given a java.util.Date

If given a java.util.Date first convert to a java.time type. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds.

Instant instant = myUtilDate.toInstant();

Assign a time zone to get a ZoneDateTime.

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( z );

Generate a YearQuarter from that ZonedDateTime.

YearQuarter yq = YearQuarter.from( zdt );

Use throughout your code

You should be passing around instances of YearQuarter rather than mere numbers or strings. Using objects provides type-safety, ensures valid values, and makes your code more self-documenting.


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.

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
3

When using Joda time, use Math.ceil() function:

double quarter = Math.ceil(new Double(jodaDate.getMonthOfYear()) / 3.0);
Coltini
  • 41
  • 2
1
int month = Calendar.getInstance().get( Calendar.MONTH ) + 1;

int quarter = month % 3 == 0?  (month / 3): ( month / 3)+1;
slfan
  • 8,950
  • 115
  • 65
  • 78
  • @http://stackoverflow.com/users/430688/graham-savage This "works" because it is just the accepted answer but done in a stupid way. Adding 1 to month in line one messes up the integer division so instead of simply not doing that he has a complicated conditional. Simpler is int month = Calendar.getInstance().get(Calendar.MONTH) and int quarter = (month / 3)+1; Oh wait, that's the accepted answer. – Dirk Bester Mar 04 '15 at 01:58
1

Make sure that the thisMonth is at least a float or a double, not an int:

String quarter = thisMonth/3 <= 1 ? "Q1" : thisMonth/3 <= 2 ? "Q2" : thisMonth/3 <= 3 ? "Q3" : "Q4";

Regards, MS

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
Marco
  • 2,445
  • 2
  • 25
  • 15
1

JFreeChart has a Quarter class. If you're curious, check out the javadoc. The source is also available from SourceForge if you want to check out the implementation.

Brendan Cashman
  • 4,878
  • 2
  • 23
  • 20
1

Good solutions here, but remember that quarters can be subject to change depending on company/industry too. Sometimes a quarter can be a different 3 months.

You probably want to extend or encapsulate the calendar class to customize it to your tasks rather than write some utility function that converts it. Your application is probably complex enough in that area that you will find other uses for your new calendar class--I promise you'll be glad you extended or encapsulated it even if it seems silly now.

Bill K
  • 62,186
  • 18
  • 105
  • 157
0

For Me, I Used this method for string representation:

int quarter = (Calendar.getInstance().get(Calendar.MONTH) / 3); // 0 to 3
String[] mQuarterKey = {"qt1", "qt2", "qt3", "qt4"};
String strQuarter = mQuarterKey[quarter];
0

with java8 you may use formatter:

import java.time.format.DateTimeFormatter
import java.time.LocalDate

println("withQuarter: " + LocalDate.of("2016".toInt,"07".toInt,1).format(DateTimeFormatter.ofPattern("yyyyQMM")))

withQuarter: 2016307

nexoma
  • 275
  • 4
  • 10
0

I use this method.

 public static Integer getQuarter(Date d){
    Calendar c = Calendar.getInstance();
    c.setTime(d);
    int month = c.get(Calendar.MONTH);
    return (month /3)+1;
}
Sunila SS
  • 93
  • 5