Java Dates - Какой правильный класс использовать?

Итак, вся Java Date/Calendar/GregorianCalendar - это, безусловно, шутка. Какой правильный класс Date использовать?

Изменить: Создание SDK для сторонних разработчиков на Android, где приложение должно предоставить дату

Подробнее Изменить: Вещи, которые делают это, очевидно, шуткой:

  • 99% даты устарело
  • Дата Год смещен с 1900 г.
  • Дата Месяц индексируется с нулевым значением, в то время как день индексируется
  • Даты изменяются
  • Вы должны использовать календарь для создания даты...
  • ... кроме того, что вам действительно нужно использовать GregorianCalendar
    • Значит, значительный процент разработчиков хочет использовать другой календарь?
  • Calendar.getTime() возвращает дату
  • Нет даты математики (например, насколько далеки друг от друга две даты в годах)
    • Беседа с миллисекундами с эпохи не считается
  • Вы не можете связать части вместе, чтобы получить выражение (например, дату год назад).
  • Вероятно, больше вещей

Ответы

Ответ 1

Joda-Time. Даже на Android.

Если вы хотите придерживаться классов Java SE, это зависит от того, что вы пытаетесь сделать.

Изменить: вы постоянно меняете свой вопрос. Date и Calendar.

Ответ 2

"Правильный" тип даты полностью зависит от вашего приложения; однако java.util.Calendar обычно принимается за замену java.util.Date, поскольку он обеспечивает большую функциональность (особенно для извлечения отдельных элементов даты, таких как год, месяц и т.д.). На самом деле, Date может быть намного проще использовать для определенных ситуаций (и это тот, который используется Java DateFormat), поэтому это решение суда.

Не сложно конвертировать между ними, поэтому я бы выбрал один и последовательно придерживался его для вашего API. Если бы я выбрал один, я бы использовал Date, потому что это самый простой, ИМХО.

Ответ 3

Избегать устаревших классов времени

Итак, вся Java Date/Calendar/GregorianCalendar - это, безусловно, шутка.

Да, старые классы времени, связанные с самыми ранними версиями Java, - ужасный беспорядок. Плохо спроектированные, неуклюжие попытки улучшения, многие хаки.

Но, честно говоря, эти классы были отважными усилиями в решении удивительно сложной темы, которую вся информационная индустрия игнорировала на протяжении десятилетий. На основе предыдущей работы на Taligent и IBM, авторы этих классов, по крайней мере, предприняли попытку, когда практически все другие языки, платформы и инструменты программирования проходят пропуск с минимальным минимальным уровнем поддержки обработки времени.

К счастью, теперь у нас есть ведущие в отрасли классы java.time(JSR 310), встроенные в Java 8 и более поздние версии. Они были вдохновлены успехом проекта Joda-Time. Действительно, оба усилия были предприняты одним и тем же человеком, Стивен Коулборн.

java.time

Каждый из ваших предметов с пулями исправляется с помощью java.time вместо этого.

  • 99% даты устарело
    Instant заменяет java.util.Date. AFAIK, ничто не устарело в java.time в Java 8 и Java 9.
  • Дата Год смещен с 1900 года. Годы имеют нормальную нумерацию в java.time, 2018 - 2018 год.
  • Дата Месяц индексируется с нулевым индексом, в то время как день индексируется
    Месяцы имеют нормальную нумерацию в java.time, 1-12 за январь-декабрь. Еще лучше, Month enum предоставляет объекты, представляющие каждый месяц года, а не просто целое число. Таким образом, вы получаете достоверные значения тип безопасности и самодокументирующий код.
  • Даты изменяются
    Практически все java.time immutable. Любые вызовы для изменения какого-либо аспекта объекта java.time возвращают новый и отдельный объект. Даже конструкторы скрыты, вместо них используются статические методы factory.
  • Вы должны использовать календарь для создания даты...
    ZonedDateTime заменяет java.util.Calendar.
  • ... кроме того, что вам действительно нужно использовать GregorianCalendar
    ZonedDateTime, вместо java.util.GregorianCalendar. Рамка java.time использует интерфейсы в основном только для внутреннего использования, что позволяет приложениям использовать только конкретные классы. Это было дизайнерское решение, специфичное для потребностей java.time в качестве рамки, и не означает, что вы должны делать то же самое в своих приложениях.
  • Calendar.getTime() возвращает дату
    Просто используйте Instant как основной класс строительного блока в java.time, всегда представляя момент в UTC с разрешением наносекунды. Другие типы, такие как OffsetDateTime и ZonedDateTime, могут конвертировать назад и вперед с помощью Instant.
  • Нет математики Дата (например, насколько далеки друг от друга две даты в годах)
    В классах java.time есть много удобных методов plus…/minus…. Кроме того, java.time предоставляет мощный TemporalAduster реализация, а также позволяет вам писать свои собственные. Также обратите внимание на метод ChronoUnit::between, например ChronoUnit.YEARS.between( thisLocalDate , that LocalDate ).
    • Беседа с миллисекундами с эпохи не считается
      Посмотрите на Instant::toEpochMilli и Instant.ofEpochMilli, если вы должны использовать count-from-epoch, но, конечно, не рекомендуется. Лучше использовать объекты java.time и строки ISO 8601 для представления значений даты и времени.
  • Вы не можете объединять детали вместе, чтобы получить выражение (например, дату год назад)
    Классы java.time определенно предназначены для цепочек вызовов. Пример: LocalDate.now( ZoneId.of( "Europe/Paris" ) ).minusYears( 1 ).getDayOfWeek().getDisplayName( TextStyle.FULL , Locale.FRANCE ) > dimanche. Иногда это подходит, но не сходите с ума - вот мой совет.
  • Вероятно, больше вещей
    Да еще много проблем со старыми классами наследия. Вы найдете java.time, чтобы быть радикальным отходом от старого материала, полностью современным и хорошо продуманным, гигантским улучшением.

Одной из других проблемных областей является обмен значениями даты и времени с базой данных. Обратите внимание, что с драйвером JDBC, совместимым с JDBC 4.2 или позже (JSR 221), вы можете избежать связанных с датой классов java.sql, таких как java.sql.Timestamp. Эти старые классы связаны с трудными старыми классами наследия и больше не нужны.

myPreparedStatement.setObject( … , instant ) ;

... и...

Instant instant = myResultSet.getObject( … , Instant.class ) ;

О java.time

Структура java.time встроена в Java 8 и более поздних версий. Эти классы вытесняют неприятный старый legacy классы даты-времени, такие как java.util.Date, Calendar и SimpleDateFormat.

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

Чтобы узнать больше, см. Учебник Oracle. И поиск Qaru для многих примеров и объяснений. Спецификация JSR 310.

Где получить классы java.time?

  • Java SE 8, Java SE 9, а затем
    • Встроенный.
    • Часть стандартного Java API с объединенной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большая часть функций java.time возвращается на Java 6 и 7 в ThreeTen-Backport.
  • Android
    • Более поздние версии реализаций пакетов Android классов java.time.
    • Для более раннего Android проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше). См. Как использовать ThreeTenABP....