Java:为什么Date构造函数不推荐,我用什么来代替?

我来自C#世界,所以对Java还不太熟悉。 Eclipse刚刚告知, Date已被弃用。

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

为什么? 而且应该使用什么(特别是在上面的情况下)呢?


具体的Date构造函数已被弃用,应该使用日历。 JavaDoc for Date描述哪些构造函数已被弃用,以及如何使用日历来替换它们。


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


TL;博士

LocalDate.of( 1985 , 1 , 1 )

…要么…

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

细节

当Java第一次启动并发展时, java.util.Datejava.util.Calendarjava.text.SimpleDateFormat类被冲得太快了。 这些课程没有很好的设计或实施。 尝试改进,因此您已发现的弃用。 不幸的是,改进的尝试很大程度上失败 你应该完全避免这些类 。 它们在Java 8中被新类所取代。

代码中的问题

java.util.Date具有日期和时间部分。 您忽略了代码中的时间部分。 因此,Date类将按照JVM默认时区定义的那一天开始,并将该时间应用于Date对象。 所以你的代码的结果将取决于它运行的机器或设置的时区。 可能不是你想要的。

如果你只想要日期而没有时间部分,比如出生日期,你可能不想使用Date对象。 您可能只想以YYYY-MM-DD ISO 8601格式存储日期的字符串。 或者使用Joda-Time的LocalDate对象(见下文)。

乔达时间

在Java中学习的第一件事: 避免与Java捆绑在一起的臭名昭着的java.util.Date&java.util.Calendar类

正如在user3277382的答案中正确指出的那样,在Java 8中使用Joda-Time或新的java.time。*包。

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 ),并构建一个分配给该时区的日期 - 时间对象( 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.DateCalendarSimpleDateFormat等麻烦的旧式遗留日期时间类。

现在处于维护模式的Joda-Time项目建议迁移到java.time类。

要了解更多信息,请参阅Oracle教程。 并搜索堆栈溢出了很多例子和解释。 规范是JSR 310。

您可以直接与数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC驱动程序。 不需要字符串,不需要java.sql.*类。

何处获取java.time类?

  • Java SE 8Java SE 9Java SE 10和更高版本
  • 内置。
  • 带有捆绑实现的标准Java API的一部分。
  • Java 9增加了一些次要功能和修复。
  • Java SE 6Java SE 7
  • 大部分java.time功能都在ThreeTen-Backport中移植到Java 6和7。
  • Android的
  • 后续版本的java.time类的Android捆绑实现。
  • 对于早期的Android(<26), ThreeTenABP项目采用了ThreeTen-Backport(如上所述)。 请参阅如何使用ThreeTenABP ...。
  • ThreeTen-Extra项目将java.time扩展到其他类。 这个项目是未来可能增加java.time的一个试验场。 您可以在这里找到一些有用的课程,例如IntervalYearWeekYearQuarter等。

    链接地址: http://www.djcxy.com/p/18767.html

    上一篇: Java: Why is the Date constructor deprecated, and what do I use instead?

    下一篇: Should I use Java date and time classes or go with a 3rd party library like Joda Time?