Pulling all dates that refer to a specific date of the week in a year - Java

Struggling with this problem for a while, would love some kind of input.

The problem I want to solve is collecting all dates in one specific year that fall on a specific day of the week, for example, every Tuesday in 2014. Dates are stored in ArrayList<Date>

. This list is then returned.

It also needs to be confirmed so that the year is not 0 and the day of the week represented must be a number between 1 and 7.

If there is any problem I would like to know what I messed up.

public List<Date> getDatesforDayOfWeek(int year, int dayOfWeek) throws InvalidDateException, ParseException {

    List<Date> dateList = new ArrayList<>();

    if (year <= 0 || (1 > dayOfWeek && dayOfWeek > 7)) {

        throw new InvalidDateException("Year or day of week is invalid.");

    } else {

        Calendar newCal = Calendar.getInstance();
        newCal.set(YEAR, year);
        newCal.set(DAY_OF_YEAR, 1);



        while (newCal.get(YEAR) < year + 1) {

            int currentDayOfWeek = newCal.get(DAY_OF_WEEK);

            Date newDate = null;
            if (currentDayOfWeek >= dayOfWeek) {

                int dayOfMonth = newCal.get(DAY_OF_MONTH);
                String strDayOfMonth = String.valueOf(dayOfMonth);
                String strYear = String.valueOf(year);

                DateUtility d1 = new DateUtility();
                Date passDate = newCal.getTime();

                String weekDay = d1.getWeekDayNameAbbreviation(passDate);
                String monthAbbreviation = d1.getMonthAbbreviation(passDate);


                String finalString = new String();

                finalString.concat(weekDay).concat(" ").
                        concat(monthAbbreviation).concat(" ").
                        concat(strDayOfMonth).concat(" ").
                        concat(strYear);

                SimpleDateFormat format = new SimpleDateFormat("EEE MMM dd YYYY");
                Date theDate = format.parse(finalString);

                dateList.add(theDate);
            }
            newCal.add(Calendar.DATE, 1);
        }

    }
    return (dateList);
}

      

+4


source to share


3 answers


Your question doesn't specify what is the first day of the week, but your method makes it even more complicated to test the current day of the week. Start by checking the days of the week using the standard Calendar

,

private static boolean isValidDayOfWeek(int dayOfWeek) {
    switch (dayOfWeek) {
    // Seven days of the week.
    case Calendar.SUNDAY: case Calendar.MONDAY: case Calendar.TUESDAY: 
    case Calendar.WEDNESDAY: case Calendar.THURSDAY: case Calendar.FRIDAY:
    case Calendar.SATURDAY:
        return true;
    }
    return false;
}

      

It follows that we can do something like <



public static List<Date> getDatesforDayOfWeek(int year, int dayOfWeek) {
    List<Date> dateList = new ArrayList<>();
    if (year <= 0 || !isValidDayOfWeek(dayOfWeek)) {
        return null;
    } else {
        Calendar newCal = Calendar.getInstance();
        newCal.set(Calendar.YEAR, year);
        newCal.set(Calendar.DAY_OF_YEAR, 1);
        // First, let loop until we're at the correct day of the week.
        while (newCal.get(Calendar.DAY_OF_WEEK) != dayOfWeek) {
            newCal.add(Calendar.DAY_OF_MONTH, 1);
        }
        // Now, add the Date to the List. Then add a week and loop (stop
        // when the year changes).
        do {
            dateList.add(newCal.getTime());
            newCal.add(Calendar.DAY_OF_MONTH, 7);
        } while (newCal.get(Calendar.YEAR) == year);
    }
    return dateList;
}

      

Leaving us with main()

. So, so that every Tuesday in 2014 you can use -

public static void main(String[] args) {
    List<Date> tuesdays = getDatesforDayOfWeek(2014, Calendar.TUESDAY);
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    for (Date d : tuesdays) {
        System.out.println(df.format(d));
    }
}

      

+1


source


I think your main problem is this condition

if (currentDayOfWeek >= dayOfWeek) {

      

since this will count any day that is "higher" than the day you want. If you pass 3

, it will also count any day that is higher than 3

that which is not what you want.



the condition should be

if (currentDayOfWeek == dayOfWeek) {

      

I also recommend using the getTime calendar method instead of parsing String

to get Date

.

0


source


TL; dr

startOfYear                                              // 'Year.of( 2019 ).atDay( 1 )' gets the first day of the year.
.datesUntil( startOfYear.plusYears( 1 ) )                // Generate a stream of incrementing 'LocalDate' objects.
.filter(                                                 // Pull out the dates that are a Tuesday.
    t -> t.getDayOfWeek().equals( DayOfWeek.TUESDAY ) 
)
.collect( Collectors.toList() )                          // Return results in a 'List' of 'LocalDate' objects.

      

ISO 8601

The ISO 8601 standard for working with date and time defines Monday as the first day of the week , indicated by the number 1. Sunday is 7.

Avoid juDate & .Calendar

The java.util.Date and .Calendar classes bundled with java are notoriously troublesome. Avoid them. They were superseded in Java 8 by the new java.time package. This package was inspired by Joda-Time, an alternative that remains an active viable project with some benefits.

Joda-Time and java.time use ISO 8601 by default .

Date-Only

For this question, we only need dates, not time of day or time zones. Both Joda-Time and java.time offer a LocalDate class for this purpose.

java.time

Use Year.of

and LocalDate::plusYears

to define the boundaries of the year by getting a pair of objects LocalDate

for each first day of the year.

LocalDate startOfYear = Year.of( 2019 ).atDay( 1 );  // Determine first day of the year.
LocalDate startOfFollowingYear = startOfYear.plusYears( 1 );

      

Cycle increasing the date one day at a time. If this date turns out to be Tuesday, add it to our collection.

LocalDate localDate = startOfYear;
List < LocalDate > tuesdays = new ArrayList <>( 55 ); // Set initialCapacity to maximum number of tuesdays in a year. Probably 53, but I'll go with 55 for good measure.
while ( localDate.isBefore( startOfFollowingYear ) )
{
    if ( localDate.getDayOfWeek().equals( DayOfWeek.TUESDAY ) )
    {
        tuesdays.add( localDate );
    }
    // Set up the next loop.
    localDate = localDate.plusDays( 1 );
}
System.out.println( tuesdays );

      

Watch this code live at IdeOne.com .

[2019-01-01, 2019-01-08, 2019-01-15, 2019-01-22, 2019-01-29, 2019-02-05, 2019-02-12, 2019-02-19, 2019 -02-26, 2019-03-05, 2019-03-12, 2019-03-19, 2019-03-26, 2019-04-02, 2019-04-09, 2019-04-16, 2019-04 -23, 2019-04-30, 2019-05-07, 2019-05-14, 2019-05-21, 2019-05-28, 2019-06-04, 2019-06-11, 2019-06-18 , 2019-06-25, 2019-07-02, 2019-07-09, 2019-07-16, 2019-07-23, 2019-07-30, 2019-08-06, 2019-08-13, 2019 -08-20, 2019-08-27, 2019-09-03, 2019-09-10, 2019-09-17, 2019-09-24, 2019-10-01, 2019-10-08, 2019-10 -15, 2019-10-22, 2019-10-29, 2019-11-05, 2019-11-12, 2019-11-19, 2019-11-26, 2019-12-03, 2019-12-10 , 2019-12-17, 2019-12-24, 2019-12-31]

Or get carried away with functional lambda syntax . The method generates a stream in Java 9 and later. Then filter the stream by match in . LocalDate::datesUntil

DayOfWeek.TUESDAY

LocalDate startOfYear = Year.of( 2019 ).atDay( 1 );
Stream < LocalDate > stream = startOfYear.datesUntil( startOfYear.plusYears( 1 ) );
List < LocalDate > tuesdays = stream.filter( t -> t.getDayOfWeek().equals( DayOfWeek.TUESDAY ) ).collect( Collectors.toList() );

      

Joda time

Here is some sample code in Joda-Time 2.4 to collect all Tuesdays in a year.

int year = 2014; 
String input = year + "-01-01";
LocalDate localDateInput = LocalDate.parse( input );
LocalDate firstTuesday = localDateInput.withDayOfWeek ( DateTimeConstants.TUESDAY );
LocalDate tuesday = firstTuesday;  // for incrementing by week.
List<LocalDate> list = new ArrayList<>();
while ( tuesday.getYear() == year ) {
  list.add( tuesday );
  tuesday.plusWeeks( 1 );
}

      


About java.time

Java.time infrastructure is built in Java 8 and later versions . These classes displace nasty old outdated date and time classes such as , , and . java.util.Date

Calendar

SimpleDateFormat

For more information, see the Oracle Tutorial . And search for many examples and explanations. Specification JSR 310 .

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

You can exchange java.time objects directly with your database. Use the JDBC driver, the appropriate JDBC 4.2 or later version . No need for strings, no need for java.sql.*

.

Where can I get the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a testing ground for possible future additions to java.time. Here you can find some useful classes such as , , and others . Interval

YearWeek

YearQuarter

0


source







All Articles