为什么 Date 构造函数已被弃用,我应该使用什么来代替?

发布于 2024-11-02 02:39:31 字数 196 浏览 3 评论 0 原文

我来自 C# 世界,所以对 Java 还不太有经验。 Eclipse 刚刚告诉我 Date 已被弃用:

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

为什么?应该使用什么(特别是在上述情况下)来代替?

I come from the C# world, so not too experienced with Java yet. I was just told by Eclipse that Date was deprecated:

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

Why? And what (especially in cases like above) should be used instead?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

梦里的微风 2024-11-09 02:39:32

目前大多数 Java 开发人员使用第三方包 Joda-Time。它被广泛认为是一个更好的实现。

然而,Java 8 将有一个新的 java.time.* 包。请参阅这篇文章介绍 JDK 8 的新日期和时间 API

Most Java developers currently use the third party package Joda-Time. It is widely regarded to be a much better implementation.

Java 8 however will have a new java.time.* package. See this article, Introducing the New Date and Time API for JDK 8.

凹づ凸ル 2024-11-09 02:39:32

Date 构造函数期望年份格式为自 1900 年以来的年份、从零开始的月份、从一开始的日期,并将小时/分钟/秒/毫秒设置为零。

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

因此,使用 Calendar 替换(从零开始的年份、从零开始的月份、从一开始的日期)来替换已弃用的 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(它具有从零开始的年份和从一开始的月份以及days):

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));

The Date constructor expects years in the format of years since 1900, zero-based months, one-based days, and sets hours/minutes/seconds/milliseconds to zero.

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

So using the Calendar replacement (zero-based years, zero-based months, one-based days) for the deprecated Date constructor, we need something like:

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

Or using Java 1.8 (which has zero-based year, and one-based months and days):

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

Here are equal versions of Date, Calendar, and 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));
鞋纸虽美,但不合脚ㄋ〞 2024-11-09 02:39:32

与 binnyb 建议的类似,您可以考虑使用较新的 Calendar >公历日历方法。请参阅这些最新文档:

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

Similar to what binnyb suggested, you might consider using the newer Calendar > GregorianCalendar method. See these more recent docs:

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

缘字诀 2024-11-09 02:39:32

您可以使用 Calendar 类在代码中创建类似于 new Date(year,month,date) 的方法。

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 构造函数一样工作

You can make a method just like new Date(year,month,date) in your code by using Calendar class.

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();
}

It will work just like the deprecated constructor of Date

夏有森光若流苏 2024-11-09 02:39:32

我从 Java 安全代码指南 得到这个

本节中的示例广泛使用 java.util.Date
可变 API 类的示例。在应用程序中,它将是
最好使用新的 Java 日期和时间 API (java.time.*)
被设计为不可变的。

I got this from Secure Code Guideline for Java

The examples in this section use java.util.Date extensively as it is
an example of a mutable API class. In an application, it would be
preferable to use the new Java Date and Time API (java.time.*) which
has been designed to be immutable.

旧街凉风 2024-11-09 02:39:32
new GregorianCalendar(1985, Calendar.JANUARY, 1).getTime();

(Java-8 之前的方式)

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

(the pre-Java-8 way)

雄赳赳气昂昂 2024-11-09 02:39:31

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

The java.util.Date class isn't actually deprecated, just that constructor, along with a couple other constructors/methods are deprecated. It was deprecated because that sort of usage doesn't work well with internationalization. The Calendar class should be used instead:

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();

Take a look at the date Javadoc:

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

花开浅夏 2024-11-09 02:39:31

tl;dr

LocalDate.of( 1985 , 1 , 1 )

…or…

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

详细信息

java.util.Datejava.util.Calendarjava.text.SimpleDateFormat 类被匆忙处理当 Java 首次推出和发展时,速度太快了。这些课程设计或实施得不好。尝试了改进,因此您发现了弃用。不幸的是,改进的尝试基本上失败了。您应该完全避免这些课程。它们在 Java 8 中被新类取代。

代码中的问题

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

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

Joda-Time

在 Java 中学习的第一件事:避免众所周知的麻烦的 java.util.Date & 。 java.util.Calendar 类与 Java 捆绑在一起。

正如 user3277382 的答案中正确指出的,使用 Joda-Time 或新的 Java 8 中的 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.timeJoda-Time 几乎相同一个>。

我们得到一个时区(ZoneId),并构造一个分配给该时区的日期时间对象(ZonedDateTime)。然后使用 不可变对象 模式,我们根据旧对象的同一时刻创建新的日期时间(自 epoch 以来的纳秒计数,但分配了其他时间区。最后我们得到一个 LocalDate< /a> 没有时间或时区,但请注意在确定日期时适用时区(新的一天在 奥斯陆纽约)。

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< /a>,日历,& SimpleDateFormat< /代码>

要了解更多信息,请参阅 Oracle 教程 。并在 Stack Overflow 上搜索许多示例和解释。规范为 JSR 310

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

您可以直接与数据库交换java.time对象。使用符合 JDBC 驱动程序 jeps/170" rel="noreferrer">JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* 类。 Hibernate 5 和 Hibernate 5 JPA 2.2 支持 java.time。

从哪里获取 java.time 类?

其中的表格java.time 库与哪个版本的 Java 或 Android 一起使用

tl;dr

LocalDate.of( 1985 , 1 , 1 )

…or…

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

Details

The java.util.Date, java.util.Calendar, and java.text.SimpleDateFormat classes were rushed too quickly when Java first launched and evolved. The classes were not well designed or implemented. Improvements were attempted, thus the deprecations you’ve found. Unfortunately the attempts at improvement largely failed. You should avoid these classes altogether. They are supplanted in Java 8 by new classes.

Problems In Your Code

A java.util.Date has both a date and a time portion. You ignored the time portion in your code. So the Date class will take the beginning of the day as defined by your JVM’s default time zone and apply that time to the Date object. So the results of your code will vary depending on which machine it runs or which time zone is set. Probably not what you want.

If you want just the date, without the time portion, such as for a birth date, you may not want to use a Date object. You may want to store just a string of the date, in ISO 8601 format of YYYY-MM-DD. Or use a LocalDate object from Joda-Time (see below).

Joda-Time

First thing to learn in Java: Avoid the notoriously troublesome java.util.Date & java.util.Calendar classes bundled with Java.

As correctly noted in the answer by user3277382, use either Joda-Time or the new java.time.* package in Java 8.

Example Code in 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 );

Dump to console…

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 );

When run…

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

In this case the code for java.time is nearly identical to that of Joda-Time.

We get a time zone (ZoneId), and construct a date-time object assigned to that time zone (ZonedDateTime). Then using the Immutable Objects pattern, we create new date-times based on the old object’s same instant (count of nanoseconds since epoch) but assigned other time zone. Lastly we get a LocalDate which has no time-of-day nor time zone though notice the time zone applies when determining that date (a new day dawns earlier in Oslo than in New York for example).

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();

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?

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

冬天旳寂寞 2024-11-09 02:39:31

特定的 Date 构造函数已弃用,应使用 Calendar 代替。
日期JavaDoc a> 描述了哪些构造函数已被弃用以及如何使用日历替换它们。

The specific Date constructor is deprecated, and Calendar should be used instead.
The JavaDoc for Date describes which constructors are deprecated and how to replace them using a Calendar.

叶落知秋 2024-11-09 02:39:31

我发现这个问题是一个较新的问题的重复,它询问什么获取特定年、月、日的 Date 的未弃用方法是。

到目前为止,这里的答案是使用 Calendar 类,在 Java 8 出现之前都是如此。但从 Java 8 开始,执行此操作的标准方法是:

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

然后,如果您确实需要 java.util.Date,则可以使用 这个问题

有关详细信息,请查看APIJava 8 教程

I came across this question as a duplicate of a newer question which asked what the non-deprecated way to get a Date at a specific year, month, and day was.

The answers here so far say to use the Calendar class, and that was true until Java 8 came out. But as of Java 8, the standard way to do this is:

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

And then if you really really need a java.util.Date, you can use the suggestions in this question.

For more info, check out the API or the tutorials for Java 8.

情未る 2024-11-09 02:39:31

不推荐使用构造函数的原因之一是年份参数的含义不是您所期望的。 javadoc 说:

从 JDK 版本 1.1 开始,被 Calendar.set(year + 1900, Month, date) 取代。

请注意,年份字段是自 1900 以来的年数,因此您的示例代码很可能不会执行您期望的操作。这就是重点。

一般来说,Date API 仅支持现代西历,具有特殊指定的组件,并且如果您设置字段,则行为会不一致。

CalendarGregorianCalendar API 比 Date 更好,并且第 3 方 Joda-time API 通常被认为是最好的。在 Java 8 中,他们引入了 java.time 包,这些包现在是推荐的替代方案。

One reason that the constructor is deprecated is that the meaning of the year parameter is not what you would expect. The javadoc says:

As of JDK version 1.1, replaced by Calendar.set(year + 1900, month, date).

Notice that the year field is the number of years since 1900, so your sample code most likely won't do what you expect it to do. And that's the point.

In general, the Date API only supports the modern western calendar, has idiosyncratically specified components, and behaves inconsistently if you set fields.

The Calendar and GregorianCalendar APIs are better than Date, and the 3rd-party Joda-time APIs were generally thought to be the best. In Java 8, they introduced the java.time packages, and these are now the recommended alternative.

小草泠泠 2024-11-09 02:39:31

请注意,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测试)

Please note that Calendar.getTime() is nondeterministic in the sense that the day time part defaults to the current time.

To reproduce, try running following code a couple of times:

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

Output eg.:

Sun Mar 07 10:46:21 CET 2010

Running the exact same code a couple of minutes later yields:

Sun Mar 07 10:57:51 CET 2010

So, while set() forces corresponding fields to correct values, it leaks system time for the other fields. (Tested above with Sun jdk6 & jdk7)

哥,最终变帅啦 2024-11-09 02:39:31

Date 本身并未被弃用。只是它的方法很多而已。 请参阅此处了解详细信息

使用 java.util.Calendar 相反。

Date itself is not deprecated. It's just a lot of its methods are. See here for details.

Use java.util.Calendar instead.

小梨窩很甜 2024-11-09 02:39:31

由于 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

As the Date constructor is deprecated, you can try this code.

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文