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.