Java 8: Обчислення різниці між двома ZonedDateTime


80

Я намагаюся написати метод для друку різниці в часі між двома ZonedDateTime , щодо різниці між часовими поясами.

Я знайшов кілька рішень, але всі вони були написані для роботи з LocalDateTime .


2
Опублікуйте конкретний приклад того, чого ви хочете досягти, і отримайте в результаті.
JB Nizet

2
Відповідь Міхала - саме те, що я очікував. Дуже дякую!
Меггі Хілл

Відповіді:


102

Ви можете використовувати метод між з ChronoUnit .

Цей метод перетворює ці часи в одну і ту ж зону (зона з першого аргументу), а після цього викликає, поки метод не оголошений у тимчасовому інтерфейсі:

static long zonedDateTimeDifference(ZonedDateTime d1, ZonedDateTime d2, ChronoUnit unit){
    return unit.between(d1, d2);
}

Оскільки і ZonedDateTime, і LocalDateTime реалізують тимчасовий інтерфейс, ви також можете написати універсальний метод для тих типів дати та часу:

static long dateTimeDifference(Temporal d1, Temporal d2, ChronoUnit unit){
    return unit.between(d1, d2);
}

Але майте на увазі, що виклик цього методу для змішаних LocalDateTime і ZonedDateTime веде до DateTimeException .

Сподіваюся, це допоможе.


Чи є спосіб отримати різницю між двома типами ZDT, коли ZoneId відрізняється між двома ZDT?
stanlick

@stanlick Так: Duration.between( zdtA , zdtB )як показано в моїй відповіді . Я думаю, betweenметод просто закликає ZonedDateTime::toInstant()до обох.
Basil Bourque

73

tl; д-р

Години, хвилини, секунди:

Duration.between( zdtA , zdtB )  // Represent a span-of-time in terms of days (24-hour chunks of time, not calendar days), hours, minutes, seconds. Internally, a count of whole seconds plus a fractional second (nanoseconds).

Роками, місяцями, днями:

Period.between(                  // Represent a span-of-time in terms of years-months-days. 
    zdtA.toLocalDate() ,         // Extract the date-only from the date-time-zone object. 
    zdtB.toLocalDate() 
)

Деталі

Відповіді на цей питання Міхал S правильно, показуючи ChronoUnit.

Duration & Period

Інший маршрут - Duration і Periodкласи. Перший використовуйте на коротший проміжок часу (години, хвилини, секунди), другий - на довший (роки, місяці, дні).

Duration d = Duration.between( zdtA , zdtB );

Створіть рядок у стандартному форматі ISO 8601 , зателефонувавшиtoString . Формат - PnYnMnDTnHnMnSтам, де Pпозначено початок і Tрозділено дві частини.

String output = d.toString();

У Java 9 і пізніших версіях викликайте to…Partметоди для отримання окремих компонентів. Обговорюється в іншій моїй відповіді .

Приклад коду

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtStart = ZonedDateTime.now( z );
ZonedDateTime zdtStop = zdtStart.plusHours( 3 ).plusMinutes( 7 );

Duration d = Duration.between( zdtStart , zdtStop );

2016-12-11T03: 07: 50.639-05: 00 [Америка / Монреаль] /2016-12-11T06:14:50.639-05:00 [Америка / Монреаль]

PT3H7M

Подивитися живий код на IdeOne.com .

Interval & LocalDateRange

Проект ThreeTen-Extra додає функціональність класам java.time. Одним з його зручних класів є Intervalвідображення проміжку часу як пари точок на шкалі часу. Інший - LocalDateRangeдля пари LocalDateоб’єктів. На відміну від цього, усі класи Period& Durationпредставляють проміжок часу, який не прикріплений до часової шкали.

Заводський метод Intervalбере пару Instantоб’єктів.

Interval interval = Interval.of( zdtStart.toInstant() , zdtStop.toInstant() );

Ви можете отримати Durationз Interval.

Duration d = interval.toDuration();

Таблиця проміжків занять на Java та в проекті ThreeTen-Extra


Про java.time

Java.time каркас вбудований в Java 8 і пізніших версій. Ці класи витісняти неприємні старі застарілі класи дати і часу , такі як java.util.Date, Calendar, і SimpleDateFormat.

Проект Joda-Time , який зараз перебуває в режимі обслуговування , радить перейти на java.time класи .

Щоб дізнатись більше, див. Підручник Oracle . І шукайте в Stack Overflow багато прикладів та пояснень. Специфікація - JSR 310 .

Ви можете обмінювати об'єкти java.time безпосередньо з базою даних. Використовуйте драйвер JDBC, сумісний з JDBC 4.2 або новішою. Не потрібно рядків, не потрібноjava.sql.* класи.

Де отримати класи java.time?

Проект ThreeTen-Extra розширює java.time додатковими класами. Цей проект є полігоном для можливих майбутніх доповнень до java.time. Ви можете знайти деякі корисні класи тут , такі як Interval, YearWeek, YearQuarter, і більш .


Де ви бачите of метод тривалості, який займає два моменти? Я тільки бачуpublic static Duration of(long amount, TemporalUnit unit)
Брайан Гордон

@BrianGordon Виправлено, замінюючи .ofна .between. Дякую.
Basil Bourque

Тривалість працює з ZonedDateTime, тим часом Період працює з LocalDate. виклик методу toLocalDate () потрібно зробити на нашому об’єкті zdt.
Гійом Герін

1
@guillaumeguerin Ви маєте рацію. Виправлено приклад мого коду. Дякую.
Василь Бурк

О, людино дякую, ваш приклад дуже гарний !!!!
Брендон Івата
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.