Это просто часть ужасного беспорядка, который представляет собой API даты / времени Java. Перечисление того, что с ним не так, заняло бы очень много времени (и я уверен, что я не знаю половину проблем). По общему признанию, работать с датами и временем сложно, но все равно.
Сделайте себе одолжение и используйте Joda Time или, возможно, JSR-310 .
РЕДАКТИРОВАТЬ: Что касается причин, почему - как отмечалось в других ответах, это может быть связано со старыми API C или просто с ощущением, что все начинается с 0 ... за исключением того, что дни начинаются с 1, конечно. Я сомневаюсь, что кто-то за пределами исходной команды реализации мог бы действительно изложить причины - но я бы настоятельно призвал читателей не беспокоиться так сильно о , почему были приняты плохие решения, чтобы взглянуть на всю гамму злобности в java.util.Calendar
и найди что-нибудь получше.
Единственное замечание, которое является в пользу использования индексов на основе 0, заключается в том, что это облегчает такие вещи, как "массивы имен":
// I "know" there are 12 months
String[] monthNames = new String[12]; // and populate...
String name = monthNames[calendar.get(Calendar.MONTH)];
Конечно, это не сработает, как только вы получите календарь с 13 месяцами ... но, по крайней мере, указанный размер соответствует ожидаемому числу месяцев.
Это не хорошая причина, но это причина ...
РЕДАКТИРОВАТЬ: В качестве комментария просит некоторые идеи о том, что я думаю, что неправильно с Дата / Календарь:
- Удивительные основы (1900 как годовая база в Date, допустимо для устаревших конструкторов; 0 как месячная база в обоих)
- Изменчивость - использование неизменяемых типов упрощает работу с действительно эффективными значениями
- Недостаточный набор типов: приятно иметь
Date
и Calendar
как разные вещи,
но разделение "локальных" и "зонированных" значений отсутствует, как и дата / время против даты против времени
- API, который приводит к некрасивому коду с магическими константами, вместо явно названных методов
- API, о котором очень сложно рассуждать - все дело в том, когда что-то пересчитывается и т. Д.
- Использование конструкторов без параметров по умолчанию "now", что приводит к трудному для тестирования коду
- Реализация
Date.toString()
, которая всегда использует локальный часовой пояс системы (это смущало многих пользователей переполнения стека до сих пор)