Дата 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-Time (и JSR-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?
Проект 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. Вот почему.
- API является последовательным и интуитивно понятным. В отличие от API java.util.Date/Calendar
- он не страдает от проблем с многопоточностью, в отличие от java.text.SimpleDateFormat и т.д. (я видел множество клиентских проблем, связанных с непониманием того, что стандартное форматирование даты/времени не является поточно-ориентированным)
- это основа новых 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
Отстранить от восторга и правильно понять, сэр, зачем смеяться. В моем вступлении ужасный Маргарет подходит он быстро следовал. Действительно извините тщеславие или г-н любителей на. По предложению масштабируем вещи. Румяна, извини, не видать. Пел потерять час, затем он ушел найти.