Как найти разницу в днях между двумя Joda-Time DateTime
экземпляры?
С "разницей в днях" я имею в виду, что если начало в понедельник, а конец во вторник, я ожидаю возвращаемое значение 1 независимо от часа/минуты/секунды дат начала и окончания.
Days.daysBetween(start, end).getDays()
дает мне 0, если начало вечера и заканчивается утром.
У меня также такая же проблема с другими полями даты, поэтому я надеялся, что будет общий способ "игнорировать" поля с меньшим значением.
Иными словами, месяцы между февралем и 4 марта также будут равны 1, как и часы между 14:45 и 15:12. Однако часовая разница между 14:01 и 14:55 будет равна 0.
Ответ 1
Досадно, ответ withTimeAtStartOfDay ошибочен, но только изредка. Вы хотите:
Days.daysBetween(start.toLocalDate(), end.toLocalDate()).getDays()
Оказывается, что "полночь/начало дня" иногда означает 1 утра (в некоторых местах это происходит в летнее время), которые Days.daysBetween не обрабатывают должным образом.
// 5am on the 20th to 1pm on the 21st, October 2013, Brazil
DateTimeZone BRAZIL = DateTimeZone.forID("America/Sao_Paulo");
DateTime start = new DateTime(2013, 10, 20, 5, 0, 0, BRAZIL);
DateTime end = new DateTime(2013, 10, 21, 13, 0, 0, BRAZIL);
System.out.println(daysBetween(start.withTimeAtStartOfDay(),
end.withTimeAtStartOfDay()).getDays());
// prints 0
System.out.println(daysBetween(start.toLocalDate(),
end.toLocalDate()).getDays());
// prints 1
Переход через LocalDate
обходит всю проблему.
Ответ 2
Days
Класс
Используя класс Days
с withTimeAtStartOfDay
должен работать:
Days.daysBetween(start.withTimeAtStartOfDay() , end.withTimeAtStartOfDay() ).getDays()
Ответ 3
вы можете использовать LocalDate
:
Days.daysBetween(new LocalDate(start), new LocalDate(end)).getDays()
Ответ 4
ТЛ; др
java.time.temporal.ChronoUnit.DAYS.between(
earlier.toLocalDate(),
later.toLocalDate()
)
... или...
java.time.temporal.ChronoUnit.HOURS.between(
earlier.truncatedTo( ChronoUnit.HOURS ) ,
later.truncatedTo( ChronoUnit.HOURS )
)
java.time
К вашему сведению, проект Joda-Time в настоящее время находится в режиме обслуживания, а команда рекомендует перейти на классы java.time.
Эквивалентом Joda-Time DateTime
является ZonedDateTime
.
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;
Очевидно, вы хотите посчитать дни по датам, то есть вы хотите игнорировать время суток. Например, начиная с минуты до полуночи и заканчивая минутой после полуночи, вы получите один день. Для этого поведения извлеките LocalDate
из вашего ZonedDateTime
. Класс LocalDate
представляет значение только для даты без времени суток и часового пояса.
LocalDate localDateStart = zdtStart.toLocalDate() ;
LocalDate localDateStop = zdtStop.toLocalDate() ;
Используйте ChronoUnit
перечисление, чтобы вычислить прошедшие дни или другие единицы.
long days = ChronoUnit.DAYS.between( localDateStart , localDateStop ) ;
Округление
Что касается того, что вы спрашиваете о более общем способе подсчета, когда вас интересует разница часов в часах, а не полных часов в промежутке времени в шестьдесят минут, используйте метод truncatedTo
.
Вот ваш пример с 14:45 до 15:12 в тот же день.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime start = ZonedDateTime.of( 2017 , 1 , 17 , 14 , 45 , 0 , 0 , z );
ZonedDateTime stop = ZonedDateTime.of( 2017 , 1 , 17 , 15 , 12 , 0 , 0 , z );
long hours = ChronoUnit.HOURS.between( start.truncatedTo( ChronoUnit.HOURS ) , stop.truncatedTo( ChronoUnit.HOURS ) );
1
Это не работает в течение нескольких дней. В этом случае используйте toLocalDate().
О java.time
Среда java.time встроена в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
и & SimpleDateFormat
.
Проект Joda-Time, который теперь находится в режиме обслуживания, рекомендует выполнить переход на классы java.time.
Чтобы узнать больше, см. Учебное пособие по Oracle. И поищите в Кару множество примеров и объяснений. Спецификация: JSR 310.
Вы можете обмениваться объектами java.time напрямую с вашей базой данных. Используйте драйвер JDBC, совместимый с JDBC 4.2 или более поздней версией. Нет необходимости в строках, нет необходимости в классах java.sql.*
.
Где взять классы java.time?
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval
, YearWeek
, YearQuarter
и еще more.
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти несколько полезных классов, таких как Interval
, YearWeek
, YearQuarter
и еще more.
Ответ 5
В принятом ответе строятся два объекта LocalDate
, которые довольно дороги, если вы читаете много данных.
Я использую это:
public static int getDaysBetween(DateTime earlier, DateTime later)
{
return (int) TimeUnit.MILLISECONDS.toDays(later.getMillis()- earlier.getMillis());
}
Вызывая getMillis()
, вы используете уже существующие переменные.
MILLISECONDS.toDays()
, то, используя простой арифметический расчет, не создает никакого объекта.
Ответ 6
java.time.Period
Используйте класс java.time.Period
для подсчета дней.
Поскольку вычисление разницы в Java 8 более интуитивно понятно с использованием LocalDate
, LocalDateTime
для представления двух дат
LocalDate now = LocalDate.now();
LocalDate inputDate = LocalDate.of(2018, 11, 28);
Period period = Period.between( inputDate, now);
int diff = period.getDays();
System.out.println("diff = " + diff);
Ответ 7
DateTime dt = new DateTime(laterDate);
DateTime newDate = dt.minus( new DateTime ( previousDate ).getMillis());
System.out.println("No of days : " + newDate.getDayOfYear() - 1 );
Ответ 8
public static int getDifferenceIndays(long timestamp1, long timestamp2) {
final int SECONDS = 60;
final int MINUTES = 60;
final int HOURS = 24;
final int MILLIES = 1000;
long temp;
if (timestamp1 < timestamp2) {
temp = timestamp1;
timestamp1 = timestamp2;
timestamp2 = temp;
}
Calendar startDate = Calendar.getInstance(TimeZone.getDefault());
Calendar endDate = Calendar.getInstance(TimeZone.getDefault());
endDate.setTimeInMillis(timestamp1);
startDate.setTimeInMillis(timestamp2);
if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) {
int day1 = endDate.get(Calendar.DAY_OF_MONTH);
int day2 = startDate.get(Calendar.DAY_OF_MONTH);
if (day1 == day2) {
return 0;
} else {
return 1;
}
}
int diffDays = 0;
startDate.add(Calendar.DAY_OF_MONTH, diffDays);
while (startDate.before(endDate)) {
startDate.add(Calendar.DAY_OF_MONTH, 1);
diffDays++;
}
return diffDays;
}