22

I know there is the same question here, but I have tried the answer provided and it returned an output that I don't understand. I am confused by the answer and I don't think the output is correct.

I need help, thank you :)

GregorianCalendar date1 = new GregorianCalendar( 2014, 05, 12 ); //05 is june as month start from 0 -11

while( date1.get( Calendar.DAY_OF_WEEK ) != Calendar.MONDAY )
    date1.add( Calendar.DATE, 1 );  

System.out.println(date1);

Here is the output:

java.util.GregorianCalendar[time=1405267200000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Singapore",offset=28800000,dstSavings=0,useDaylight=false,transitions=9,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2014,MONTH=6,WEEK_OF_YEAR=29,WEEK_OF_MONTH=3,DAY_OF_MONTH=14,DAY_OF_YEAR=195,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=2,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=0,ZONE_OFFSET=28800000,DST_OFFSET=0]

Where on the output should I extract to retrieve Monday's date?

Community
  • 1
  • 1
Ridzuan Adris
  • 1,192
  • 2
  • 13
  • 32
  • Do you want the Monday before or after the specified date? – MadProgrammer Jun 12 '14 at 06:11
  • after specified date :) – Ridzuan Adris Jun 12 '14 at 06:11
  • 1
    System.out.println(date1.getTime()); – Rod_Algonquin Jun 12 '14 at 06:12
  • 1
    `DAY_OF_WEEK=2` - output looks correct (albeit not human-friendly). – user2864740 Jun 12 '14 at 06:13
  • @Rod_Algonquin the output is "Mon Jul 14 00:00:00 SGT 2014", well now i know the code is for 1st monday on the month, what i seek actually was the fist next monday date after given specific date like if given date is 12 june 2014 it will return Mon 16 june 2014..than you Rod for your quick reply – Ridzuan Adris Jun 12 '14 at 06:16
  • 2
    If you're able to use Java 8, I'd advise you to use the `java.time` classes. Otherwise, I'd advise you to use Joda Time. Note that currently you're trying to find the next Monday (or today - your while loop won't iterate even once if it's already Monday) *in the system time zone*. Is that what you want? – Jon Skeet Jun 12 '14 at 06:17
  • @ Jon Skeet, yes jon that is exactly what i am currently looking for, i dont think changing to java 8 is an option at the current state. ill look at joda time :) – Ridzuan Adris Jun 12 '14 at 06:21
  • 1
    `Calendar` months are `0` indexed, you've specified July not June... – MadProgrammer Jun 12 '14 at 06:24
  • Thanks @MadProgrammer, its a relieve i don't have to start researching joda time at this moment :). it work and i should have realize that earlier. – Ridzuan Adris Jun 12 '14 at 06:29
  • 1
    @beNice I'd still consider using JodaTime when you can – MadProgrammer Jun 12 '14 at 06:30
  • possible duplicate of [Retrieve current week's Monday's date](http://stackoverflow.com/questions/9307884/retrieve-current-weeks-mondays-date) – Basil Bourque Jun 13 '14 at 05:34
  • @Basil Bourque, please remove the duplicate statement, that question you refer was for current monday of the week, not next monday after date specified, that is one different question and different kind of answer. better kept this post for other who face same scenario as me, beside, this post was the extension of this 2011 post http://stackoverflow.com/questions/7565356/get-first-monday-after-certain-date – Ridzuan Adris Jun 13 '14 at 07:50
  • @beNice Really?! Passing today's date is different that passing a specific date? How is that different? Still seems like the exact same question to me. Or am I missing some other nuance? – Basil Bourque Apr 19 '15 at 01:28
  • I've added a [detailed answer](http://stackoverflow.com/a/29724887/642706) using [Joda-Time](http://www.joda.org/joda-time/) library with discussion and example code, on the 2011 dup Question, [Get first Monday after certain date?](http://stackoverflow.com/q/7565356/642706). – Basil Bourque Apr 19 '15 at 02:22

5 Answers5

50

Java 8+

LocalDate ld = LocalDate.of(2014, Month.JUNE, 12);
System.out.println(ld);
ld = ld.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
System.out.println(ld);

Which prints...

2014-06-12
2014-06-16

Because it's possible that the date my actually be a Monday, you could also use...

ld = ld.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY));

Java <= 7

You should be using the ThreeTen Backport, which gives you the support of the Java 8 Date/Time API

Original Answer

Instead of System.out.println(date1); use System.out.println(date1.getTime());

getTime returns an instance of Date which represents the current state of the Calendar

Which will output Mon Jul 14 00:00:00 EST 2014

System.out.println(date1) is the equivlent of using System.out.println(date1.toString()), which, in this case, is dumping a bunch of useful info about the state of the Calendar object, but not really human readable data.

System.out.println(date1.getTime()) will use the Date's to toString method to display a date value, formatted based on the current local settings, which will provide more useful information.

Updated

Instead of using GregorianCalendar, you should use the system Calendar, for example...

Calendar date1 = Calendar.getInstance();
date1.set(2014, 06, 12);

Also, months are 0 indexed, meaning that Janurary is actually 0 not 1, so in your example, you've specified the month as July, not June.

So, instead, using...

Calendar date1 = Calendar.getInstance();
date1.set(2014, 05, 12);

while (date1.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
    date1.add(Calendar.DATE, 1);
}

System.out.println(date1.getTime());

Which outputted...

Mon Jun 16 16:22:26 EST 2014

Which is next Monday from today...more or less ;)

Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Custom `TemporalAdjuster` example: https://stackoverflow.com/questions/42619409/java-8-find-nth-dayofweek-after-specific-day-of-month – Vadzim Mar 11 '20 at 10:03
15

tl;dr

LocalDate.of( 2014 , Month.JUNE , 12 )                    // Represent a date-only value, without time-of-day and without time zone.
         .with(                                           // Move from one date to another by passing an implementation of the `TemporalAdjuster` interface. 
             TemporalAdjusters.next( DayOfWeek.MONDAY )   // Use an existing implementation found on utility class `TemporalAdjusters` (plural versus singular).
         )                                                // Returns another fresh `LocalDate` object rather than altering the original, per immutable objects design.

Using java.time

You are using troublesome old date-time classes that are now legacy, supplanted by the java.time classes.

The LocalDate class represents a date-only value without time-of-day and without time zone.

LocalDate ld = LocalDate.of( 2014 , Month.JUNE , 12 ) ;

To get the following Monday, use a TemporalAdjuster implementation found in TemporalAdjusters class.

LocalDate nextMonday = ld.with( TemporalAdjusters.next( DayOfWeek.MONDAY ) ) ;

If you want to go with the original date if it is itself a Monday, then use nextOrSame adjuster.

LocalDate nextOrSameMonday = ld.with( TemporalAdjusters.nextOrSame( DayOfWeek.MONDAY ) ) ;

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.

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
3

A minor change to your code:

    GregorianCalendar date1 = new GregorianCalendar(2014, 6, 12);

    while (date1.get(Calendar.DAY_OF_WEEK) != Calendar.MONDAY) {
        date1.add(Calendar.DATE, 1);
    }

    SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
    System.out.println(sdf.format(date1.getTime()));

Yields:

 14-07-2014

EDIT: As per the JavaDoc documentation, the constructor you are using, expects a 0 based month index, so for the month of June, you will need to pass in a value of 5, not 6.

npinti
  • 51,780
  • 5
  • 72
  • 96
0

Just a suggestion - Instead of looping, you could just use the switch statement along with the Calendar.add() like this:

int weekdayNum = c.get(Calendar.DAY_OF_WEEK);

    switch (weekdayNum) {
    case 1: {
        c.add(Calendar.DAY_OF_MONTH, 1);
        break;
    }
    case 3: {
        c.add(Calendar.DAY_OF_MONTH, 6);
        break;
    }
    case 4: {
        c.add(Calendar.DAY_OF_MONTH, 5);
        break;
    }
    case 5: {
        c.add(Calendar.DAY_OF_MONTH, 4);
        break;
    }
    case 6: {
        c.add(Calendar.DAY_OF_MONTH, 3);
        break;
    }
    case 7: {
        c.add(Calendar.DAY_OF_MONTH, 2);
        break;
    }
    default:
        break;
    }
javaGirl243
  • 99
  • 3
  • 14
0

Or Just do some simple math. Since Calender.Monday equals 2, it is easy to calculate the number of days that need to be added to the current date.

Calendar date1 = Calendar.getInstance();
date1.set(2014, 05, 12);
int dayOfWeek = date1.get(Calendar.DAY_OF_WEEK);
date1.add(Calendar.DATE, (9 - dayOfWeek) % 7);
Dalancer
  • 1
  • 1
  • 1
    I do not see where you find the information that Monday equals 2. Can you explain? – Yunnosch May 09 '17 at 20:26
  • 1
    FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/8/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html), and `java.text.SimpleTextFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [java.time](https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque May 09 '17 at 21:23
  • @Yunnosch [`Calendar.MONDAY`](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#MONDAY) is indeed [documented as being a constant of type `int` with a value of `2`](https://docs.oracle.com/javase/8/docs/api/constant-values.html#java.util.Calendar.MONDAY). This numbering is peculiar to North America and other regions that commonly consider Sunday as first day of the week. The ISO 8601 standard defines Monday as first day. One of many reasons to avoid this troublesome old legacy class and instead use the modern java.time classes like `DayOfWeek` enum which follows the standard. – Basil Bourque May 10 '17 at 00:19
  • Thanks, I was thinking along totally different, and wrong, routes. – Yunnosch May 10 '17 at 04:34