Вычисление даты Java в течение двух дней отключается
Это вызвало ошибку в стиле Y2K в моем программном обеспечении, если вы можете себе представить. Странная вещь - расчет за один год только происходит в течение двух дней в году, что я не уверен, как устранить неполадки.
Выход:
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
Я не уверен, какая часть утилит Java date может вызвать такую ошибку.
Код (так как тест настолько мал, что я включил полную рабочую программу):
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));
}
}
}
Ответы
Ответ 1
В этом проблема:
"dd-MMM-YYYY"
YYYY
- это недельный, а не календарный год. Вместо этого вы хотите YYYY
.
Последние два дня календарного 2012 года были в первую неделю недели 2013 года. Обычно вы должны использовать только недельный год в сочетании с спецификатором "неделя года" (w
).
Ответ 2
Я предполагаю, что вы используете java 1.7
.
Фрагмент кода выше не будет работать с java 1.6
, так как SimpleDateFormat("dd-MMM-YYYY")
поднимет java.lang.IllegalArgumentException
(YYYY недоступен в java 1.6
)
Вам нужно использовать yyyy
вместо yyyy
.
Y -> week-year
y -> year
здесь
ИЗМЕНИТЬ
Отлично работает с 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
Ответ 3
Проблема заключается в вашей форме формата даты - год должен быть yyyy
не yyyy
.
Если вы печатаете значение workingDate.getTime()
в каждой итерации цикла, вы увидите, что оно имеет ожидаемые значения:
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
Поэтому проблема заключается в использовании SimpleDateFormat.
Ответ 4
Вам нужно использовать нижний регистр y для года. Попробуйте следующее:
SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy");
Ответ 5
Для полноты, это современный ответ, используя LocalDate
(как рекомендовал Василий Бурк в комментарии).
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));
}
}
}
Запустив это сегодня, я получил
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
Несколько замечаний:
- Дайте явный языковой стандарт вашему форматиру, чтобы контролировать langauge вашего вывода. Даже если вы просто проходите
Locale.getDefault()
, вы говорите читателю, что вы подумали о локали и приняли решение.
- Аналогично дайте явному часовому поясу
LocalDate.now()
, чтобы сообщить читателю, что вы приняли решение (например, ZoneId.of("America/New_York")
для определенного часового пояса, ZoneId.systemDefault()
для настройки текущего часового пояса JVM).
- Я нахожу код более простым и понятным, чем код, используя старомодный класс
Calendar
. Это типично для новых классов.
- Я использовал
uuuu
год. yyyy
(нижний регистр) тоже работает, будет только разница за годы до общей эры (AKA BC).