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));
}
}
}
Find the time difference between two dates in millisecondes by using the method getTime() in Java as d2. getTime() – d1. getTime(). Use date-time mathematical formula to find the difference between two dates.
String dateStart = "11/03/14 09:29:58"; String dateStop = "11/03/14 09:33:43"; // Custom date format SimpleDateFormat format = new SimpleDateFormat("yy/MM/dd HH:mm:ss"); Date d1 = null; Date d2 = null; try { d1 = format.
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
).
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
here
EDIT
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
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.
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).You need to use lower case y for the year. Try this:
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With