Я хотел бы внести современный ответ.
ZonedDateTime endOfFebruary2010 = LocalDate.of(2010, Month.MARCH, 1)
.atStartOfDay(ZoneId.systemDefault())
.minusNanos(1);
System.out.println(endOfFebruary2010);
В моем часовом поясе это печатает:
2010-02-28T23: 59: +59,999999999 + 01: 00 [Европа / Копенгаген]
Распечатка остается одинаковой независимо от времени года и месяца, когда вы ее запускаете. Зависимость от часового пояса может быть неудачной, но ее можно исправить, указав нужный часовой пояс, например ZoneId.of("Asia/Oral")
. Я использую и рекомендую java.time
, современный Java API даты и времени.
Если вам необходим старомодный объект java.util.Date
(и только в этом случае), преобразуйте:
Date oldFashionedDate = Date.from(endOfFebruary2010.toInstant());
System.out.println(oldFashionedDate);
вс 28 февраля 23:59:59 CET 2010
Если вам нужно было только количество дней в каком-либо месяце (это было задано в дублирующем вопросе ):
YearMonth ym = YearMonth.of(2011, Month.FEBRUARY);
int numDays = ym.lengthOfMonth();
System.out.println(numDays);
28
Как я понимаю, ваш настоящий вопрос был:
... Мне было интересно, действительно ли это было требуемое поведение. Какие-нибудь мысли
Я твердо верю, что желаемым поведением является то, что конструктор no-arg GregorianCalendar
возвращает текущий день и текущее время дня. И это Calender.set()
только устанавливает поля, которые вы явно задаете, и пытается сохранить другие поля без изменений. И это 31 февраля 2010 года переполняется в марте без каких-либо признаков ошибки, потому что в месяце было только 28 дней. Сочетание этих дизайнерских решений приводит меня к неизбежному выводу: поведение, которое вы наблюдали, является умышленным.
Если вы считаете, что это плохой дизайн, мы многие с вами согласны. По этой же причине замена Calendar
и GregorianCalendar
появилась на java.time
четыре года назад. Вам никогда не понадобится снова использовать Calendar
.
Резервирование: наш инструмент все еще зависит от Java 1.7
java.time
прекрасно работает на Java 7. Для этого требуется как минимум Java 6 .
- В Java 8 и более поздних версиях и на более новых устройствах Android (от 26 уровня API, как мне сказали) современный API поставляется встроенным.
- В Java 6 и 7 получите ThreeTen Backport, бэкпорт новых классов (ThreeTen для JSR 310; см. Ссылки внизу).
- На более старых (Android) версиях Android используется ThreeTen Backport. Это называется ThreeTenABP. И убедитесь, что вы импортируете классы даты и времени из
org.threeten.bp
с подпакетами.
Ссылки