-1

I am using java 1.7, How to find the quarter to which a particular date belong for a Fiscal year, which can start from 1st of any month (JAN-DEC) and also need the start date and end date of that Quarter.

i.e Suppose FY(1 April 2017 - 31 March 2018) then Date 26 June 2017 belong to Q1(Quarter 1) and quarter start date is 1 October 2017 and end date is 31 December 2017 ..etc

AKT
  • 182
  • 1
  • 8
  • Isolate the month M from the date; if M is less than the starting month of the F/Y, add 12 to M; subtract F/Y start month from M to obtain month-of-FY MFY; divide MFY by 4 and add 1 to the quotient to obtain the quarter Q. – Kevin Anderson Jan 08 '18 at 11:20
  • Thanks for the solution, but In addition to the quarter , we need the start and end date of that particular quarter as well. – AKT Jan 08 '18 at 11:34
  • Tip: search “Half-Open” and `YearMonth`. This has been covered many times already on Stack Overflow. – Basil Bourque Jan 13 '18 at 17:19

3 Answers3

2

java.time

java.time, the modern Java data and time API, gives you most of what you are asking for. Only it dies not know your financial year. The quarter you are asking for is one less that the quarter used in the ISO calendar system supported by java.time. So my trick is to subtract one quarter from your date and then query java.time about the quarter and year. That will give you the numbers you require.

In code, trying different dates:

    LocalDate[] exampleDates = {
            LocalDate.of(2020, Month.JANUARY, 1),
            LocalDate.of(2020, Month.JUNE, 30),
            LocalDate.of(2020, Month.AUGUST, 22),
            LocalDate.of(2020, Month.OCTOBER, 1),
            LocalDate.of(2021, Month.MARCH, 31),
    };
    
    for (LocalDate date : exampleDates) {
        LocalDate syntheticQuarterDate = date.minus(1, IsoFields.QUARTER_YEARS);
        
        // Get quarter number and year as int
        int quarter = syntheticQuarterDate.get(IsoFields.QUARTER_OF_YEAR);
        int year = syntheticQuarterDate.getYear();
        System.out.format("Quarter: %d; year: %d%n", quarter, year);
    }

Output is:

Quarter: 4; year: 2019
Quarter: 1; year: 2020
Quarter: 2; year: 2020
Quarter: 3; year: 2020
Quarter: 4; year: 2020

Suppose you wanted a string like Q42019 rather than the numbers. In this case it’s best to use a formatter:

    DateTimeFormatter quarterFormatter
            = DateTimeFormatter.ofPattern("QQQuuuu", Locale.ENGLISH);

Now for each date do:

        // Print a string like "Q42019"
        String quarterString = syntheticQuarterDate.format(quarterFormatter);
        System.out.println(quarterString);

Output using the same dates as before:

Q42019
Q12020
Q22020
Q32020
Q42020

Question: Does that work with Java 7?

java.time works nicely on Java 7. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
1

In Java 7, you could do:

public static void main(String[] args) {
    // Dates are DD/MM/YYYY
    String date_string = "26/06/2017";

    String quarter_start_string = "01/04/2017";
    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
    Date in_date = sdf.parse(date_string);
    Date qstart = sdf.parse(quarter_start_string);
    boolean found = false; 
    int quarter = 1;
    Calendar in_date_cal = GregorianCalendar.getInstance();
    in_date_cal.setTime(in_date);

    Calendar fq_start = GregorianCalendar.getInstance();
    fq_start.setTime(qstart);
    Calendar fq_end = GregorianCalendar.getInstance();
    fq_end.setTime(qstart);
    fq_end.add(GregorianCalendar.MONTH, 3 );
    while (!found) { 
        if (in_date_cal.hashCode() >= fq_start.hashCode() && 
                in_date_cal.hashCode() <= fq_end.hashCode()) {
            break; 
        }
        fq_start.add(GregorianCalendar.MONTH, 3 );
        fq_end.add(GregorianCalendar.MONTH, 3 );
        quarter++; 
    }

    System.out.println("Quarter# is " + quarter);
    System.out.println("Quarter Start is " + sdf.format(fq_start.getTime()));
    System.out.println("Quarter End is " + sdf.format(fq_end.getTime()));
}

For people coming to this question using Java 8, you can use LocalDate:

public static void main(String[] args) throws ParseException {
    // Dates are DD/MM/YYYY
    String date_string = "26/06/2017";

    String quarter_start_string = "01/04/2017";

    DateTimeFormatter f = DateTimeFormatter.ofPattern("dd/MM/yyyy");
    LocalDate ld_in = LocalDate.parse(date_string, f);

    LocalDate ld_qstart = LocalDate.parse(quarter_start_string, f);

    LocalDate fq_start = ld_qstart; 
    LocalDate fq_end = ld_qstart.plusMonths(3);
    boolean found = false; 
    int quarter = 1; 
    while (!found) { 
        if (ld_in.hashCode() >= fq_start.hashCode() && 
                ld_in.hashCode() <= fq_end.hashCode()) {
            break; 
        }
        fq_start = fq_start.plusMonths(3); 
        fq_end = fq_start.plusMonths(3);
        quarter++; 
    }

    System.out.println("Quarter# is " + quarter);
    System.out.println("Quarter Start is " + fq_start);
    System.out.println("Quarter End is " + fq_end);
}
Scott C Wilson
  • 19,102
  • 10
  • 61
  • 83
-1

Use a calendar:

Calendar cal = Calendar.getInstance();
cal.setTime(myDate);

Quarter:

int q = cal.get(Calendar.MONTH)%3;
System.out.println("Quarter: Q" + (q + 1));

Begining of quarter:

cal.set(Calendar.MONTH, 3*q);
cal.set(Calendar.DAY_OF_MONTH, 1);
Date start = cal.getTime();
System.out.println("Start: " + start);

End of quarter:

cal.add(Calendar.MONTH, 3);
cal.add(Calendar.DATE, -1);
Date end = cal.getTime();
System.out.println("End: " + end);
Maurice Perry
  • 9,261
  • 2
  • 12
  • 24