-2

For the current year i.e 2014. Starting from Jan 1st, I have to get the 1st and 3rd Wednesday dates for every month ending, Dec 31st. I am using java version 1.6

I have no idea how to get this.

Vicky
  • 657
  • 1
  • 8
  • 16
  • 1
    which java version?? because the date api is improved heavily since 1.8 as @NimChimpsky said use joda for pre 1.8 FYI joda time library is merged into 1.8 within [JSR310](https://jcp.org/en/jsr/detail?id=310) – isaias-b Jun 23 '14 at 12:42
  • 3
    use joda time or it will take a year to finish it – NimChimpsky Jun 23 '14 at 12:42
  • 1
    @NimChimpsky: Really? This is yet another problem, which actually cannot be solved with Joda (for all reasonable definitions of cannot). Joda has no support for localized week rules and is not suitable to find the 1st and 3rd Wednesday of a month. – jarnbjo Jun 23 '14 at 12:44
  • 2
    @jarnbjo I have had to implement a number of similar requirements using joda-time. So I would very much dispute that. – NimChimpsky Jun 23 '14 at 12:46
  • 1
    @NimChimpsky: There's nothing to dispute here. You could easily have googled and found e.g. http://stackoverflow.com/questions/1801907/joda-time-first-day-of-week Joda only knows the Mon-Sun week as defined by ISO and has no support e.g. for the Sun-Sat week as common in English-speaking countries or the Sat-Fri week common in countries with the Islam calendar. – jarnbjo Jun 23 '14 at 12:55
  • @jarnbjo see answer, not fully featured, but definitely not impossible. – NimChimpsky Jun 23 '14 at 12:55
  • Although, rowing back. I just realized that the week boundaries are irrelevant to answer the question, at least if you implement a naive loop to find the days. – jarnbjo Jun 23 '14 at 12:56
  • @jarnbjo that wasn't the question. – NimChimpsky Jun 23 '14 at 12:56
  • @isi I am using java 1.6 – Vicky Jun 23 '14 at 12:58
  • Please update the question with version information or any information which is not clear at the beginning. – isaias-b Jun 23 '14 at 13:03
  • @jarnbjo I am interested, how would you do this using the standard java classes ? – NimChimpsky Jun 23 '14 at 13:13
  • 1
    @NimChimpsky: Why not. You initialize a GregorianCalendar with the first day of the month and then set it to the first and third Wednesday of the month. But if you claim knowledge to determine that Joda is so much better than the old API, shouldn't we expect that you know what you're comparing with? – jarnbjo Jun 23 '14 at 13:21
  • possible duplicate of [Get Last Friday of Month in Java](http://stackoverflow.com/questions/76223/get-last-friday-of-month-in-java) – Basil Bourque Jun 23 '14 at 18:48
  • @jarnbjo I didn't literally think it would take a year to write the code using the old java date calendar api. I thought that was obvious. The fact its been replaced suggests many people hold the view that in general its not very developer friendly, which was the point of my tongue in cheek comment. – NimChimpsky Jun 27 '14 at 08:21
  • @NimChimpsky: And not only did it not take a year, but it turned out to be much simpler than with Joda. You just set the calendar to the numbered Wednesday of the month instead of looping through all the days to do a "brute-force" search for the special week days. The old Calendar API is not at all particularly easy to use (I agree completely with that), but I have absolutely no understanding for the propagation of Joda with an IMHO much more confusing and inconsistent API and lack of functionality present in the legacy API. Not without reason, Joda was *not* chosen as a replacement in Java 8. – jarnbjo Jun 27 '14 at 09:27
  • @jarnbjo but the lead of the replacement date api, is the guy who wrote joda. So I don't think your logic really holds up there. – NimChimpsky Jun 27 '14 at 09:42
  • @NimChimpsky: Why not? If he has done one mistake does not mean that he's not able to learn from it and make something better with a second attempt. If you are talking about Stephen Colebourne, he explains himself in his blog why Joda-Time was not chosen to be included in the Java API: "Well, there is one key reason - Joda-Time has design flaws." If you compare Joda-Time and the Java 8 Time and Date API, it should also be obvious that they don't have very much in common. Solving this problem with the Java 8 API would e.g. be very similar to the legacy API. – jarnbjo Jun 27 '14 at 13:49
  • @jarnbjo very similar ? See my updated for java 8 version. The inner loop is hidden by the temporal adjuster which uses lambda expressions, unless there is a more concise way ? – NimChimpsky Jun 27 '14 at 14:12
  • @NimChimpsky: Even if you unroll your inner loop, you are still iterating through the Wednesdays to get to the first, second and third Wednesdays just as in your first solutions instead of simply telling the API that you want the first Wednesday. Your solution is also incorrect. If the month starts on a Wednesday, `nextWed` will point to the second Wednesday and not the first. I don't have a JDK8 installed here to give you a ready solution, but using LocalDate.with(field, value).with(field, value), you can set the fields to the nth Wednesday of the month, just as I did with the old API. – jarnbjo Jun 27 '14 at 15:23

3 Answers3

2

Pseudo code, should get you started in jodatime:

LocalDate dt = new LocalDate(2014, 1, 1); // 1st january

for(loop 12 months){

  now loop again to find 3rd wednesday
   while(count < 4) {
        d = d.plusDays(1);
        if(d.getDayOfWeek() != DateTimeConstants.WEDNESDAY){
          count++
        }
      // now based on count save in hashmap, 1 = 1st, 3 = 3rd for each month

    }
d.plusMonth(1);
}

And here it is in the new java 8 data time :

for(loop through months){
        LocalDate date = LocalDate.of(2014, month, 01);
        TemporalAdjuster adj = TemporalAdjusters.next(DayOfWeek.WEDNESDAY);
        LocalDate nextWed = date.with(adj);
        LocalDate secondWed = nextWed.with(adj);
        LocalDate thirdWed = secondWed.with(adj);
        // save in map
}
NimChimpsky
  • 46,453
  • 60
  • 198
  • 311
2

Just to answer NimChimpsky's comment to the question. Using the pre-Java8 date and calendar API, here is the solution:

for(int month = Calendar.JANUARY; month <= Calendar.DECEMBER; month++) {

    GregorianCalendar c = new GregorianCalendar(2014, month, 1);

    c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
    c.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY);
    System.out.println("First Wednesday: " + c.getTime());

    c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 3);
    System.out.println("Third Wednesday: " + c.getTime());
    System.out.println("---");

}

I haven't actually tried it (the code may be incorrect), but using the new date and time API in Java 8 would be similar:

for(Month month : Month.values()) {

    LocalDate ld = 
        LocalDate.of(2014, month, 1)
        .with(ChronoField.ALIGNED_WEEK_OF_MONTH, 1)
        .with(ChronoField.DAY_OF_WEEK, DayOfWeek.WEDNESDAY.getValue());

    System.out.println("First Wednesday: " + ld);

    ld = ld.with(ChronoField.ALIGNED_WEEK_OF_MONTH, 3);

    System.out.println("Third Wednesday: " + ld);
    System.out.println("---");

}
jarnbjo
  • 33,923
  • 7
  • 70
  • 94
0

Here's my take on the problem of collecting first and third Wednesdays of each month of current year.

Time Zone

Note one important difference from the other answers is time zone. Keep in mind that in the wee hours of a new day in Paris, the date in Montréal is still "yesterday", the previous date. So determining the current date requires a time zone.

If you omit the time zone, you get the date according to the JVM’s current default time zone. So your code varies depending on which computer it runs and on what current OS & JVM settings. Better to specify your intended/expected time zone via a DateTimeZone object defined by a proper time zone name.

LocalDate

Joda-Time (like java.time) offers a LocalDate class to represent date-only values without any time-of-day or time zone.

Joda-Time can jump to another day of week using the withDayOfWeek method. That method does not always go forward in time. Following the ISO 8601 standard week of MONDAY to SUNDAY, the method goes back in time if necessary to get prior days that are Monday or later. In our case, that means for any first of the year date that is a Thursday to Sunday we need to jump to the next week to avoid going to earlier days in the prior year to fetch a Wednesday. To experiment with this behavior in the code below, change the LocalDate.now call to new LocalDate( 2013, 1, 1 ) and vary the year.

Joda-Time

Here is some example code using Joda-Time 2.4.

I test this code with 2013, 2014, and 2015. Those are handy years as the first day of the year is Tuesday, Wednesday, and Thursday respectively.

// Collection to store our found Wednesdays.
List<LocalDate> list = new ArrayList<>( 24 ); // Two wednesdays for each of 12 months is 24.

// Get first day of the year.
DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
LocalDate firstOfYear = LocalDate.now( timeZone ).monthOfYear().withMinimumValue().dayOfMonth().withMinimumValue();

// Move from first day of the year to first Wednesday of that first month of year.
// Joda-Time follows ISO 8601 in defining the week to be MONDAY-SUNDAY.
LocalDate firstWedOfMonth;
if ( firstOfYear.getDayOfWeek() > DateTimeConstants.WEDNESDAY ) {
    firstWedOfMonth = firstOfYear.plusWeeks( 1 ).withDayOfWeek( DateTimeConstants.WEDNESDAY ); // Jump a week forward to avoid getting dates from prior year.
} else { // Else the first of year is on the target day-of-week or later in the week.
    firstWedOfMonth = firstOfYear.withDayOfWeek( DateTimeConstants.WEDNESDAY ); // Returns the same local date if already on a Wednesday.
}

// Capture first and third Wednesdays, then move on to next month, and repeat until past the end of year.
do {
    int month = firstWedOfMonth.getMonthOfYear();
    list.add( firstWedOfMonth );
    list.add( firstWedOfMonth.plusWeeks( 2 ) ); // Get 2nd Wednesday of month.
    // Move on to next month.
    do {
        firstWedOfMonth = firstWedOfMonth.plusWeeks( 1 );
    } while ( month == firstWedOfMonth.getMonthOfYear() );
} while ( firstWedOfMonth.getYear() == firstOfYear.getYear() );

Dump to console.

System.out.println( "list: " + list );

When run.

List: [2014-01-01, 2014-01-15, 2014-02-05, 2014-02-19, 2014-03-05, 2014-03-19, 2014-04-02, 2014-04-16, 2014-05-07, 2014-05-21, 2014-06-04, 2014-06-18, 2014-07-02, 2014-07-16, 2014-08-06, 2014-08-20, 2014-09-03, 2014-09-17, 2014-10-01, 2014-10-15, 2014-11-05, 2014-11-19, 2014-12-03, 2014-12-17]
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154