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

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

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


person Marty Pitt    schedule 10.09.2009    source источник
comment
Время Joda: joda-time.sourceforge.net   -  person R. Martinho Fernandes    schedule 10.09.2009
comment
К вашему сведению, неприятные старые классы даты и времени, такие как java.util.Date, java.util.Calendar и java.text.SimpleDateFormat, теперь унаследованы, их заменили java.time классы. Большая часть функций java.time перенесена на Java 6 и Java 7 в ThreeTen-Backport. Дальнейшая адаптация для более ранних версий Android в ThreeTenABP проект. См. Как использовать ThreeTenABP….   -  person Basil Bourque    schedule 23.02.2018
comment
К вашему сведению, проект Joda-Time (упомянутый в другом комментарии ) сейчас находится в режиме обслуживания, и команда советует перейти на java.time классы. См. Руководство Oracle.   -  person Basil Bourque    schedule 23.02.2018


Ответы (13)


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

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

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

person cletus    schedule 10.09.2009
comment
К вашему сведению, ужасно неприятные старые классы даты и времени, такие как java.util.Date, java.util.Calendar, и java.text.SimpleDateFormat теперь являются устаревшими и заменены java.time классы, встроенные в Java 8 и новее . См. Руководство от Oracle. - person Basil Bourque; 19.10.2018

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

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

person dmeister    schedule 10.09.2009
comment
Я поддерживаю предложение использовать время йоды. Его проще использовать и понимать, и он предлагает гораздо больше возможностей, которые вы можете использовать. - person Jeroen van Bergen; 10.09.2009
comment
Для обсуждения того, следует ли использовать Joda Time или придерживаться стандартных классов JDK, см. stackoverflow.com/questions/589870 / - person Jonik; 10.09.2009
comment
Как с этим сосуществуют другие фреймворки? Поддерживается ли он из коробки или вам нужно написать дополнительные конвертеры? - person IAdapter; 10.09.2009
comment
Я не знаю, заслуживает ли он отрицательных отзывов, но он не отвечает на вопрос. Может быть лучше в качестве комментария. - person IcedDante; 31.12.2012
comment
Потому что вопрос касался использования даты и календаря без использования сторонней библиотеки, которая добавляет к проекту риск зависимости от одного поставщика. - person Archimedes Trajano; 15.11.2013
comment
К вашему сведению, проект Joda-Time теперь находится в режим обслуживания, советуя перейти на java.time классы. См. Руководство Oracle. - person Basil Bourque; 19.10.2018
comment
Это БЫЛО лучшим способом до появления java.time пакет стал доступен с Java 8. - person DaBlick; 16.11.2018

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

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

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

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

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

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

person oxbow_lakes    schedule 10.09.2009
comment
Есть ли временные рамки для JSR310? Это должно было быть в Java 7, но я считаю, что сейчас это не так. - person Brian Agnew; 10.09.2009
comment
@Brian - в этом списке рассылки определенно ничего не слышно! - person oxbow_lakes; 10.09.2009
comment
Просто проверяю, он стал Неактивным, что означает, что они не публиковали черновик вехи за 18 месяцев :-( - person Brian Agnew; 10.09.2009
comment
Самый последний комментарий в списке рассылки от Стивена, июль, так что проект, вероятно, еще не завершен. - person oxbow_lakes; 10.09.2009
comment
Согласовано. Если вы знаете, как безопасно использовать Date как неизменяемый объект и Calendar для управления датами, большинство людей должно быть в безопасности. Будьте осторожны при использовании SimpleDateFormat в многопоточном коде. - person cwash; 23.11.2010
comment
Мне нравится оптимизм (в конце 2009 года), лежащий в основе идеи о том, что Joda скоро будет [заменен] API дат JSR-310. - person duelin markers; 08.08.2013
comment
JSR-310 был выпущен как часть Java 8. - person miguel; 10.11.2015
comment
... и я бы сказал, что это не слишком сложно по сравнению с комбинациями Joda-Time и даже Calendar / Date. Я бы сказал, что как только вы поймете теорию, лежащую в основе даты / времени в компьютерах и как они рассчитываются (что, я считаю, является самой большой основной проблемой с датами), тогда API станет гораздо более понятным (с несколькими странными гранями, но все же. .). Проблема с Java Date / Calendar заключается в том, что большинство людей (включая меня, когда я впервые начал их использовать) неправильно понимают, как работают даты и как они рассчитываются. - person Martin Marconcini; 15.05.2020

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

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

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

person KLE    schedule 10.09.2009
comment
Я так понимаю, вы говорите о неизменном java.lang.Long - person pjp; 10.09.2009

tl;dr

посоветуйте текущую "передовую практику" в отношении Date и Calendar

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

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

  • На мгновение в UTC используйте _ 5_
    (современный эквивалент Date)
  • На мгновение в определенном часовом поясе используйте _ 7_
    (современный эквивалент GregorianCalendar)
  • На мгновение в конкретном offset-from-UTC используйте _ 9_
    (нет эквивалента в устаревших классах)
  • Для даты и времени (не момента) с неизвестным часовым поясом или смещением используйте _ 10_
    (нет эквивалента в устаревших классах)

Таблица всех типов даты и времени в Java, как современных, так и устаревших

Подробности

Ответ Ортомалы Локни прав, предлагая использовать современный 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 < / a>), чтобы получить ZonedDateTime.

Часовой пояс

Укажите правильное название часового пояса в формате continent/region, например _ 21_, _ 22_ или 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. Найдите Stack Overflow для более подробного обсуждения.

Струны

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

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


О java.time

java.time framework встроена в Java 8 и новее. Эти классы заменяют неудобные старые устаревшие классы даты и времени, такие как _ 36_, _ 37_, & _ 38_.

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

Чтобы узнать больше, см. Руководство по Oracle . И поищите в Stack Overflow множество примеров и объяснений. Спецификация - JSR 310.

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

Где взять классы java.time?

  • Java SE 8, Java SE 9, and later
    • Built-in.
    • Часть стандартного Java API со встроенной реализацией.
    • В Java 9 добавлены некоторые незначительные функции и исправления.
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • Для более ранних версий Android проект ThreeTenABP адаптируется к < em> ThreeTen-Backport (упомянутый выше). См. Как использовать ThreeTenABP….

Таблица библиотеки java.time для использования с какой версией Java или Android

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

person Basil Bourque    schedule 28.02.2017
comment
Спасибо за подробное объяснение. Я новичок в Java и начну использовать java.time. - person raphael75; 18.12.2020

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

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

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

И возвращаясь к аналогии с 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);
person Archimedes Trajano    schedule 15.06.2010
comment
Да, неизменяемые объекты имеют смысл для работы с датой и временем. Классы java.time, которые вытеснили _1 _ / _ 2_, используют шаблон неизменяемых объектов. - person Basil Bourque; 19.10.2018
comment
Это может быть правдой, но не в 2010 году. - person Archimedes Trajano; 20.10.2018
comment
да. Но эту страницу читают тысячи людей сейчас, а пока более 150 000. Мой комментарий - это примечание к ним, а не критика в вашу сторону. - person Basil Bourque; 20.10.2018
comment
Я знаю, поэтому я проголосовал за другой ответ. Тем не менее, есть люди, которым нужно страдать со старыми JDK, которым тоже нужен ответ, приведенный выше. - person Archimedes Trajano; 20.10.2018
comment
Собственно, для Java 6 и 7 у нас есть проект ThreeTen-Backport. Это обеспечивает большую часть функциональности java.time практически с тем же API. Так что нет необходимости когда-либо использовать эти ужасные устаревшие классы даты и времени. - person Basil Bourque; 20.10.2018

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

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

person Andrzej Doyle    schedule 10.09.2009
comment
Да, неизменяемые объекты имеют смысл для работы с датой и временем. Классы java.time, которые вытеснили _1 _ / _ 2_, используют шаблон неизменяемых объектов. В частности, Instant заменяет java.util.Date, а ZonedDateTime заменяет _6 _ / _ 7_. - person Basil Bourque; 19.10.2018

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

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

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

    Date date = new Date();
    ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());
person Ortomala Lokni    schedule 15.06.2015
comment
Хорошо предложить классы java.time. Но нехорошо предлагать LocalDateTime. Этот класс намеренно теряет любую информацию о смещении от UTC и часовом поясе. Таким образом, этот класс не эквивалентен, поскольку Date находится в формате UTC, а Calendar имеет назначенный часовой пояс. См. мой ответ и отличную диаграмму по другому вопросу, Преобразовать java.util.Date в какой тип« java.time »?. - person Basil Bourque; 28.02.2017

Я всегда выступаю за 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

person Brian Agnew    schedule 10.09.2009
comment
В последний раз, когда я смотрел, JODA и JSR-310 выглядели очень по-разному, даже если они оба написаны Стивеном Колебурном. Тем не менее, JODA познакомит вас со сложностью проблем с датой и временем, которые также решает JSR-310. - person oxbow_lakes; 10.09.2009
comment
Потому что вопрос касался использования даты и календаря без использования сторонней библиотеки, которая добавляет к проекту риск зависимости от одного поставщика. - person Archimedes Trajano; 15.11.2013
comment
Я считаю, что лучше всего просто не использовать эти классы. - person Brian Agnew; 21.11.2013
comment
Учитывая известные проблемы с классами java.util.Date и Calendar, предложение Joda-Time (или JSR 310) кажется мне уместным и ответственным. Мы не говорим о вкусе или эстетическом стиле. Если кто-то спросит, следует ли им взять красную машину или серебряную, и я знал, что у красной машины спустило колесо, а у серебряной машины - сломанный радиатор, выбрать машину или предложить вызвать такси? В настоящее время ответ на этот вопрос должен казаться очевидным, поскольку даже Sun / Oracle решили оставить этих юнкеров и купить новую машину: JSR 310: API даты и времени. - person Basil Bourque; 09.01.2014
comment
Обновление ответа: JSR 310 является частью Java 8 в java.time. * классы. - person Basil Bourque; 09.01.2014
comment
К вашему сведению, проект Joda-Time теперь находится в режим обслуживания, советуя перейти на java.time классы. См. Руководство Oracle. - person Basil Bourque; 19.10.2018
comment
Согласовано. Я исправляю ответ соответствующим образом - person Brian Agnew; 20.10.2018

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

person Silviu Burcea    schedule 23.05.2014

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

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

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

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

person user2835562    schedule 01.10.2013
comment
Тот факт, что вы можете сохранить один и тот же момент времени, но сообщать разные часы / минуты / день / неделю / год / foo на основе разных календарных систем, является сильной стороной, а не недостатком. Он отражает (сложную) реальность. - person ThrawnCA; 30.10.2015
comment
Действительно, Date был переработан; заменен классом java.time.Instant. И _3 _ / _ 4_ был заменен классом java.time.ZonedDateTime. - person Basil Bourque; 19.10.2018

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

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

person xxxvodnikxxx    schedule 26.05.2015

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

person Brian Nelson    schedule 02.07.2018
comment
К вашему сведению, проблемные классы Calendar & Date были вытеснены несколько лет назад классами java.time. Нет необходимости использовать Date или Calendar. И Locale не имеет ничего общего со значением объектов даты и времени. Locale используется только для указания человеческого языка и культурных норм, которые будут использоваться при локализации при создании текста для представления значения объекта даты и времени. - person Basil Bourque; 03.07.2018