Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Months from a given quarter

I'm trying to get Months from a certain quarter. Using the code below, I successfully get the names of the months in the current quarter from the LocalDate.now() instance.

How would I get a quarter's months from just a quarter String (e.g. "Q1")?

int monthInt = Month.from(LocalDate.now()).firstMonthOfQuarter().getValue();
      for (int j = 1; j <= 3; j++) { //for each month in quarter
          System.out.println(Month.of(monthInt).name()); //January, February, March
          monthInt++;
      }
like image 217
xblaz3kx Avatar asked Jan 31 '26 03:01

xblaz3kx


2 Answers

We can find out how the JDK calculates the quarter by looking at the declaration of getFrom of IsoFields.QUARTER_OF_YEAR:

public long getFrom(TemporalAccessor temporal) {
    if (isSupportedBy(temporal) == false) {
        throw new UnsupportedTemporalTypeException("Unsupported field: QuarterOfYear");
    }
    long moy = temporal.getLong(MONTH_OF_YEAR);
    return ((moy + 2) / 3);
}

Notice how it uses the formula quarter = (moy + 2) / 3. Therefore, to find the starting month of a quarter, we just need to rearrange it in terms of moy - moy = quarter * 3 - 2.

You can write a method like this:

private static List<String> monthNamesFromQuarter(int quarter) {
    // you can do the validation of quarter yourself
    int start = quarter * 3 - 2;
    return IntStream.range(start, start + 3)
            .mapToObj(Month::of)
            .map(Month::name)
            .collect(Collectors.toList());
}
like image 81
Sweeper Avatar answered Feb 01 '26 17:02

Sweeper


tl;dr

Use org.threeten.extra.YearQuarter class, along with Quarter, ZoneId, LocalDate, and Month.

YearQuarter                         // Represent an entire quarter of a specific year.
.now( ZoneId.of( "Asia/Tokyo" ) )   // Determine the current quarter as seen via the wall-clock time used by the people of a particular region (a time zone). 
.with(                              // Move to another quarter.
    Quarter.valueOf( "Q1" )         // Or, `Quarter.of( 1 )` if starting with an integer number rather than a `String` object.
)                                   // Returns another `YearQuarter` object, rather than modifying the original.
.atDay( 1 )                         // Returns a `LocalDate` object.
.getMonth()                         // Returns a `Month` enum object.
.getDisplayName(                    // Automatically localize the name of the month. 
    TextStyle.FULL ,                // How long or abbreviated do you want the translation.
    Locale.US                       // Or Locale.CANADA_FRENCH and so on. 
)                                   // Returns a `String` object.

January

YearQuarter in ThreeTen-Extra

The ThreeTen-Extra library has a class you might find useful for this work: YearQuarter.

Get the current quarter. We need a time zone to determine the current date, and therefore the current quarter. For any given moment, the date varies around the globe by time zone.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
YearQuarter currentYearQuarter = YearQuarter.now( z ) ;

But you want to determine a quarter by parsing a string.

If you have a string styled similar to ISO 8601 (the standard does not actually specify quarters) YYYY-Qq then YearQuarter can directly parse.

String input = "2020-Q1" ;
YearQuarter yearQuarter = YearQuarter.parse( input ) ;

If you have only the quarter part without the year, use Quarter enum. If your input string is Q1 and such, use valueOf to retrieve the matching enum object.

String input = "Q1" ;
Quarter quarter = Quarter.valueOf( input ) ;

If you have a number instead of a string, that is, 1 or 2 or 3 or 4, then use static method Quarter.of. By the way, in your own code you should be passing around these Quarter objects rather than a mere integer or string, to make your code more self-documenting, to provide type-safety, and to ensure valid values.

int input = 1 ; // Domain: 1, 2, 3, 4. 
Quarter quarter = Quarter.of( input ) ;

Apply that Quarter instance to our current YearQuarter instance to get another YearQuarter instance. These classes use the immutable objects pattern, so we are not modifying existing instance, we are generating new instances.

YearQuarter yearQuarter = currentYearQuarter.with( quarter ) ;

yearQuarter.toString(): 2019-Q1

Get first date (LocalDate), and year-month (YearMonth), and Month enum object, from that year-quarter.

LocalDate firstDate = yearQuarter.atDay( 1 ) ;
YearMonth yearMonth1 = YearMonth.from( firstDate ) ;
YearMonth yearMonth2 = yearMonth1.plusMonths( 1 ) ;
YearMonth yearMonth3 = yearMonth1.plusMonths( 2 ) ;

Generate a string containing the automatically localized name of month.

Locale locale = Locale.US ;  // Or Locale.CANADA_FRENCH and so on. 
String output1 = yearMonth1.getMonth().getDisplayName( TextStyle.FULL , locale ) ;

January


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?

  • Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - 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
    • Most 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.

like image 32
Basil Bourque Avatar answered Feb 01 '26 15:02

Basil Bourque



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!