Как посчитать время потраченное на выполнение задания?
Пишу маленькое приложение на Android на Java. У меня пользователи в одном активити проходят тест и, по завершению теста, открывается следующее активити, в которое передается итоговая инфа по прохождению теста. Так вот, одно из полей — это потраченное время на задание. я пробую считать время хронометром, но он в миллисекундах считает и потом форматировать через различные проверки в формат 00:00 (02 : 34), очень костыльно получается. Я уверен, что есть более изящное решение. Как это можно сделать?
Отслеживать
5,185 3 3 золотых знака 23 23 серебряных знака 48 48 бронзовых знаков
задан 14 дек 2015 в 21:13
10.9k 17 17 золотых знаков 62 62 серебряных знака 127 127 бронзовых знаков
Измерьте прошедшее время (или время выполнения) в Java
В этом посте будет обсуждаться, как измерить прошедшее время в Java, используя System.nanoTime() , System.currentTimeMillis() , Instant.now() а также StopWatch предоставлено Guava и Apache Commons Lang.
1. Использование System.nanoTime() метод
Мы можем использовать System.nanoTime() для измерения прошедшего времени с точностью до наносекунды. Он возвращает текущее значение источника времени с высоким разрешением работающей JVM в наносекундах.
Значение, возвращаемое этим методом, само по себе не имеет значения, но оно может стать значимым при вычислении разницы между двумя такими значениями.
import java . util . concurrent . TimeUnit ;
// Программа для измерения прошедшего времени на Java
class Main
public static void main ( String [ ] args ) throws InterruptedException
long startTime = System . nanoTime ( ) ;
/* … Измеряемый код начинается … */
// спать 5 секунд
TimeUnit . SECONDS . sleep ( 5 ) ;
/* … Измеряемый код заканчивается … */
long endTime = System . nanoTime ( ) ;
// получаем разницу между двумя значениями нано-времени
long timeElapsed = endTime — startTime ;
System . out . println ( «Execution time in nanoseconds: » + timeElapsed ) ;
System . out . println ( «Execution time in milliseconds: » + timeElapsed / 1000000 ) ;
Выход (может варьироваться):
Execution time in nanoseconds : 5000372657
Execution time in milliseconds: 5000
2. Использование System.currentTimeMillis() метод
Java System класс также предоставляет статический метод currentTimeMillis() который возвращает разницу между текущим временем и полуночью 1 января 1970 года по всемирному координированному времени в миллисекундах.
Идеально, currentTimeMillis() следует использовать для измерения времени настенных часов, и nanoTime() должен измерять прошедшее время программы. Если прошедшее время измеряется с помощью System.currentTimeMillis() , результаты могут быть неточными.
Основы API Time для Java
Во многих языках программирования работа с датой и временем — непростая задача. Но, начиная с Java 8, JDK предоставляет новый API Time, полностью меняющий подход к концепциям, которые относятся к времени.
Примечания. Хотя JSR 310 был представлен в Java 8, для большей удобочитаемости в приведенных примерах кода задействована такая функция Java 10, как вывод типа локальной переменной. Однако сами примеры кода совместимы с Java 8. В части примеров, содержащих // => , будет показан вывод toString() предыдущей строки/переменной.
До JSR310
До появления нового API в JDK было лишь несколько классов для обработки даты и времени.
Вот наиболее известные из них.
- java.util.Date — конкретный момент времени с точностью до миллисекунды, например 1 января 1970 года 00:00:00 по Гринвичу.
- java.util.Calendar — мостик между моментом времени и параметрами календаря, например месяц, год, день и т. д.
- java.util.TimeZone отвечает за смещение часовых поясов и обработку летнего времени (DST).
- java.text.DateFormat — форматирование и парсинг.
На первый взгляд эти четыре варианта охватывают наиболее распространенные сценарии. Но действительно ли они способны справиться со всеми деликатными особенностями даты и времени?
Миллисекунды
Поскольку java.util.Date базируется на миллисекундах, мы склонны думать о дате и времени как о сумме миллисекунд.
static long MILLIS_PER_MINUTE = 1_000L * 60L; // 60_000L
static long MILLIS_PER_HOUR = MILLIS_PER_MINUTE * 60L; // 3_600_000L
static long MILLIS_PER_DAY = MILLIS_PER_HOUR * 24L; // 86_400_000L
Использование миллисекунд может показаться интуитивно понятным, но в конечном итоге приводит к ошибкам.
Работать со временем сложно из-за интуитивных предположений о дате и времени, которые не соответствуют действительности. Дейв ДеЛонг ведет большой список таких представлений с краткими объяснениями. Вот несколько таких неверных предположений.
- Дни длятся 86 400 секунд.
- Полночь бывает каждый день.
- Границы часовых поясов всегда проходят по ровным часам.
Проблема с граничными случаями в том, что мы часто не осознаем их существования, пока не столкнемся с ними. Если наш код ломается только в високосные годы, он может нормально работать до четырех лет.
Не все — идеальный момент во времени
Date представляет один момент времени с точностью до миллисекунды. Но как насчет более широких единиц?
В какой день начинается январь 2021 года? Во сколько наступает 6 января?
Нам нужно представлять различные концепции даты и времени, помимо одной точки.
- Даты без указания времени: 30 декабря 2020 года.
- Время без дат: 12:24.
- Месяц и годы: декабрь 2020 года.
- Годы: 2020 год.
- Сроки: 7 дней.
- Различные календарные системы: японский календарь.
Эти концепции приходилось реализовывать самостоятельно с помощью контрактов кода, например представлять даты без указания времени в виде java.util.Date со временем полночь. Из-за таких контрактов снижается гибкость данных, и они легко ломаются. Эти крайние случаи и соображения могут легко привести ко многим ошибкам, которые не сразу становятся очевидными.
Joda Time
К счастью, сторонний фреймворк Joda-Time предоставляет лучшую концепцию для работы с датами и временем, благодаря чему он стал стандартной библиотекой до Java 8. Однако, начиная с Java 8, на его основе был разработан новый API Time.
API Time Java (JSR 310)
Для устранения ранее упомянутых недостатков понадобился совершенно новый API. Он был разработан с нуля при участии автора Joda-Time Стивена Коулборна, который возглавлял работу. Результатом стало полное и всестороннее дополнение к JDK. Но чем этот API настолько лучше предшественника?
Цели проектирования
Новый API разрабатывался с учетом нескольких основных принципов.
Неизменяемость. Каждый тип должен быть по возможности неизменяемым. Преимущества неизменяемости хорошо известны: потокобезопасность, снижение числа ошибок из-за отсутствия состояний и лучшая совместимость со сборщиком мусора.
Гибкость API. Гибкий код — это понятный код, с которым легче работать.
Ясность, очевидность, ожидаемый результат. Каждый метод должен быть четко определен и понятен. Управляемый доменом дизайн с согласованными префиксами имен методов повышает ясность и читаемость.
Расширяемость. ISO 8601 — наиболее распространенная и основная для нового API календарная система. Однако нужна возможность пользоваться и другими календарями, которые могли бы предоставлять разработчики приложений, а не только сам JDK.
Локальные типы
Новый пакет java.time.* содержит много различных типов, каждый из которых предназначен для определенной цели. Сначала изучим типы Local , которые отделены от концепции часовых поясов.
java.time.LocalDate
В соответствии с названием, этот тип представляет дату без часового пояса: только день, месяц и год.
var date = LocalDate.of(2021, 1, 1);// => 2021-01-01
java.time.LocalTime
Это время без даты и часового пояса. Применяется стандартное определение времени: время внутри суток, в 24-часовом формате, начиная с полуночи.
LocalTime хранит часы, минуты, секунды и наносекунды. Хотя данный тип поддерживает точность вплоть до наносекунд, имейте в виду, что фактическая точность зависит от реализации JVM/JDK.
var now = LocalTime.now();
// => 12:45:38.896793
var time = LocalTime.of(12, 45);
// => 12:45
java.util.LocalDateTime
Это комбинация LocalTime и LocalDate .
var dt = LocalDateTime.of(2021, 1, 1, 12, 45);// => 2021-01-01T12:45
Есть возможность легко декомпозировать на составляющие:
var dt = LocalDateTime.of(2021, 1, 1, 12, 45);
// => 2021-01-01T12:45
var date = dt.toLocalDate();
// => 2021-01-01
var time = dt.toLocalTime();
// => 12:45
Часовые пояса и смещения
Часовые пояса и их смещения — проклятие всех, кто работает со временем. При работе с ними можно допустить много ошибок (что обычно и происходит).
Чтобы это исправить, API Time разделяет ответственность на несколько классов.
- ZoneOffset — смещение от времени в UTC/GMT, от +14:00 до -12:00.
- ZoneRules — правила изменения смещения для одного часового пояса (например, летнее время, исторические изменения).
- ZoneId — идентификатор часового пояса, например Европа/Берлин.
Доступны два различных типа часовых поясов.
- ZonedDateTime — привязка к определенному ZoneId .
- OffsetDateTime / OffsetTime — дата/время со смещением, но не привязанные к определенному часовому поясу.
java.time.OffsetDateTime / java.time.OffsetTime
OffsetDateTime — это упрощенная версия ZonedDateTime без привязки к конкретному часовому поясу, определенная только смещением. Она больше подходит для форматов обмена, таких как сохранение в базах данных или JSON/XML.
var dt = LocalDateTime.of(2021, 1, 1, 12, 45);
// => 2021-01-01T12:45
var offset = ZoneOffset.of("+02:00");
// => +02:00
var odt = OffsetDateTime.of(dt, offset);
// => 2021-01-01T12:45+02:00
java.time.ZonedDateTime
Смещения часто бывает достаточно, но иногда нужно обрабатывать данные, относящиеся к конкретному часовому поясу. Для таких случаев существует ZonedDateTime .
var dt = LocalDateTime.of(2021, 1, 1, 12, 45);
// => 2021-01-01T12:45
var zoneId = ZoneId.of("Europe/Berlin");
// => Europe/Berlin
var zdt = ZonedDateTime.of(dt, zoneId);
// => 2021-01-01T12:45+01:00[Europe/Berlin]
Другие типы даты и времени
Помимо типов даты, времени и даты/времени, новый API содержит специальные классы и для других концепций.
java.time.Instant
Instant — ближайший доступный эквивалент java.util.Date . Это классическая временная метка по отношению к эпохе. По умолчанию эпоха начинается с метки времени Unix “0” (1970–01–01T00:00:00Z, полночь в начале 1 января 1970 UTC).
var instant = Instant.ofEpochSecond(1609505123);// => 2021-01-01T12:45:23Z
Этот тип можно преобразовать в другие, если предоставить недостающую информацию. Например, чтобы создать LocalDateTime , нужно указать соответствующий ZoneId . В таком случае можно будет применить правила, такие как летнее время и смещение.
var instant = Instant.ofEpochSecond(1609505123);
// => 2021-01-01T12:45:23Z
var zoneId = ZoneId.of("Europe/Berlin");
// => Europe/Berlin
var dt = LocalDateTime.ofInstant(instant, zoneId);
// 2021-01-01T13:45:23
java.time.Duration
Duration представляет собой промежуток, основанный на времени (часы, минуты, секунды, наносекунды). Его можно создать либо напрямую, либо вывести в качестве разности между другими типами:
var sixHours = Duration.ofHours(6);
// => PT6H
var lhs = LocalDateTime.of(2020, 12, 24, 15, 22, 23);
var rhs = LocalDateTime.of(2021, 1, 1, 12, 45, 18);
var diff = Duration.between(lhs, rhs);
// => PT189H22M55S
java.time.Period
Period — двойник Duration , только не на основе промежутка времени, а на основе даты (года, месяца, дня).
var threeQuarters = Period.ofMonths(9);
// => P9M
var lhs = LocalDate.of(2020, 7, 12);
var rhs = LocalDate.of(2021, 1, 1);
var diff = Period.between(lhs, rhs);
// => P5M20D
java.time.Year
Год по календарю ISO.
var jan2021 = YearMonth.of(YearMonth.of(2021, Month.JANUARY));// => 2021-01
Имейте в виду: соответствие между григорианским и юлианским календарями есть только для недавних лет. Например, некоторые области России перешли на современный григорианский календарь только в 1920 году. Кроме того, многочисленные календарные реформы могут дополнительно усложнить расчеты с использованием исторических дат.
java.time.YearMonth
Тип даты без указания дня, к примеру январь 2021 года.
var jan2021 = YearMonth.of(YearMonth.of(2021, Month.JANUARY));// => 2021-01
java.time.MonthDay
Указание даты без года, например 6 января.
var threeKingsDay = MonthDay.of(Month.JANUARY, 6);// --01-06
Строка вывода может показаться странной, но подобный вид точно так же определен в стандарте ISO 8601:2000. Однако обновленный стандарт ISO 8601:2004 запрещает пропускать год, если присутствует месяц.
Перечисления Month / DayOfWeek
Еще один источник множества багов — разовые ошибки, связанные с месяцами и днями недели.
- Январь представлен цифрой 1 или цифрой 0?
- А декабрь — 11 или 12?
- Когда начинается неделя? В воскресенье или в понедельник?
- Какими значениями представлены эти дни?
Поскольку API Java Time основан на стандарте ISO 8601, неделя всегда начинается в понедельник. Чтобы сохранять последовательность, для понедельника и января используются значения 1.
Для большего удобства представлены два перечисления, которые в большинстве методов взаимозаменяемы с числовыми значениями.
var january2021 = YearMonth.of(2021, Month.JANUARY);
var wednesday = LocalDateTime.now().with(DayOfWeek.WEDNESDAY);
- java.time.Month ;
- java.time.DayOfWeek .
Общий дизайн API
Когда в API много новых классов, приходится запоминать большое количество новых методов и концепций. Чтобы облегчить когнитивную нагрузку, API был разработан с согласованными префиксами имен методов и общими концепциями между типами.
Префиксы имен методов
Можно легко изучить различные возможности типа, просто запустив автозаполнение после запуска префикса.
Классический геттер для извлечения частей типа.
var date = LocalDate.of(2021, Month.JANUARY, 1);
var year = date.getYear();
// => 2021
Возвращает копию с некоторым изменением.
var date = LocalDate.of(2021, Month.JANUARY, 1);
date = date.withDayOfMonth(15)
// => 2021-01-15
Возвращает копию с результатом вычисления.
var date = LocalDate.of(2021, Month.JANUARY, 1);
date = date.plusDays(15L);
date = date.minusYears(10L)
// => 2011-01-16
- multipliedBy/dividedBy/negated
Дополнительные вычисления для Duration / Period .
var quarter = Period.ofMonths(3);
var fourQuarters = quarter.multipliedBy(4);
// => P12M
Преобразование между типами.
var dt = LocalDateTime.of(2021, 1, 1, 12, 45);
var date = dt.toLocalDate();
// => 2021-01-01
var time = dt.toLocalTime();
// => 12:45
Возвращает новый объект с изменениями относительно часового пояса.
var date = LocalDate.of(2021, 1, 1);
LocalDateTime dt = date.atTime(12, 45);
// => 2021-01-01T12:45
var zoneId = ZoneId.of("Europe/Berlin");
ZonedDateTime zdt = dt.atZone(zoneId);
// => 2021-01-01T12:45+01:00[Europe/Berlin]
Статические методы фабрики без преобразований.
var date = LocalDate.of(2021, 1, 1);
var zoneId = ZoneId.of("Europe/Berlin");
Статические методы фабрики c преобразованием.
var dt = LocalDateTime.of(2021, 1, 1, 12, 45);
var date = LocalDate.from(dt);
// => 2021-01-01
Имейте в виду, что преобразование работает только для нисходящих операций. К примеру, нельзя создать LocalDateTime из LocalDate :
var date = LocalDate.of(2021, 1, 1);
var dt = LocalDateTime.from(date);
// Выбросит исключение:
// Exception java.time.DateTimeException: Unable to obtain LocalDateTime from TemporalAccessor: 2021-01-01 of type java.time.LocalDate
// | at LocalDateTime.from (LocalDateTime.java:461)
// | at do_it$Aux (#47:1)
// | at (#47:1)
// | Caused by: java.time.DateTimeException: Unable to obtain LocalTime from TemporalAccessor: 2021-01-01 of type java.time.LocalDate
// | at LocalTime.from (LocalTime.java:431)
// | at LocalDateTime.from (LocalDateTime.java:457)
// | .
Статические методы фабрики для обработки текстового ввода.
var date = LocalDate.parse("2021-01-01");
var dt = LocalDateTime.parse("2021-01-01T12:45:32");
Парсинг и форматирование
У всех типов определены методы toString() , основанные на стандарте ISO 8601.
TYPE | FORMAT
----------------|-------------------------------------
LocalDate | uuuu-MM-dd
LocalTime | HH:mm
| HH:mm:ss
| HH:mm:ss.SSS
| HH:mm:ss.SSSSSS
| HH:mm:ss.SSSSSSSSS
LocalDateTime | uuuu-MM-dd'T'HH:mm
| uuuu-MM-dd'T'HH:mm:ss
| uuuu-MM-dd'T'HH:mm:ss.SSS
| uuuu-MM-dd'T'HH:mm:ss.SSSSSS
| uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSS
Year | value without leading zeroes
YearMonth | uuuu-MM
MonthDay | --MM-dd
OffesetDateTime | uuuu-MM-dd'T'HH:mmXXXXX
| uuuu-MM-dd'T'HH:mm:ssXXXXX
| uuuu-MM-dd'T'HH:mm:ss.SSSXXXXX
| uuuu-MM-dd'T'HH:mm:ss.SSSSSSXXXXX
| uuuu-MM-dd'T'HH:mm:ss.SSSSSSSSSXXXXX
OffestTime | HH:mm:ssXXXXX
| HH:mm:ss.SSSXXXXX
| HH:mm:ss.SSSSSSXXXXX
| HH:mm:ss.SSSSSSSSSXXXXX
ZonedDateTime | LocalDateTime + ZoneOffset
ZoneOffset | Z (for UTC)
| +h
| +hh
| +hh:mm
| -hh:mm
| +hhmm
| -hhmm
| +hh:mm:ss
| -hh:mm:ss
| +hhmmss
| -hhmmss
Duration | PT[n]H[n]M[n]S
Period | P[n]Y[n]M[n]D
Формат, созданный через toString() , также доступен в соответствующих методах parse(CharSequence text) , что отлично подходит для методов обмена или нелокализованного отображения.
Для более понятных и локализованных представлений можно воспользоваться классом java.time.format.DateTimeFormatter . Он потокобезопасен, неизменяем и предоставляет гибкий API:
var formatted = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
.withLocale(Locale.GERMAN)
.format(LocalDate.of(2021, 1, 1))
// => Freitag, 1. Januar 2021
Его также можно применить для парсинга, предоставив форматер для метода parse :
var formatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL)
.withLocale(Locale.GERMAN);
var parse = LocalDate.parse("Freitag, 1. Januar 2021", formatter);
// => 2021-01-01
java.time.TemporalAdjuster
С помощью функционального интерфейса TemporalAdjuster можно определить стратегии настройки типов, реализующих Temporal . Таким образом можно получить четко определенные, повторно используемые настройки для новых типов API Time.
API Time предоставляет несколько предопределенных регуляторов через служебный класс TemporalAdjusters . Названия методов (в основном) говорят сами за себя:
dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek)firstDayOfMonth()
firstDayOfNextMonth()
firstDayOfNextYear()
firstDayOfYear()
firstInMonth(DayOfWeek dayOfWeek)lastDayOfMonth()
lastDayOfYear()
lastInMonth(DayOfWeek dayOfWeek)next(DayOfWeek dayOfWeek)
nextOrSame(DayOfWeek dayOfWeek)ofDateAdjuster(UnaryOperator dateBasedAdjuster)previous(DayOfWeek dayOfWeek)
previousOrSame(DayOfWeek dayOfWeek)
Например, в приложении, где есть платная подписка, можно создать настройки для конкретных клиентов, такие как следующая дата выставления счета nextBillingDate(Customer customer) . Код легко читаем, а вся логика расчета даты выставления счета в зависимости от клиента находится в одном месте.
java.time.temporal.TemporalUnit и java.time.temporal.ChronoUnit
Интерфейс TemporalUnit предоставляет способ выражения единиц даты и времени, которые затем можно задействовать в расчетах.
Наиболее востребованные единицы измерения уже доступны в перечислении ChronoUnit , где предоставлены константы для всевозможных видов единиц измерения, таких как MILLENNIA , DAYS , HOURS , MILLIS и т. д.
Помимо конкретных методов расчета, таких как LocalDate plusDays(long daysToAdd) , существуют также неспецифические методы, для которых требуется TemporalUnit , например LocalDate plus(long amountToAdd, TemporalUnit unit) .
Все вычисления API Time по возможности сохраняют рациональность, а также остаются в пределах своей единицы и связанных с ней более крупных единиц. Новые типы — скорее комбинации различных единиц измерения, а не единичные значения.
Это означает, что если мы добавим месяц к LocalDate , это повлияет на месяц (и связанные с ним единицы, такие как год).
var date = LocalDate.of(2021, 1, 31);
// 2021-01-31
date = date.plus(1L, ChronoUnit.MONTHS);
// => 2021-02-28
Разницу также легко подсчитать с помощью ChronoUnit . В случае LocalDate :
var startDate = LocalDate.of(2021, 1, 1);
// 2021-01-01
var endDate = LocalDate.of(2023, 11, 8);
// 2023-11-08
var amount = startDate.until(endDate, ChronoUnit.WEEKS);
// => 148
Само значение перечисления содержит два метода для большей понятности кода вычислений.
- R addTo(R temporal, long amount) ;
- long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) .
Предыдущие примеры также можно выразить через эти методы:
var date = LocalDate.of(2021, 1, 31);
// 2021-01-31
date = ChronoUnit.MONTHS.addTo(date, 1L);
// => 2021-02-28
var startDate = LocalDate.of(2021, 1, 1);
// => 2021-01-01
var endDate = LocalDate.of(2023, 11, 8);
// => 2023-11-08
var amount = ChronoUnit.WEEKS.between(startDate, endDate);
// => 148
В сочетании со static import читаемость повышается еще больше:
import static java.time.temporal.ChronoUnit;
var date = LocalDate.of(2021, 1, 31);
// => 2021-01-31
date = MONTHS.addTo(date, 1L);
// 2021-02-28
var startDate = LocalDate.of(2021, 1, 1);
// => 2021-01-01
var endDate = LocalDate.of(2023, 11, 8);
// => 2023-11-08
var amount = WEEKS.between(startDate, endDate);
// => 148
Константы перечисления также представимы в виде Duration в рамках календаря ISO:
ChronoUnit.HALF_DAYS.getDuration();
// => PT12H
ChronoUnit.WEEKS.getDuration();
// => PT168H
ChronoUnit.CENTURIES.getDuration();
// => PT876582H
Преобразование между типами
Нельзя просто взять и заменить все экземпляры java.util.Date одним из новых типов. Поэтому необходима возможность осуществлять преобразование между ними. Метод java.util.Date#toInstant() обеспечивает связь между старыми и новыми датами.
Instant может быть преобразован в другой тип, если предоставлены соответствующие данные относительно часового пояса:
Соответствующий код вполне понятен:
// Шаг 1: Есть объект даты до-JSR310
var date = new Date();
// Шаг 2: Определить подходящий часовой пояс
var zone = ZoneId.systemDefault();
// Шаг 3: Преобразовать дату в Instant
var instant = date.toInstant();
// SШаг 4: Преобразовать в ZonedDateTime
var zdt = instant.atZone(zone);
Теперь можно воспользоваться еще одним методом to для дальнейших преобразований.
Поддержка Android
В прошлом многие функции Java 8+ не сразу были доступны для Android. Для них требовался либо сторонний фреймворк, либо бэкпорты.
Благодаря плагину Android Gradle 4.0 многие функции Java 8 можно использовать с помощью десахаризацию без необходимости повышать уровень API. Однако потребуются некоторые изменения в build.gradle и новая зависимость:
android defaultConfig // Требуется при установке minSdkVersion на 20 или ниже
multiDexEnabled true
>
compileOptions // Отметка для получения поддержки нового API языка
coreLibraryDesugaringEnabled true
// Установка совместимости с Java 8
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
>
>
dependencies coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.0.9'
>
Список всех API, доступных через десахаризацию, можно найти здесь.
API Time для Java 6 и 7
Хотя Java 8 вышла шесть лет назад, не все могут позволить себе перейти на эту версию. Но не отчаивайтесь. Благодаря бэкпорту у вас остается возможность воспользоваться новым API.
Проект ThreeTen Backport предоставляет совместимый с Java 6 и 7 способ применения новых типов без дополнительных зависимостей. Проект поддерживается главным автором API Time Стивеном Коулборном.
Ссылки
- JSR-310 Date and Time API Guide (JCP.org).
- Package java.time (Oracle).
- ISO 8601 (Wikipedia).
- ThreeTen Backport.
- 3 применения исключений, которые улучшат навыки программирования на Java
- Осваиваем реактивное программирование на Java
- Асинхронность в Java
Как рассчитать разницу времени и даты в Java
В этом уроке мы покажем вам 2 примера для вычисления разницы даты / времени в Java:
- Ручной расчет времени.
- Библиотека времени Йода.
1. Ручной расчет времени
Обращенные Date в миллисекундах (мс) и рассчитайте разницу между двумя датами по следующим правилам:
1000 milliseconds = 1 second 60 seconds = 1 minute 60 minutes = 1 hour 24 hours = 1 day
package com.csharpcoderr.date; import java.text.SimpleDateFormat; import java.util.Date; public class DateDifferentExample < public static void main(String[] args) < String dateStart = "01/14/2012 09:29:58"; String dateStop = "01/15/2012 10:31:48"; // ЧЧ преобразует часы в 24-часовой формат (0-23), расчет дня SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); Date d1 = null; Date d2 = null; try < d1 = format.parse(dateStart); d2 = format.parse(dateStop); // в миллисекундах long diff = d2.getTime() - d1.getTime(); long diffSeconds = diff / 1000 % 60; long diffMinutes = diff / (60 * 1000) % 60; long diffHours = diff / (60 * 60 * 1000) % 24; long diffDays = diff / (24 * 60 * 60 * 1000); System.out.print(diffDays + " days, "); System.out.print(diffHours + " hours, "); System.out.print(diffMinutes + " minutes, "); System.out.print(diffSeconds + " seconds."); >catch (Exception e) < e.printStackTrace(); >> >
1 days, 1 hours, 1 minutes, 50 seconds.
Почему секундам и минутам нужно% 60, а часам% 24?
Если вы измените его на
long diffSeconds = diff / 1000;
1 days, 1 hours, 1 minutes, 90110 seconds.
« 90110 ”- общее количество секунд разницы между date1 а также date2 , это правильно, если вы хотите узнать разницу только в секундах.
ЧИТАТЬ ТАКЖЕ: Java MongoDB: обновить документ
Чтобы отобразить разницу в формате « день, час, минута и секунда », вы должны использовать модуль (% 60), чтобы обрезать оставшиеся секунды ( 90060 ). Понял? Идея применяется также в минутах (% 60) и часах (% 24).
90110 % 60 = 50 seconds (you want this) 90110 - 50 = 90060 seconds (you dont want this)
2. Пример Joda Time
Вот эквивалентный пример, но с использованием времени Joda для расчета различий между двумя датами.
PS Этот пример использует joda-time-2.1.jar
package com.csharpcoderr.date; import java.text.SimpleDateFormat; import java.util.Date; import org.joda.time.DateTime; import org.joda.time.Days; import org.joda.time.Hours; import org.joda.time.Minutes; import org.joda.time.Seconds; public class JodaDateDifferentExample < public static void main(String[] args) < String dateStart = "01/14/2012 09:29:58"; String dateStop = "01/15/2012 10:31:48"; SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss"); Date d1 = null; Date d2 = null; try < d1 = format.parse(dateStart); d2 = format.parse(dateStop); DateTime dt1 = new DateTime(d1); DateTime dt2 = new DateTime(d2); System.out.print(Days.daysBetween(dt1, dt2).getDays() + " days, "); System.out.print(Hours.hoursBetween(dt1, dt2).getHours() % 24 + " hours, "); System.out.print(Minutes.minutesBetween(dt1, dt2).getMinutes() % 60 + " minutes, "); System.out.print(Seconds.secondsBetween(dt1, dt2).getSeconds() % 60 + " seconds."); >catch (Exception e) < e.printStackTrace(); >> >
1 days, 1 hours, 1 minutes, 50 seconds.
Оставьте комментарий ниже, если у вас есть альтернативные способы
Рекомендации
- Второй в Википедии
- Официальный сайт Joda Time