3

How would I implement dayNumber_of_quarter?

E.g. March 3 (Q1) should return 62 = 31 (Jan) + 28 (Feb) + 3(March) and Apr 29 (Q2) should return 29.

My code so far:

int month = getMonth(date);
int quarter = getQuarter(date);
int date1 = getDate(date);
int year = getYear(date);
int monthMod = month % 3;
if (monthMod == 0) monthMod = 3;
//System.out.println(monthMod);
int countNumDaysOfQuarter = 0;

if (monthMod == 1) countNumDaysOfQuarter = getDate(date);
if (monthMod == 2) countNumDaysOfQuarter = getDate(date) + getCountOfDaysInMonth(date1, month - 1, year); 
if (monthMod == 3) countNumDaysOfQuarter = getDate(date) + getCountOfDaysInMonth(date1, month - 1, year) + getCountOfDaysInMonth(date1, month - 2, year);
Zong
  • 6,160
  • 5
  • 32
  • 46

4 Answers4

1

Have you tried using joda time?

The standard date and time classes prior to Java SE 8 are poor. By tackling this problem head-on, Joda-Time became the de facto standard date and time library for Java prior to Java SE 8.

Then you can count the number of days between two dates

  1. the start date of your quarter, and
  2. the end date of your quarter.

using a technique similar to: Number of days between two dates in Joda-Time

Note: The number of days in each quarter charges per year (leap years). So you'll need to care about leap years, you will indeed need to specify a full date that includes the year, and not just the month, in order to calculate the number of days in a quarter.

Community
  • 1
  • 1
James Lawson
  • 8,150
  • 48
  • 47
1

Here is a simple implementation using Java 8:

public static long dayOfQtr(LocalDate date) {
    LocalDate firstDayOfQtr = LocalDate.of(date.getYear(), (qtr(date) - 1) * 3 + 1, 1);
    return ChronoUnit.DAYS.between(firstDayOfQtr, date) + 1;
}
public static int qtr(LocalDate date) {
    return (date.getMonthValue() - 1) / 3 + 1;
}

TEST

for (int i = 1; i <= 12; i++) {
    LocalDate date = LocalDate.of(2016, i, i);
    System.out.println(date + " is day " + dayOfQtr(date) + " of Q" + qtr(date));
}

OUTPUT

2016-01-01 is day 1 of Q1
2016-02-02 is day 33 of Q1
2016-03-03 is day 63 of Q1
2016-04-04 is day 4 of Q2
2016-05-05 is day 35 of Q2
2016-06-06 is day 67 of Q2
2016-07-07 is day 7 of Q3
2016-08-08 is day 39 of Q3
2016-09-09 is day 71 of Q3
2016-10-10 is day 10 of Q4
2016-11-11 is day 42 of Q4
2016-12-12 is day 73 of Q4
Andreas
  • 154,647
  • 11
  • 152
  • 247
0

Below is a very basic implementation.

private static int getDayOfQtr() {
    final int[] daysYr = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    final int[] daysLeapYr = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    final int[] quarters = { 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4 };
    final int[] months = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
    int currQtr = 0;
    int dayOfQtr = 0;

    int currDay = Calendar.getInstance().get(Calendar.DATE);
    int currMth = Calendar.getInstance().get(Calendar.MONTH) + 1;
    int currYr = Calendar.getInstance().get(Calendar.YEAR);
    if (currMth % 3 == 0) {
        currQtr = currMth / 3;
    } else {
        currQtr = currMth / 3 + 1;
    }
    for (int qtr = 0; qtr < quarters.length; qtr++) {
        if (currQtr == quarters[qtr]) {
            if (currMth > months[qtr]) {
                if (currYr % 4 == 0) {
                    dayOfQtr += daysLeapYr[qtr];
                } else {
                    dayOfQtr += daysYr[qtr];
                }
            } else if (currMth == months[qtr]) {
                dayOfQtr += currDay;
            }
        }
    }
    return dayOfQtr;
}
Aniket V
  • 3,183
  • 2
  • 15
  • 27
0

tl;dr

LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" );
int dayOfQuarter = (int) ChronoUnit.DAYS.between( 
    YearQuarter.from( today ).atDay( 1 ) , 
    today 
) + 1 ;  // Add one to get the ordinal rather than get index into quarter.

java.time

Use the java.time framework built into Java 8 and later (with back-ports to Java 6 & 8 and Android), as shown in the Answer by Andreas.

ThreeTen-Extra

In addition, you can add the ThreeTen-Extra library which extends java.time to provide extra functionality, some of which may eventually be added into java.time. To use this library, add its jar file to your project (or use Maven etc.).

Quarter & YearQuarter

The ThreeTen-Extra library 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.of( "America/Montreal" ) );

The YearQuarter has many useful methods, including asking for its dates. LocalDate is a date-only value, without time-of-day and without time zone.

LocalDate start = currentQuarter.atDay ( 1 );
LocalDate lastday = currentQuarter.atEndOfQuarter ();

We can get the quarter for a certain date.

LocalDate localDate = LocalDate.of ( 2016 , 4 , 29 );
YearQuarter yearQuarter = YearQuarter.from ( localDate );

Then ask that YearQuarter object for its starting date.

LocalDate quarterStart = yearQuarter.atDay ( 1 );

ChronoUnit

The ChronoUnit enum can calculate elapsed time as shown above.

Or, alternatively, Period class.

Period

The Period class represents a span of time in terms of years, months and days.

Calculate the span of time between the start of quarter and our target date.

Period period = Period.between ( quarterStart , localDate );

Extract the total number of days in that span of time.

int days = ( period.getDays () + 1 );  // Add one to get the ordinal.

Half-Open

Note that this result is 28 rather than the 29 you expected. This is because in date-time work we commonly use the “Half-Open” approach for defining a span of time where the beginning is inclusive while the ending is exclusive. This is usually wiser and beneficial. Also makes your coding more predictable and easier to understand if you practice this in all your date-time work. So a week runs from a Monday and going up to but not including the following Monday. Your lunch break runs from the first moment of noon and going up to but not including the first moment of 1 PM.

So, here, going from April 1 to 29 is 28 days. I suggest sticking with that but if desired you can of course just add one.

Dump to console.

System.out.println ( "localDate: " + localDate + " is days: " + days + " into yearQuarter: " + yearQuarter );

localDate: 2016-04-29 is days: 28 into yearQuarter: 2016-Q2

See my Answer to a similar Question for more discussion.

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