1

I having a hard time wrapping my head around a problem I am having with Calendar.add() and I need a sanity check.

My integration tests started to fail today on a project I'm working on. I think it has something to do with a method where I calculating a date by subtracting x amount of days.

For some reason when I subtract 1 day from today (Monday 2 January 2017), I get the result 2016-01-01? I would expect 2017-01-01?

I tried with other dates and it seems to work fine, but seems when it the day is a Monday 2nd of any year it subtracts 1 year too much, instead of one day?

Have I misunderstood something basic with subtracting days in certain situations?

...

// fails. Result is 2010-01-01??
SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd");
Calendar now = Calendar.getInstance();
now.set(2011, 0, 2);
now.add(Calendar.DATE, -1);
assertEquals("2011-01-01", format.format(now.getTime()));

...
// fails. Result is 2016-01-01??
SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd");
Calendar now = Calendar.getInstance();
now.set(2017, 0, 2);
now.add(Calendar.DATE, -1);
assertEquals("2017-01-01", format.format(now.getTime()));

...

// works fine. 
SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd");
Calendar now = Calendar.getInstance();
now.set(2017, 0, 5);
now.add(Calendar.DATE, -1);
assertEquals("2017-01-04", format.format(now.getTime()));

...

// works fine. 
SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd");
Calendar now = Calendar.getInstance();
now.set(2016, 0, 2);
now.add(Calendar.DATE, -1);
assertEquals("2015-01-01", format.format(now.getTime()));

...
William Lee
  • 164
  • 1
  • 14
  • 5
    Replace `YYYY` with `yyyy`!!! Read the javadoc of [`SimpleDateFormat`](http://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html), *please!!!* – Andreas Jan 02 '17 at 17:48
  • Omg... I knew it was something lame.. That's why I need a sanity check. One of the util classes was refactored today and the format string was copied pasted and search&replaced from the webpage (https://www.w3.org/TR/NOTE-datetime). Haha I will accept all downvotes with happiness that it was something simple. Thanks! – William Lee Jan 02 '17 at 17:56
  • 1
    Not sure why it was downvoted except your code isn't fully runnable. Snaps for having tests detailed enough to detect it. – Gene Jan 02 '17 at 18:12
  • @Gene Ahh, I see. I will add runnable code in my next post. I just thought brevity was preferred on SO. Thanks for the info. – William Lee Jan 02 '17 at 18:26

1 Answers1

2

Use lowercase yyyy rather than uppercase YYYY in your formatting pattern. As seen here:

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

public class Dates {
    public static void main(String args[]){
        // OK
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar now = Calendar.getInstance();
        now.clear();
        now.set(2011, 0, 2);
        now.add(Calendar.DAY_OF_MONTH, -1);
        System.out.println(("2011-01-01".equals(format.format(now.getTime())) ));
        System.out.println(format.format(now.getTime()));

        // OK
        format = new SimpleDateFormat("yyyy-MM-dd");
        now = Calendar.getInstance();
        now.clear();
        now.set(2017, 0, 2);
        now.add(Calendar.DAY_OF_MONTH, -1);     
        System.out.println(("2017-01-01".equals(format.format(now.getTime())) ));
        System.out.println(format.format(now.getTime()));

        // OK
        format = new SimpleDateFormat("yyyy-MM-dd");
        now = Calendar.getInstance();
        now.clear();
        now.set(2017, 0, 5);
        now.add(Calendar.DAY_OF_MONTH, -1);
        System.out.println(("2017-01-04".equals(format.format(now.getTime())) ));
        System.out.println(format.format(now.getTime()));

        // OK
        format = new SimpleDateFormat("yyyy-MM-dd");
        now = Calendar.getInstance();
        now.clear();
        now.set(2016, 0, 2);
        now.add(Calendar.DAY_OF_MONTH, -1);
        System.out.println(("2016-01-01".equals(format.format(now.getTime())) ));
        System.out.println(format.format(now.getTime()));
    }
}

OUTPUT:

true
2011-01-01
true
2017-01-01
true
2017-01-04
true
2016-01-01
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Dani
  • 1,825
  • 2
  • 15
  • 29
  • Yeah, thanks :-) Andreas pointed out my error. Totally missed it and even checked the docs before posting :-P Guess I was tired. I will accept your answer as you used time to document it. – William Lee Jan 03 '17 at 08:22