tl; dr
Вы должны использовать LocalDate
с нормальным подсчетом вместо проблемного Calendar
класса.
ChronoUnit.DAYS.between(
LocalDate.of( 2013 , 11 , 30 ) ,
LocalDate.of( 2013 , 12 , 1 )
)
См. Этот код, запущенный в прямом эфире на IdeOne.com .
1
Сумасшедший счет
Вы, кажется, не знаете о сумасшедшем подсчете, используемом в ужасном классе Calendar
: 0-11 в течение месяцев январь-декабрь.
То есть cal1.set(2013, 11, 30)
до cal2.set(2013, 12, 1)
означает 30 октября - 1 ноября, что действительно составляет два дня, что соответствует 31 октября. Вы, очевидно, ошибочно считали это с 30 ноября по 1 декабря, но нет.
Это подсчет индекса, начиная с нуля .К сожалению, подсчет индексов проявляется слишком часто, когда некоторые программисты неуместно используют то, что имело смысл с примитивными массивами или скачками памяти в системном программировании или программировании в стиле C старой школы.В обычных бизнес-приложениях с современными языками подсчет порядковых номеров обычно имеет больше смысла.Например, думать о январе как о первом месяце, месяце 1 и декабре как о двенадцатом месяце, месяце 12.
java.time
К счастью, у нас есть java.time классы сейчас.У вас нет причин использовать ужасный беспорядок, который представляет собой устаревшие классы даты и времени, такие как Date
, Calendar
и SimpleDateFormat
.
Для использования с Java 7 см. ThreeTen-Backport проект, связанный в пулях внизу.
LocalDate
Класс LocalDate
представляет значение только для датыбез времени суток и без часового пояса.
Часовой пояс имеет решающее значение при определении даты.В любой момент времени дата меняется по всему земному шару в зависимости от зоны.Например, через несколько минут после полуночи в Париж Франция - это новый день, в то время как "вчера" в Монреаль Квебек .
Если часовой пояс не указан,JVM неявно применяет свой текущий часовой пояс по умолчанию.Это значение по умолчанию может измениться в любой момент во время выполнения (!), Поэтому ваши результаты могут отличаться.Лучше указать в качестве аргумента желаемый / ожидаемый часовой пояс .
Укажите правильное имя часового пояса в формате continent/region
, например America/Montreal
, Africa/Casablanca
или Pacific/Auckland
.Никогда не используйте 3-4-буквенное сокращение, например EST
или IST
, так как они не истинных часовых поясов, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
Если вы хотите использовать текущий часовой пояс JVM по умолчанию, запросите его и передайте в качестве аргумента.Если опущено, текущее значение по умолчанию JVM применяется неявно.Лучше быть явным, поскольку значение по умолчанию может быть изменено в любой момент во время выполнения любым кодом в любом потоке любого приложения в JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Или укажите дату.Вы можете установить месяц по номеру, с нормальным номером 1-12 для января-декабря.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Или, лучше, использовать предварительно определенные объекты перечисления Month
, по одному на каждый месяц года.Совет: используйте эти Month
объекты по всей вашей кодовой базе, а не просто целое число, чтобы сделать ваш код более самодокументируемым, обеспечить допустимые значения и обеспечить type-safety .
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
ChronoUnit.DAYS
Для подсчета прошедших дней используйте перечисление ChronoUnit
.
long days = ChronoUnit.DAYS.between( start , stop ) ;
О java.time
Среда java.time встроена в Java 8 и более поздние версии.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
Проект Joda-Time , теперь в режиме обслуживания , рекомендует выполнить переход на классы java.time .
Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация JSR 310 .
Youможет обмениваться java.time объектами напрямую с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версией.Нет необходимости в строках, нет необходимости в java.sql.*
классах.
Где получить классы java.time?
ThreeTen-Extra Проект расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти некоторые полезные классы, такие как Interval
, YearWeek
, YearQuarter
и more .