3

I am trying to add consecutive Calendar days into an ArrayList. When I add one day into ArrayList and later use Calendar.add method to go to next day, then I don't know why the ArrayList is also automatically modified i.e. the original entry is added 1 day? Below is my code that would explain the situation:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.ArrayList;

public class TestingStuff {

    public static void main(String[] args) throws ParseException {

        ArrayList<Calendar> cals = new ArrayList<Calendar>();
        SimpleDateFormat sdf = new SimpleDateFormat("MMM dd");
        Calendar startDate = Calendar.getInstance();
        startDate.setTime(sdf.parse("Mar 25"));

        cals.add(startDate);
        Calendar secondDate = startDate;
        secondDate.add(Calendar.DATE, 1);
        Calendar thirdDate = Calendar.getInstance();
        thirdDate.setTime(sdf.parse("Mar 26"));

        if (cals.contains(thirdDate)) {
            System.out.println("It does contain");
        } else {
            System.out.println("Sorry, it does not contain");
        }
    }
}

I'm not expecting 26 Mar in the ArrayList, but it does. Thanks a lot!

Tiny
  • 27,221
  • 105
  • 339
  • 599

2 Answers2

5
Calendar secondDate = startDate;
secondDate.add(Calendar.DATE, 1);

This line means that secondDate and startDate refer to the same object, so modifying one also modifies the other.

If you want a new Calendar instance that's one day later than the other, you'll need to clone the first instance and then modify the clone, as suggested in this answer. For instance:

Calendar secondDate = (Calendar)startDate.clone();
secondDate.add(Calendar.DATE, 1);
Community
  • 1
  • 1
Alex
  • 13,811
  • 1
  • 37
  • 50
  • Hi Alex, thanks that works for me! I'm still wondering why did the object in the Array changed as both startDate and secondDate were changed later after inserting into Array? –  Apr 18 '14 at 08:31
  • What was added to the ArrayList was a reference to the same object referenced by `startDate` and `secondDate`, not a copy of that object. See http://stackoverflow.com/questions/40480/is-java-pass-by-reference for more details. – Alex Apr 18 '14 at 13:39
1

tl;dr

Use modern java.time class LocalDate.

LocalDate.of( 2020 , Month.MARCH , 25 ).plusDays( 1 ) 

Avoid legacy date-time classes

You are using the terrible date-time classes that were years ago supplanted by the modern java.time classes.

java.time.LocalDate

Seems you only care about the date, not the time-of-day nor time zone. So use the LocalDate class.

ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;

Add days.

LocalDate tomorrow = today.plusDays( 1 ) ;
LocalDate dayAfterTomorrow = tomorrow.plusDays( 1 ) ;

Collect in a list.

List< LocalDate > dates = new ArrayList<>( 3 ) ;
dates.add( today ) ;
dates.add( tomorrow ) ;
dates.add( dayAfterTomorrow ) ;

Or use new List.of for a non-modifiable list.

List< LocalDate > dates = List.of( today , tomorrow , dayAfterTomorrow ) ;

If you want to start with a specific day, use the LocalDate.of factory methods.

LocalDate localDate = LocalDate.of( 2020 , Month.MARCH , 25 ) ;

Then proceed with your date math.

for( int i = 0 ; i < 7 ; i ++ ) {
    list.add( localDate.plusDays( i ) ) ;
}

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.

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

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

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