Java:为什么日期构造函数被弃用,我该用什么呢?tl;博士详代码中的问题城大时间java.time关于 java.time

2022-08-31 05:31:34

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

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

为什么?应该使用什么(特别是在像上面这样的情况下)?


答案 1

该类实际上并未被弃用,只是该构造函数以及其他几个构造函数/方法被弃用。它被弃用了,因为这种用法不适用于国际化。应改用该类:java.util.DateCalendar

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


答案 2

tl;博士

LocalDate.of( 1985 , 1 , 1 )

...或。。。

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

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

代码中的问题

java.util.Date 既有日期部分,也有时间部分。您忽略了代码中的时间部分。因此,Date 类将采用 JVM 的默认时区所定义的一天的开始时间,并将该时间应用于 Date 对象。因此,代码的结果将根据它运行的计算机或设置的时区而有所不同。可能不是你想要的。

如果您只想使用日期,而不想要时间部分(例如出生日期),则可能不想使用对象。您可能希望仅存储日期的字符串,格式为 ISO 8601。或者使用 Joda-Time 中的 LocalDate 对象(见下文)。DateYYYY-MM-DD

城大时间

在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

要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310

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

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

从哪里获取 java.time 类?

Table of which java.time library to use with which version of Java or Android