ТЛ; др
( ChronoUnit.DAYS.between( start , today ) * 100 )
/
ChronoUnit.DAYS.between( start , stop )
java.time
Вы используете ужасные классы даты и времени, которые были вытеснены несколько лет назад классами java.time , определенными в JSR 310.
LocalDate
Класс LocalDate
представляет значение только для даты без времени суток и без часовой пояс или смещение от UTC .
Часовой пояс имеет решающее значение при определении даты. В любой момент времени дата меняется по всему земному шару в зависимости от зоны. Например, через несколько минут после полуночи в Париж Франция - это новый день, а еще "вчера" в Монреаль Квебек .
Если часовой пояс не указан, JVM неявно применяет свой текущий часовой пояс по умолчанию. Это значение по умолчанию может измениться в любой момент во время выполнения (!), Поэтому ваши результаты могут отличаться Лучше явно указать желаемый / ожидаемый часовой пояс в качестве аргумента. Если критично, подтвердите зону с вашим пользователем.
Укажите собственное имя часового пояса в формате Continent/Region
, например America/Montreal
, Africa/Casablanca
или Pacific/Auckland
. Никогда не используйте 2-4 буквенные сокращения, такие как EST
или IST
, так как они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
Если вы хотите использовать текущий часовой пояс 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 . То же самое для Year
& YearMonth
.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
Истекшие дни
Кажется, вы хотите получить процент в зависимости от количества дней. Чтобы получить количество прошедших дней, используйте метод between
в классе перечисления ChronoUnit
.
long days = ChronoUnit.DAYS.between( earlier , later ) ;
С помощью пары этих целых чисел вы можете рассчитать свой процент.
* +1078 * Пример
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
LocalDate start = today.minusDays( 5 ) ;
LocalDate stop = today.plusDays( 15 ) ;
long totalDays = ChronoUnit.DAYS.between( start , stop ) ;
long elapsedDays = ChronoUnit.DAYS.between( start , today ) ;
long percentComplete = ( elapsedDays * 100 ) / totalDays ;
Дамп на консоль.
System.out.println( "start.toString(): " + start ) ;
System.out.println( "today.toString(): " + today ) ;
System.out.println( "stop.toString(): " + stop ) ;
System.out.println( "totalDays: " + totalDays ) ;
System.out.println( "elapsedDays: " + elapsedDays ) ;
System.out.println( percentComplete + "%" ) ;
См. Этот код, запущенный на IdeOne.com .
start.toString (): 2019-06-04
today.toString (): 2019-06-09
stop.toString (): 2019-06-24
всего дней: 20
Прошедшие дни: 5
25%
Проверка входных данных
Конечно, для реальной работы вам нужно сделать немного больше.
Вы должны убедиться, что старт перед остановкой.
boolean startIsBeforeStop = start.isBefore( stop ) ;
Вам необходимо проверить, что сегодня находится пара дат.
boolean todayIsWithinRange = ( ! today.isBefore( start ) ) && today.isBefore( stop ) ;
ThreeTen-Extra
Если в вашей работе часто используются диапазоны дат, добавьте в свой проект библиотеку ThreeTen-Extra . Это дает вам удобный LocalDateRange
класс.
LocalDateRange range = LocalDateRange.of( start , stop ) ;
boolean startIsBeforeStop = ( range.lengthInDays() > 0 ) ; // A negative number beens the start is *not* before the stop.
boolean todayIsWithinRange = range.contains( today ) ;
О java.time
Фреймворк java.time встроен в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
Чтобы узнать больше, см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .
Проект Joda-Time , теперь в режиме обслуживания , рекомендует выполнить переход на классы java.time .
Вы можете обмениваться java.time объектами напрямую с вашей базой данных. Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии. Нет необходимости в строках, нет необходимости в java.sql.*
классах.
WhГде получить классы java.time?