0

I'm having problem when I try to reset the Calendar because it doesn't recover the original date. What am I doing wrong ?

public static void main(String[] args) {
   Calendar from = Calendar.getInstance();
   int contador = 0;
   while (contador < 30) {
      Calendar cal = from;
      for (int i = 0; i < 3; i++) {
         cal.add(Calendar.DAY_OF_YEAR, +1);
         System.out.println("Dia: " + String.valueOf(cal.get(Calendar.YEAR) + "/" + (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DAY_OF_MONTH)));
      }
      contador++;
   }
}

That is the result:

Dia: 2017/6/21
Dia: 2017/6/22
Dia: 2017/6/23
Dia: 2017/6/24
Dia: 2017/6/25
Dia: 2017/6/26
Dia: 2017/6/27
Dia: 2017/6/28
Dia: 2017/6/29
Dia: 2017/6/30
...... 
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Jaume
  • 39
  • 1
  • 2
  • It hasn’t really got anything to do with you question, but these days you should not be using the long outdated `Calendar` class. Prefer the modern `LocalDate`. It is much nicer to work withm more programmer friendly. Also it will make your code a bit simpler. It will also eliminate your problem since you will need to make a new object every time you add a day. – Ole V.V. Jun 20 '17 at 08:50
  • 1
    Where do you think you reset the calendar? – Tom Jun 20 '17 at 08:51

3 Answers3

3

Because you are not doing a copy of Calendar from with Calendar cal = from. So when you update cal, you update also from because those two are the same instance.

Just call Calendar.getInstance() each time you need a new Calendar.

Calendar cal = Calendar.getInstace();

As Ole V.V said in comments, you could have a strange behavior if this code is running just before midnigh, you could get a different "date" value with a Calendar.getInstance(). This is why this solution as some risk.

To prevent that, you could clone() the instance, Calendar implements Cloneable. This would assure you to use the exact same date and time. As this will recreate a new instance with the exact argument.

Calendar cal = (Calendar) from.clone();
AxelH
  • 14,325
  • 2
  • 25
  • 55
  • Just getting a new `Calendar` instance every time could give a surprising result if you run the code over midnight. – Ole V.V. Jun 20 '17 at 09:07
  • 1
    @OleV.V. That's exactly why I continue with the `cloneable` interface to assure to use the same time, I should have explain why ;) (I had that bug once, I will never forget that now ;) ) – AxelH Jun 20 '17 at 09:10
  • You did explain (maybe I wanted to make it a bit clearer, maybe my comment was superfluous). Thanks for reporting you had that bug, I believe we can all learn from it. – Ole V.V. Jun 20 '17 at 09:12
1

The answer by AxelH is correct. I am posting this answer to show you the use of the modern class LocalDate for your purpose. Because it is easier and automatically eliminates your problem because of the better designed API; but mostly because the modern classes are generally nicer to work with, more programmer friendly, so no one should use the long outdated Calendar class anymore IMHO.

private static DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("uuuu/M/d");

public static void main(String[] args) {
    // give explicit time zone
    LocalDate from = LocalDate.now(ZoneId.systemDefault());
    int contador = 0;
    while (contador < 30) {
        LocalDate cal = from;
        for (int i = 0; i < 3; i++) {
            cal = cal.plusDays(1);
            System.out.println("Dia: " + cal.format(dateFormatter));
        }
        contador++;
    }
}

The output goes:

Dia: 2017/6/21
Dia: 2017/6/22
Dia: 2017/6/23
Dia: 2017/6/21
Dia: 2017/6/22
Dia: 2017/6/23
Dia: 2017/6/21
Dia: 2017/6/22
Dia: 2017/6/23
Dia: 2017/6/21
…

No matter if you use the old or the newer class, I recommend you give explicit time zone as shown, to make it clear for the reader that obtaining today’s date is a time zone dependent operation.

In case you can live with hyphens instead of slashes in the output, you may drop the use of dateFormatter and just print like this:

            System.out.println("Dia: " + cal);

Output:

Dia: 2017-06-21
Dia: 2017-06-22
…
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0
Calendar cal = Calendar.getInstance();

// The default Date constructor defaults to local time.
cal.setTime(new Date());
Elior Malul
  • 683
  • 6
  • 8
  • Please read [How do I write a good answer?](https://stackoverflow.com/help/how-to-answer). While this code block may answer the OP's question, this answer would be much more useful if you explain how this code is different from the code in the question, what you've changed, why you've changed it and why that solves the problem without introducing others. – Saeed Zhiany Jun 27 '22 at 07:11
  • I think that cloning a singletone instance is dangerous, and is and anti-pattern in general. The solution above is reseting the calendar to the cureent date w/o cloning the singletone object. – Elior Malul Jun 27 '22 at 07:56