Reputation: 60788
This caused a Y2K-style bug in my software if you can imagine. Strange thing is the off-by-one year calculation only occurs for two days in the year, which I'm less sure how to troubleshoot.
The output:
03-Jan-2013
02-Jan-2013
01-Jan-2013
31-Dec-2013 ** strange
30-Dec-2013 ** strange
29-Dec-2012
28-Dec-2012
27-Dec-2012
26-Dec-2012
25-Dec-2012
I am not sure which part of the Java date utilities could cause such an error.
The code (since the test is so small I included a complete working program):
import java.util.Calendar;
import java.util.Date;
import java.text.SimpleDateFormat;
public class DateT {
private static String getFormattedBackscanStartTime(int days) {
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-YYYY");
Calendar workingDate = Calendar.getInstance();
workingDate.add(Calendar.DATE, -1 * days);
String formattedStartTime = dateFormat.format(workingDate.getTime());
return formattedStartTime;
}
public static void main(String args[]) {
for(int i = 35; i < 45; i++) {
System.out.println(getFormattedBackscanStartTime(i));
}
}
}
Upvotes: 19
Views: 7556
Reputation: 12099
I am assuming you are using Java 1.7.
The code snippet above will not work with Java 1.6 as SimpleDateFormat("dd-MMM-YYYY")
will raise an java.lang.IllegalArgumentException
(YYYY is not available in Java 1.6)
You need to use yyyy
instead of YYYY
.
Y -> week-year
y -> year
It works great with yyyy
:
$ java DateT
03-Jan-2013
02-Jan-2013
01-Jan-2013
31-Dec-2012
30-Dec-2012
29-Dec-2012
28-Dec-2012
27-Dec-2012
26-Dec-2012
25-Dec-2012
Upvotes: 8
Reputation: 86324
For the sake of completeness, here’s the modern answer using LocalDate
(as recommended by Basil Bourque in a comment).
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class DateT {
private static DateTimeFormatter dateFormatter
= DateTimeFormatter.ofPattern("dd-MMM-uuuu", Locale.US);
private static String getFormattedBackscanStartTime(int days) {
return LocalDate.now(ZoneId.systemDefault()).minusDays(days).format(dateFormatter);
}
public static void main(String args[]) {
for(int i = 155; i < 165; i++) {
System.out.println(getFormattedBackscanStartTime(i));
}
}
}
Running this today I got
04-Jan-2017
03-Jan-2017
02-Jan-2017
01-Jan-2017
31-Dec-2016
30-Dec-2016
29-Dec-2016
28-Dec-2016
27-Dec-2016
26-Dec-2016
A few things to note:
Locale.getDefault()
you are telling the reader that you have thought about locale and made a decision.LocalDate.now()
to tell the reader you’ve made a decision (for example ZoneId.of("America/New_York")
for a specific time zone; ZoneId.systemDefault()
for the JVM’s current time zone setting).Calendar
class. This is typical for the newer classes.uuuu
for year. yyyy
(lowercase) works too, there will only be a difference for years before the common era (AKA BC).Upvotes: 3
Reputation: 103145
You need to use lower case y for the year. Try this:
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy");
Upvotes: 2
Reputation: 139961
The problem lies in your date format string - year should be yyyy
not YYYY
.
If you print the value of workingDate.getTime()
in each iteration of the loop, you'll see it has the expected values:
Thu Jan 03 11:19:33 EST 2013
Wed Jan 02 11:19:33 EST 2013
Tue Jan 01 11:19:33 EST 2013
Mon Dec 31 11:19:33 EST 2012
Sun Dec 30 11:19:33 EST 2012
Sat Dec 29 11:19:33 EST 2012
Fri Dec 28 11:19:33 EST 2012
Thu Dec 27 11:19:33 EST 2012
Wed Dec 26 11:19:33 EST 2012
Tue Dec 25 11:19:33 EST 2012
Therefore the problem lies in the SimpleDateFormat usage.
Upvotes: 3
Reputation: 1502106
This is the problem:
"dd-MMM-YYYY"
YYYY
is the week-year, not the calendar year. You want yyyy
instead.
The last two days of calendar year 2012 were in the first week of week-year 2013. You should normally only use the week year in conjunction with the "week of year" specifier (w
).
Upvotes: 50