Подтвердить что ты не робот

Java: почему устаревший конструктор даты не используется, и что я использую вместо этого?

Я из мира С#, поэтому еще не слишком разбираюсь в Java. Eclipse только что сказал, что Date устарела:

Person p = new Person();
p.setDateOfBirth(new Date(1985, 1, 1));

Зачем? И что (особенно в случаях как выше) должно использоваться вместо этого?

4b9b3361

Ответ 1

Конкретный конструктор Date устарел, и вместо него следует использовать Calendar. JavaDoc for Date описывает, какие конструкторы устарели и как их заменить с помощью Calendar.

Ответ 2

Класс java.util.Date на самом деле не устарел, просто этот конструктор, а также пара других конструкторов/методов устарели. Это было устарело, потому что такое использование не очень хорошо работает с интернационализацией. Вместо этого следует использовать класс Calendar:

Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 1988);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
Date dateRepresentation = cal.getTime();

Взгляните на дату Javadoc:

http://download.oracle.com/javase/6/docs/api/java/util/Date.html

Ответ 3

ТЛ; др

LocalDate.of( 1985 , 1 , 1 )

…или же…

LocalDate.of( 1985 , Month.JANUARY , 1 )

подробности

Классы java.util.Date, java.util.Calendar и java.text.SimpleDateFormat были java.text.SimpleDateFormat слишком быстро при первом запуске и java.text.SimpleDateFormat Java. Классы не были хорошо разработаны или реализованы. Попытки улучшения были предприняты, таким образом, найденные вами амортизации. К сожалению, попытки улучшения в основном провалились. Вам следует вообще избегать этих занятий. Они вытесняются в Java 8 новыми классами.

Проблемы в вашем коде

У java.util.Date есть и дата, и часть времени. Вы проигнорировали часть времени в своем коде. Таким образом, класс Date будет принимать начало дня в соответствии с часовым поясом JVM по умолчанию и применять это время к объекту Date. Таким образом, результаты вашего кода будут различаться в зависимости от того, на каком компьютере он работает или какой часовой пояс установлен. Наверное, не то, что вы хотите.

Если вам нужна только дата без временной части, например, для даты рождения, вы можете не использовать объект Date. Возможно, вы захотите сохранить только строку даты в формате ISO 8601 YYYY-MM-DD. Или используйте объект LocalDate из Joda-Time (см. Ниже).

Joda времени

Первое, чему нужно научиться на Java: избегайте печально известных классов java.util.Date & java.util.Calendar в комплекте с Java.

Как правильно отмечено в ответе user3277382, используйте либо Joda-Time, либо новый пакет java.time. * В Java 8.

Пример кода в Joda-Time 2.3

DateTimeZone timeZoneNorway = DateTimeZone.forID( "Europe/Oslo" );
DateTime birthDateTime_InNorway = new DateTime( 1985, 1, 1, 3, 2, 1, timeZoneNorway );

DateTimeZone timeZoneNewYork = DateTimeZone.forID( "America/New_York" );
DateTime birthDateTime_InNewYork = birthDateTime_InNorway.toDateTime( timeZoneNewYork ); 

DateTime birthDateTime_UtcGmt = birthDateTime_InNorway.toDateTime( DateTimeZone.UTC );

LocalDate birthDate = new LocalDate( 1985, 1, 1 );

Дамп на консоль…

System.out.println( "birthDateTime_InNorway: " + birthDateTime_InNorway );
System.out.println( "birthDateTime_InNewYork: " + birthDateTime_InNewYork );
System.out.println( "birthDateTime_UtcGmt: " + birthDateTime_UtcGmt );
System.out.println( "birthDate: " + birthDate );

Когда беги…

birthDateTime_InNorway: 1985-01-01T03:02:01.000+01:00
birthDateTime_InNewYork: 1984-12-31T21:02:01.000-05:00
birthDateTime_UtcGmt: 1985-01-01T02:02:01.000Z
birthDate: 1985-01-01

java.time

В этом случае код для java.time практически идентичен коду Joda-Time.

Мы получаем часовой пояс ( ZoneId) и ZoneId объект даты и времени, назначенный этому ZonedDateTime поясу ( ZonedDateTime). Затем, используя шаблон " Неизменяемые объекты", мы создаем новые даты и время на основе старых объектов в тот же момент (количество наносекунд с начала эпохи), но с другим часовым поясом. Наконец, мы получаем LocalDate который не имеет ни времени суток, ни часового пояса, хотя обратите внимание, что часовой пояс применяется при определении этой даты (например, новый день наступает раньше в Осло, чем в Нью-Йорке).

ZoneId zoneId_Norway = ZoneId.of( "Europe/Oslo" );
ZonedDateTime zdt_Norway = ZonedDateTime.of( 1985 , 1 , 1 , 3 , 2 , 1 , 0 , zoneId_Norway );

ZoneId zoneId_NewYork = ZonedId.of( "America/New_York" );
ZonedDateTime zdt_NewYork = zdt_Norway.withZoneSameInstant( zoneId_NewYork );

ZonedDateTime zdt_Utc = zdt_Norway.withZoneSameInstant( ZoneOffset.UTC );  // Or, next line is similar.
Instant instant = zdt_Norway.toInstant();  // Instant is always in UTC.

LocalDate localDate_Norway = zdt_Norway.toLocalDate();

О java.time

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

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

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

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

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

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

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

Ответ 4

Одна из причин, по которой конструктор устарела, заключается в том, что значение параметра year не является тем, что вы ожидаете. В javadoc говорится:

Начиная с версии JDK версии 1.1, заменяется на Calendar.set(year + 1900, month, date).

Обратите внимание, что поле year - это количество лет с 1900, поэтому ваш пример кода скорее всего не будет делать то, что вы ожидаете от него. И это точка.

В общем, API Date поддерживает только современный западный календарь, имеет идиосинкратически определенные компоненты и ведет себя непоследовательно, если вы задаете поля.

API Calendar и GregorianCalendar лучше, чем Date, а сторонние API-интерфейсы Joda-времени, как правило, считаются лучшими. В Java 8 они ввели пакеты java.time, и теперь это рекомендуемая альтернатива.

Ответ 5

Я столкнулся с этим вопросом как дубликат нового вопроса, в котором спрашивали, что не устаревший способ получить Date в конкретный год, месяц, и день был.

В ответах здесь показывается использование класса Calendar, и это было верно до тех пор, пока не выйдет Java 8. Но с Java 8 стандартный способ сделать это:

LocalDate localDate = LocalDate.of(1985, 1, 1);

И если вам действительно нужен java.util.Date, вы можете использовать предложения в этом вопросе.

Для получения дополнительной информации ознакомьтесь с API или учебники для Java 8.

Ответ 6

Обратите внимание, что Calendar.getTime() является недетерминированным в том смысле, что часть дня по умолчанию соответствует текущему времени.

Чтобы воспроизвести, попробуйте выполнить следующий код пару раз:

Calendar c = Calendar.getInstance();
c.set(2010, 2, 7); // NB: 2 means March, not February!
System.err.println(c.getTime());

Вывод, например:

Sun Mar 07 10:46:21 CET 2010

Запуск одного и того же кода через пару минут дает:

Sun Mar 07 10:57:51 CET 2010

Итак, в то время как set() заставляет соответствующие поля корректировать значения, он течет системное время для других полей. (Протестировано выше с помощью Sun jdk6 и jdk7)

Ответ 10

Собственно, класс Date имеет такие методы, как getDay, getMonth и getYear, и его конструкторы, но эти методы устарели. Эти методы были частью класса Date, прежде чем разработчики библиотеки поняли, что имеет смысл предоставлять отдельные классы календаря. Когда были введены классы календаря, методы Date были помечены как устаревшие.

У экземпляра класса Date есть состояние, а именно конкретный момент времени. Хотя вам не нужно знать это, когда вы используете класс Date, время представлено числом миллисекунд (положительным или отрицательным) с фиксированной точки, так называемой эпохой, которая равна 00:00:00 UTC, 1 января, 1970.

Класс Date не очень полезен для управления датами. Дизайнеры библиотеки Java считают, что описание даты, такое как "31 декабря 1999 года, 23:59:59", является произвольным соглашением, которым управляет календарь. Это конкретное описание следует за григорианским календарем, который является календарем, используемым в большинстве стран мира. Тот же момент времени будет описан по-разному в иранских солнечных (шамси), китайских или еврейских лунных календарях, не говоря уже о календаре, используемом вашими клиентами с Марса.

Дизайнеры библиотеки решили разделить проблемы сохранения времени и привязки имен к точкам времени. Поэтому стандартная библиотека Java содержит два отдельных класса: класс Date, который представляет собой момент времени, и класс GregorianCalendar, который выражает даты в знакомой календарной нотации. На самом деле класс GregorianCalendar расширяет более общий класс календаря, который описывает свойства календарей в целом. Стандартная библиотека Java также содержит реалии тайского буддийского и японского императорского календаря.

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

if (today.before(birthday))
    System.out.println("Still time to shop for a gift.");

Класс GregorianCalendar имеет гораздо больше методов, чем класс Date. В частности, он имеет несколько полезных конструкторов.

От: Oracle

Ответ 11

Вы можете создать метод так же, как new Date(year,month,date) в своем коде, используя класс Calendar.

private Date getDate(int year,int month,int date){
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.YEAR, year);
    cal.set(Calendar.MONTH, month-1);
    cal.set(Calendar.DAY_OF_MONTH, day);
    return cal.getTime();
}

Он будет работать так же, как устаревший конструктор Date

Ответ 12

new GregorianCalendar(1985, Calendar.JANUARY, 1).getTime();

(путь до Java-8)

Ответ 13

Конструктор Date ожидает годы в формате лет, начиная с 1900 года, начиная с нуля, и устанавливает часы/минуты/секунды/миллисекунды в ноль.

Date result = new Date(year, month, day);

Таким образом, используя замену Календаря (годы с нулями, месяцы с нулями, дни с единицами) для устаревшего конструктора Date, нам нужно что-то вроде:

Calendar calendar = Calendar.getInstance();
calendar.clear(); // Sets hours/minutes/seconds/milliseconds to zero
calendar.set(year + 1900, month, day);
Date result = calendar.getTime();

Или используя Java 1.8 (в котором год начинается с нуля, а месяцы и дни равны единице):

Date result = Date.from(LocalDate.of(year + 1900, month + 1, day).atStartOfDay(ZoneId.systemDefault()).toInstant());

Вот равные версии Date, Calendar и Java 1.8:

int year = 1985; // 1985
int month = 1; // January
int day = 1; // 1st

// Original, 1900-based year, zero-based month, one-based day
Date date1 = new Date(year - 1900, month - 1, day);

// Calendar, zero-based year, zero-based month, one-based day
Calendar calendar = Calendar.getInstance();
calendar.clear(); // Sets hours/minutes/seconds/milliseconds to zero
calendar.set(year, month - 1, day);
Date date2 = calendar.getTime();

// Java-time back to Date, zero-based year, one-based month, one-based day
Date date3 = Date.from(LocalDate.of(year, month, day).atStartOfDay(ZoneId.systemDefault()).toInstant());

SimpleDateFormat format = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss.SSS");

// All 3 print "1985-Jan-01 00:00:00.000"
System.out.println(format.format(date1));
System.out.println(format.format(date2));
System.out.println(format.format(date3));

Ответ 14

Поскольку конструктор Date устарел, вы можете попробовать этот код.

import java.util.Calendar;

  Calendar calendar = Calendar.getInstance();
     calendar.set(Calendar.HOUR_OF_DAY, 6);// for 6 hour
     calendar.set(Calendar.MINUTE, 0);// for 0 min
     calendar.set(Calendar.SECOND, 0);// for 0 sec
     calendar.set(1996,0,26);// for Date [year,month(0 to 11), date]

    Date date = new Date(calendar.getTimeInMillis());// calendar gives long value

    String mConvertedDate = date.toString();// Fri Jan 26 06:00:00 GMT+05:30 1996