Дата Java против Календаря

Может ли кто-нибудь проконсультироваться с текущей "лучшей практикой" вокруг типов Date и Calendar.

При написании нового кода лучше всегда поддерживать Calendar над Date, или существуют ли ситуации, когда Date является более подходящим типом данных?

Ответ 1

Дата - это более простой класс и, главным образом, для соображений обратной совместимости. Если вам нужно установить конкретные даты или выполнить арифметику даты, используйте Календарь. Календари также обрабатывают локализацию. С тех пор предыдущие функции манипулирования датой даты были устаревшими.

Лично я склонен использовать либо время в миллисекундах как длинный (или длинный, если нужно), либо календарь, когда есть выбор.

Обе даты и календарь изменяются, что, как правило, представляет проблемы при использовании либо в API.

Ответ 2

Лучший способ для нового кода (если ваша политика разрешает сторонний код) - использовать Joda Time library.

Оба, Date и Calendar, имеют так много проблем дизайна, которые не являются хорошими решениями для нового кода.

Ответ 3

  • Date и Calendar - это действительно одно и то же фундаментальное понятие (оба представляют собой момент времени и являются обертками вокруг базового значения long).

  • Можно утверждать, что Calendar на самом деле еще более сломан, чем Date, поскольку он предлагает конкретные факты о таких вещах, как день недели и время суток, тогда как если вы измените его свойство timeZone, бетон превратится в blancmange! По этой причине ни один из объектов не является действительно полезным как хранилище год-месяц-день или время суток.

  • Используйте Calendar только как калькулятор, который при заданных объектах Date и timeZone будет выполнять вычисления для вас. Избегайте его использования для ввода свойств в приложении.

  • Используйте SimpleDateFormat вместе с timeZone и Date для создания строк отображения.

  • Если вы чувствуете приключенческое использование Joda-Time, хотя он излишне усложняется IMHO и в любом случае вскоре будет заменен API-интерфейсом даты JSR-310.

  • Я уже ответил, что вам не сложно катить собственный класс YearMonthDay, который использует Calendar под капотом для расчета даты. Я был отклонен для предложения, но я по-прежнему считаю, что он действителен, потому что Joda-TimeJSR-310) действительно слишком сложны для большинства случаев использования.

Ответ 4

Дата лучше всего подходит для хранения объекта даты. Это сохранившийся, сериализованный...

Календарь лучше всего подходит для управления датами.

Примечание. Мы также иногда предпочитаем java.lang.Long over Date, потому что Date изменена и, следовательно, не является потокобезопасной. В объекте Date используйте setTime() и getTime() для переключения между ними. Например, постоянная дата в приложении (примеры: нуль 1970/01/01 или аппликативный END_OF_TIME, который вы установили в 2099/12/31, которые очень полезны для замены нулевых значений как времени начала и окончания, особенно когда вы сохраняете их в базе данных, так как SQL настолько странен с нулями).

Ответ 5

Обычно я использую Date, если это возможно. Хотя он изменен, мутаторы фактически устарели. В конце концов он в основном обертывает длинный, который будет представлять дату/время. И наоборот, я бы использовал календари, если мне нужно манипулировать значениями.

Вы можете думать об этом так: вы используете StringBuffer только тогда, когда вам нужно иметь Strings, с которыми вы можете легко манипулировать, а затем преобразовывать их в Strings, используя метод toString(). Точно так же я использую только календарь, если мне нужно манипулировать временными данными.

Для лучшей практики я стараюсь использовать неизменяемые объекты как можно больше за пределами модели домена. Это значительно снижает шансы на какие-либо побочные эффекты, и это делается для вас компилятором, а не для теста JUnit. Вы используете этот метод, создав в своем классе частные конечные.

И вернемся к аналогии StringBuffer. Вот какой код, который показывает вам, как конвертировать между календарем и датой

String s = "someString"; // immutable string
StringBuffer buf = new StringBuffer(s); // mutable "string" via StringBuffer
buf.append("x");
assertEquals("someStringx", buf.toString()); // convert to immutable String

// immutable date with hard coded format.  If you are hard
// coding the format, best practice is to hard code the locale
// of the format string, otherwise people in some parts of Europe
// are going to be mad at you.
Date date =     new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2001-01-02");

// Convert Date to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);

// mutate the value
cal.add(Calendar.YEAR, 1);

// convert back to Date
Date newDate = cal.getTime();

// 
assertEquals(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2002-01-02"), newDate);

Ответ 6

Date следует использовать как непреложные моменты времени; Calendar являются изменяемыми и могут быть переданы и изменены, если вам нужно сотрудничать с другими классами, чтобы получить окончательную дату. Рассмотрим их аналогично String и StringBuilder, и вы поймете, как я считаю, что они должны использоваться.

(И да, я знаю, что дата на самом деле не является технически неизменной, но намерение состоит в том, что она не должна быть изменчивой, и если ничто не вызывает устаревшие методы, то это так.)

Ответ 7

ТЛ; др

посоветуйте текущую "лучшую практику" вокруг Date и Calendar

лучше ли всегда отдавать предпочтение Calendar над Date

Избегайте этих старых классов полностью. Вместо этого используйте классы java.time.

  • На мгновение в UTC используйте Instant
    (современный эквивалент Date)
  • На мгновение в конкретном часовом поясе используйте ZonedDateTime
    (современный эквивалент GregorianCalendar)
  • На мгновение в определенном смещении от UTC используйте OffsetDateTime
    (нет эквивалента в старых классах)
  • Для даты-времени (не момента) с неизвестным часовым поясом или смещением используйте LocalDateTime
    (нет эквивалента в старых классах)

подробности

Ответ от Ortomala Lokni справедливо предложить использовать современные классы java.time, а не старые классные классы даты и времени (Date, Calendar и т.д.). Но в этом ответе предлагается неправильный класс в качестве эквивалента (см. Мой комментарий к этому ответу).

Использование java.time

Классы java.time - это значительное улучшение по сравнению с традиционными классами даты и времени, разница между днем и ночью. Старые классы плохо спроектированы, запутаны и хлопотны. Вы должны избегать старых классов, когда это возможно. Но когда вам нужно преобразовать в/из старого/нового, вы можете сделать это, вызвав новые методы add для старых классов.

Для получения дополнительной информации о преобразовании см. Мой ответ и изящную диаграмму в другой вопрос. Преобразовать java.util.Date в тип "java.time"? ,

Поиск дает сотни примеров вопросов и ответов по использованию java.time. Но вот краткий обзор.

Instant

Получить текущий момент с Instant. Класс Instant представляет момент на временной шкале в UTC с разрешением наносекунд (до девяти (9) цифр десятичной дроби).

Instant instant = Instant.now();

ZonedDateTime

Чтобы увидеть тот же самый момент одновременно через линзу часов в некоторых регионах, примените часовой пояс ( ZoneId), чтобы получить ZonedDateTime.

Часовой пояс

Укажите правильное имя часового пояса в формате continent/region, например, America/Montreal, Africa/Casablanca или Pacific/Auckland. Никогда не используйте 3-4-буквенное сокращение, такое как EST или IST поскольку они не являются истинными часовыми поясами, не стандартизированы и даже не уникальны (!).

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone();

офсет

Часовой пояс - это история изменений региона в его смещении от UTC. Но иногда вам дают только смещение без полной зоны. В этом случае используйте класс OffsetDateTime.

ZoneOffset offset = ZoneOffset.parse( "+05:30" );
OffsetDateTime odt = instant.atOffset( offset );

Использование часового пояса предпочтительнее, чем использование простого смещения.

LocalDateTime

"Локальный" в классах Local… означает любой населенный пункт, а не конкретный населенный пункт. Так что название может быть нелогичным.

LocalDateTime, LocalDate и LocalTime намеренно не имеют никакой информации о смещении или часовом поясе. Таким образом, они не представляют фактические моменты, они не являются точками на временной шкале. В случае сомнений или путаницы используйте ZonedDateTime а не LocalDateTime. Поиск для гораздо большего обсуждения.

Струны

Не путайте объекты даты и времени со строками, представляющими их значение. Вы можете проанализировать строку, чтобы получить объект даты и времени, и вы можете сгенерировать строку из объекта даты и времени. Но строка никогда не является самой датой-временем.

Узнайте о стандартных форматах ISO 8601, используемых по умолчанию в классах java.time.


О java.time

Инфраструктура java.time встроена в Java 8 и более поздние версии. Эти классы вытеснять неприятные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, и SimpleDateFormat.

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

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

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

Где взять классы 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

Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти некоторые полезные классы, такие как Interval, YearWeek, YearQuarter и другие.

Ответ 8

С Java 8 следует использовать новый пакет java.time.

Объекты неизменяемы, учитываются часовые пояса и дневное свечение.

Вы можете создать объект ZonedDateTime из старого java.util.Date, например:

    Date date = new Date();
    ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());

Ответ 9

Я всегда защищаю Joda-Time. Вот почему.

  1. API является последовательным и интуитивно понятным. В отличие от API java.util.Date/Calendar
  2. он не страдает от проблем с многопоточностью, в отличие от java.text.SimpleDateFormat и т.д. (я видел множество клиентских проблем, связанных с непониманием того, что стандартное форматирование даты/времени не является поточно-ориентированным)
  3. это основа новых API даты/времени Java (JSR310, запланированных для Java 8. Поэтому вы будете использовать API, которые станут основными API Java.

РЕДАКТИРОВАТЬ: классы даты/времени Java, представленные в Java 8, теперь являются предпочтительным решением, если вы можете перейти на Java 8

Ответ 10

Немного поздно на вечеринке, но Java имеет новый API Time Time в JDK 8. Возможно, вам захочется обновить версию JDK и принять стандарт. Нет более грязной даты/календаря, больше не сторонних банках.

Ответ 11

Дата должна быть переработана. Вместо того, чтобы быть длинным интергером, он должен содержать год, месяц, дату, час, минуту, секунду, как отдельные поля. Возможно, было бы неплохо сохранить календарь и часовой пояс, с которыми связана эта дата.

В нашем естественном разговоре, если вы назначили встречу на 1 ноября 2013 года в 13:00 по нью-йоркскому времени, это DateTime. Это не календарь. Таким образом, мы должны иметь возможность разговаривать так же и на Java.

Когда дата хранится как длинное целое число (с миллионом секунд с 1 января 1970 года или что-то еще), вычисление его текущей даты зависит от календаря. Различные календари дадут другую дату. Это связано с перспективой дать абсолютное время (например, 1 триллион секунд после Большого Взрыва). Но часто нам также нужен удобный способ общения, например, объект, охватывающий год, месяц и т.д.

Интересно, есть ли новые усовершенствования в Java, чтобы согласовать эти две цели. Возможно, мое знание java слишком старое.

Ответ 12

Btw "дата" обычно помечена как "устаревшая/устаревшая" (я точно не знаю почему) - что-то о ней написано Java: Почему устаревший конструктор устарел, и что я использую вместо этого?

Похоже, что проблема только с конструктором - через new Date (int year, int month, int day), рекомендуется использовать Calendar и устанавливать параметры отдельно.. ( Календарь cal = Calendar.getInstance(); )

Ответ 13

Я использую Календарь, когда мне нужны какие-то конкретные операции над датами, такие как перемещение во времени, но Дата мне кажется полезной, когда вам нужно отформатировать дату, чтобы адаптировать свои потребности, недавно я обнаружил, что в Locale есть много полезных операций и методов. Я использую Locale прямо сейчас!

Ответ 14

Отстранить от восторга и правильно понять, сэр, зачем смеяться. В моем вступлении ужасный Маргарет подходит он быстро следовал. Действительно извините тщеславие или г-н любителей на. По предложению масштабируем вещи. Румяна, извини, не видать. Пел потерять час, затем он ушел найти.