I'm working with some issue.
I need to get some data from database
1) get 5 records from 5 last days (one record per one day), but the days must be the days of a week (now a weekend)
2) get 20 records from the month (current or past, one record per one day)
I'm fighting with Java Calendar, but still i have no idea, how to get the dates.
Could anybody help me?
Should work:
private Calendar workingDaysBack(final Calendar from, final int count) {
for (int daysBack = 0; daysBack < count; ++daysBack) {
do {
from.add(Calendar.DAY_OF_YEAR, -1);
} while(isWeekend(from));
}
return from;
}
private boolean isWeekend(Calendar cal) {
return cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ||
cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY;
}
You can do first part by just tweaking the day of the week parameter through each day you want to consider. Depends on what behaviour you want if running during weeks - should be current week, or last complete week? Here I've assumed current week...
Calendar cal = Calendar.getInstance();
List<Date> last5Days = new LinkedList<Date>();
List<Integer> weekDays = Arrays.asList(Calendar.MONDAY,
Calendar.TUESDAY, Calendar.WEDNESDAY, Calendar.THURSDAY,
Calendar.FRIDAY);
for (int weekDay : weekDays) {
cal.set(Calendar.DAY_OF_WEEK, weekDay);
last5Days.add(cal.getTime());
}
System.out.println(last5Days);
20 week days from current month. Depends what behaviour you want on weeks than span month boundaries. Here I've gone forward to first Monday, and then add on from there.
List<Date> last20Days = new LinkedList<Date>();
// find first Monday in the month
for (int i = 1; i <= 31; i++) {
cal.set(Calendar.DAY_OF_MONTH, i);
if (cal.get(Calendar.DAY_OF_WEEK) == weekDays.get(0)) {
break;
}
}
for (int i = 1; i <= 31; i++) {
if (last20Days.size() == 20) {
break;
}
if (weekDays.contains(cal.get(Calendar.DAY_OF_WEEK))) {
last20Days.add(cal.getTime());
}
cal.add(Calendar.DAY_OF_MONTH, 1);
}
System.out.println(last20Days);
tl;dr
myLocalDate.with(
org.threeten.extra.Temporals.previousWorkingDay()
)
Using java.time
The other Answers use troublesome old date-time classes such as Calendar
than are now legacy, supplanted by the java.time classes.
To get the last five days, you first need to get “today”.
LocalDate
The LocalDate
class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
Specify a proper time zone name in the format of continent/region
, such as America/Montreal
, Africa/Casablanca
, or Pacific/Auckland
. Never use the 3-4 letter abbreviation such as EST
or IST
as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
DayOfWeek
To get previous days, you can call minusDays
to move incrementally through dates in the past.
LocalDate yesterday = today.minusDays( 1 );
LocalDate dayBeforeYesterday = yesterday.minusDays( 1 );
You can test each LocalDate
object for its day-of-week by using the DayOfWeek
enum. That class predefines seven objects, one for each day of the week. Note that these are real objects, not mere strings. No need to use strings at all here.
Boolean isSaturday = myLocalDate.getDayOfWeek().equals( DayOfWeek.SATURDAY );
Boolean isSunday = myLocalDate.getDayOfWeek().equals( DayOfWeek.SUNDAY );
EnumSet
A slicker and more flexible way of doing that comparison is with an EnumSet
, an implementation of Set
optimized for enums that is extremely fast to execute and uses very little memory.
EnumSet<DayOfWeek> weekend = EnumSet.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY );
Use contains
to test your LocalDate
object’s DayOfWeek
.
Boolean isWeekend = weekend.contains( myLocalDate.getDayOfWeek() );
ThreeTen-Extra TemporalAdjuster
previousWorkingDay()
The ThreeTen-Extra project extends the java.time classes with additional functionality. In particular here, we could use its previousWorkingDay
implementation of the TemporalAdjuster
interface.
This adjuster is hard-coded to skip over Saturday and Sunday. If you want other day-of-week values to be considered, you can write your own implementation of TemporalAdjuster
.
The java.time classes use immutable objects. So rather than change the values (“mutate”) on an object, we generate a fresh object with values based on the original. So here we call LocalDate::with
, pass a TemporalAdjuster
, and generate a fresh LocalDate
that represents a prior date while skipping over Saturday/Sunday.
LocalDate previousWorkingDay =
myLocalDate.with(
org.threeten.extra.Temporals.previousWorkingDay()
)
;
Full example
So let's put this all together.
ZoneId z = ZoneId.of ( "America/Montreal" );
LocalDate today = LocalDate.now ( z );
Integer countDaysPrior = 5;
List<LocalDate> priorWeekdays = new ArrayList<> ( countDaysPrior ); // Set initial capacity to number of days to be collected.
LocalDate localDate = today; // Initialize to today. Exclusive, we want only prior days.
for ( int i = 1 ; i <= countDaysPrior ; i ++ ) {
localDate = localDate.with ( org.threeten.extra.Temporals.previousWorkingDay () ); // Decrement each day into the past, skipping over Saturday/Sunday.
priorWeekdays.add ( localDate );
}
System.out.println ( "Weekdays prior to " + today + " are: " + priorWeekdays );
Weekdays prior to 2017-02-27 are: [2017-02-24, 2017-02-23, 2017-02-22, 2017-02-21, 2017-02-20]
I suppose you could make that code even shorter using Lambdas and Streams.
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?
- 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.
Just a kick start
Calendar cal = Calendar.getInstance();//initilized with current date & time
Date date = cal.getTime();//returned the current date & time that cal holds
boolean isMonday = Calendar.MONDAY == cal.get(Calendar.DAY_OF_WEEK);//it will return an integer
See API Doc for more