0

I need to get statistics for a quarter.

Example: today is February 10th 2018, I need to retrieve data from December 2017, from 1st to 31st, then from January 2018, from 1st to 30th and from February 1st to current date.

How can I achieve this using Java Date?

diston
  • 129
  • 3
geass94
  • 87
  • 2
  • 10
  • 2
    Don't use a `Date` for that ... at least use `Calendar` but you really should use a `LocalDate`. For the rest, google it. It can be found quickly. [java.util.Date - Deleting three months from a date?](https://stackoverflow.com/questions/1311143/java-util-date-deleting-three-months-from-a-date) ... then set the day of month to 1 ... that's simple with a `LocalDate` too. – AxelH Mar 13 '18 at 12:57
  • Please search before asking (and get a good answer faster). What you want, you can obtain it by combining the answers from [Get first date of current month in java](https://stackoverflow.com/questions/14241836/get-first-date-of-current-month-in-java) and [How to reduce one month from current date and stored in date variable using java?](https://stackoverflow.com/questions/16392892/how-to-reduce-one-month-from-current-date-and-stored-in-date-variable-using-java/16392922). I too recommend the answers that use java.time, they are there under both the questions I link to. – Ole V.V. Mar 13 '18 at 14:14

3 Answers3

2

tl;dr

YearMonth.now().minusMonths( 1 ).atEndOfMonth()  // or .atDay( 1 )

Details

Get today’s date.

ZoneId z = ZoneId.of( “Africa/Tunis” ) ;
LocalDate today = LocalDate.now( z ) ;

Get the year-month of that date.

YearMonth ymCurrent = YearMonth.from( today ) ; 

Add the ThreeTen-Extra library to your project to access the LocalDateRange class. This class represents as one object a pair of LocalDate objects, start date and stop date, for a date range from one date to the other date.

LocalDateRange rangeCurrent = LocalDateRange.ofClosed( ymCurrent.atDay( 1 ) , today ) ;

Move to previous month.

YearMonth ymPrevious = ymCurrent.minusMonths( 1 ) ;
LocalDateRange rangePrevious = LocalDateRange.ofClosed( ymPrevious.atDay( 1 ) , ymPrevious.atEndOfMonth() ) ;

Subtract yet another time for your third month.

Tip: Consider using the Half-Open approach to defining a span of time, where the beginning is inclusive while the ending is exclusive. So a month starts with the first day of the month and runs up to, but does not include, the first day of the following month.

For another valid approach using java.time classes, see the Answer by diston.


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.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

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
1

Try something like this:

// Get current date
Calendar start;
start = Calendar.getInstance();

// Go to beginning of month
start.set(Calendar.DAY_OF_MONTH, 1);
start.set(Calendar.HOUR_OF_DAY, 0);
start.set(Calendar.MINUTE, 0);
start.set(Calendar.SECOND, 0);
start.set(Calendar.MILLISECOND, 0);

// Go 2 months back
my_date.add(Calendar.MONTH, -2);

// Get end of same month
Calendar end;
end = start.clone();
end.add(Calendar.MONTH, 1);
end.add(Calendar.DAY_OF_MONTH, -1);

Then, do something similar for the other months

Robert Kock
  • 5,795
  • 1
  • 12
  • 20
  • 2
    FYI, the troublesome `Calendar` class has been legacy for years now, supplanted by the *java.time* classes built into Java 8 and later. – Basil Bourque Mar 13 '18 at 13:07
1

You can use Java 8's java.time classes (or threeten backport for Java <= 7).

If you'll work only with day/month/year and don't care about hours and timezones, the best class to use is LocalDate. To create a specific date is easy:

// February 10th 2018
LocalDate current = LocalDate.of(2018, 2, 10);

Or you can call LocalDate.now() to get the current date.

Then, to get to December 1st 2017, you must subtract 2 months (2 months before February is December) and set the day to 1:

// start is December 1st 2017
LocalDate start = current
    // 2 months ago = December
    .minusMonths(2)
    // change day of month to 1st
    .withDayOfMonth(1);

Then you can loop from December 1st to February 10th:

LocalDate date = start;
while (date.isBefore(current)) {
    // do whatever you need with the date

    // go to the next day
    date = date.plusDays(1);
}

Note that plusDays returns a new object, so I must assign it to the same variable, otherwise it won't be changed.

I also used isBefore, which doesn't include the current date in the loop - it'll stop at February 9th. If you want to include February 10th, change the condition to if (! date.isAfter(current))

diston
  • 129
  • 3
  • Tip: The `java.time.YearMonth` class makes this work simpler and makes the code more obvious as to our intentions. See my Answer for example usage. – Basil Bourque Mar 13 '18 at 13:29
  • 1
    @BasilBourque In this case, I think the codes are kinda equivalent, I don't see much difference between `current.minusMonths(2).withDayOfMonth(1)` and `YearMonth.from(current).minusMonths(2).atDay(1)` - just 2 different ways to do the same thing, IMO. – diston Mar 13 '18 at 13:36
  • 1
    Why the downvote, please? I would consider it good style to leave a comment along with it? – Ole V.V. Mar 13 '18 at 20:15