Мне смешно, что Java (или библиотека java.util) не имеет встроенной функции для вычисления разницы в датах. Я хочу вычесть одну дату из другой, чтобы узнать время, прошедшее между ними. Как лучше всего это сделать?
Я знаю, что самый простой способ - это взять разницу во времени в миллисекундах и затем преобразовать ее в дни. Однако я хотел знать, работает ли это во всех случаях (с переходом на летнее время и т. д.).
Хорошая статья. Спасибо!
@Anirudh Найдите в StackOverflow "joda" и такие термины, как "span", "Interval", "Duration", "Period". Вы найдете много примеров с обсуждением.




В Java не так много упущений, если вы посмотрите на открытый исходный код: попробуйте Джода-Тайм.
вопрос о дате Java ==> в ответе упоминается Joda!
Да, именно так это работает, когда в языке есть 2 дефектных класса даты / времени.
Посмотрел на Joda - к сожалению, нестандартные библиотеки использовать нельзя :(
Я думаю, что в наши дни Джода довольно стандартная :-)
Действительно, потомок Joda-Time (пакет java.time) теперь является официальной частью Java со вчерашнего дня в комплекте с выпуском Java 8.
I know the simple way is to take the difference of the time in milliseconds and then convert that into days. However, i wanted to know if this works in all cases (with daylight saving, etc.).
Если ваше время получено из дат в формате UTC или это просто разница между двумя вызовами System.getCurrentTimeMillis (), измеренными в одной и той же системе, вы получите допустимое количество миллисекунд в качестве разницы, независимо от каких-либо проблем с часовым поясом. (вот почему все должно использовать UTC в качестве формата хранения - гораздо проще перейти от UTC-> местного времени; если вы попытаетесь пойти другим путем, вам нужно сохранить местный часовой пояс вместе с местным временем - или попытайтесь вывести это, черт возьми!)
Что касается превращения этого количества в количество дней, вы должны просто иметь возможность разделить на 86400000 ... с оговоркой, что каждые два года или около того случаются случайные високосная секунда.
Реализация дат в Java оставляет желать лучшего. Если вы находите Джода-Тайм слишком сложным, попробуйте мой небольшой вклад в открытый исходный код: http://calendardate.sourceforge.net/javadoc/index.html
Я не согласен с утверждением, что в Java нет механизма для вычисления разницы между датами.
Java была разработана для глобального использования. Он был разработан таким образом, что нет понятия даты, есть только понятие «время в миллисекундах». Любая интерпретация такого универсального времени, как время и дата в определенном месте в соответствии с определенным соглашением, является просто проекцией или представлением.
Класс календаря используется для преобразования такого рода абсолютного времени в даты. Вы также можете добавлять или вычитать компоненты даты, если вам действительно нужно. Единственный способ обеспечить разницу в сроках компонентов между двумя временами - это создать календарь и определить его. Таким образом, вы можете утверждать, что стандартная библиотека не включает достаточно умный григорианский календарь, и я согласен, что некоторые из них оставляют желать лучшего.
При этом существует множество реализаций такого рода функций, я вижу, что другие приводили примеры.
Я согласен с вами в принципе. Мое заявление о том, что Java не имеет этой функциональности, было основано на том факте, что другие языки (Ruby, Python и т. д.) Имеют очень простую (и работающую) реализацию добавления и вычитания дат как часть стандартных классов Date.
С библиотекой date4j:
int numDaysBetween = oneDate.numDaysFrom(anotherDate);
Есть простой способ реализовать это. Мы можем использовать метод Calendar.add с циклом. Например, как показано ниже,
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
Date beginDate = dateFormat.parse("2013-11-29");
Date endDate = dateFormat.parse("2013-12-4");
Calendar beginCalendar = Calendar.getInstance();
beginCalendar.setTime(beginDate);
Calendar endCalendar = Calendar.getInstance();
endCalendar.setTime(endDate);
Минусовые дни между beginDate и endDate и код, как показано ниже,
int minusDays = 0;
while (true) {
minusDays++;
// Day increasing by 1
beginCalendar.add(Calendar.DAY_OF_MONTH, 1);
if (dateFormat.format(beginCalendar.getTime()).
equals(dateFormat.format(endCalendar).getTime())) {
break;
}
}
System.out.println("The substractation between two days is " + (minusDays + 1));
Повеселись! @. @
Я использовал этот метод раньше. Однако время выполнения - O (N), где N - количество дней между beginDate и endDate. Я подозреваю, что использование JodaTime даст лучшие результаты.
Ага, ты прав. НО я думаю, что O (n) приемлемо для некоторых проектов. Потому что я не хочу импортировать библиотеки lib. Тем не менее, спасибо за ваши предложения.
Используйте либо Joda-Time, либо новый пакет java.time в Java 8.
Обе структуры используют подход Полуоткрытый, где начало - инклюзивный, а окончание - эксклюзивный. Иногда обозначается как [). Как правило, это лучший подход для определения промежутков времени.
Инфраструктура java.time, встроенная в Java 8 и более поздние версии, имеет класс Period для представления промежутка времени в виде числа лет, месяцев и дней. Но этот класс ограничен целыми днями, без представления часов, минут и секунд.
Обратите внимание, что мы указываем часовой пояс, который имеет решающее значение для определения даты. Например, в Париж новый день начинается раньше, чем в Монреаль.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate now = LocalDate.now( zoneId );
LocalDate then = LocalDate.of( 2001, 1, 1 );
Period period = Period.between( then, now );
Then: 2001-01-01. Now: 2015-09-07. Period: P14Y8M6D. Days: 5362
Для целых дней то Летнее время (DST) неактуально.
Если вы хотите подсчитать общее количество дней, используйте перечисление ChronoUnit, которое включает некоторые методы расчета. Заметьте, что вычисления возвращаются долго.
long days = ChronoUnit.DAYS.between( then, now ); // "5362" seen above.
я спрашивал о выполнении полного периода в java.time, включая часы, минуты, секунды. Невозможно в Java 8. Неожиданный обходной путь с использованием связанных библиотек было предложено от Мено Хохшильд: используйте класс Duration, найденный в пакет javax.xml.datatype.
Вот пример кода в Joda-Time 2.3.
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Paris" );
DateTime start = new DateTime( 2014, 1, 2, 3, 4, 5, timeZone );
DateTime stop = new DateTime( 2014, 5, 2, 3, 4, 5, timeZone );
Period period = new Period( start, stop );
Вызов toString даст вам строковое представление в форме, определенной стандартом ISO 8601, PnYnMnDTnHnMnS.
См. xmission.com/~goodhill/dates/deltaDates.html для некоторой предыстории.