我来自C#世界,所以对Java还没有太多经验。刚刚被Eclipse告知Date
已被弃用。
Person p = new Person();
p.setDateOfBirth(new Date(1985, 1, 1));
为什么呢?应该使用什么(特别是在上面的情况下)呢?
答案 0 :(得分:227)
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
答案 1 :(得分:91)
不推荐使用特定的Date构造函数,而应使用Calendar。 Date的JavaDoc描述了不推荐使用的构造函数以及如何使用Calendar替换它们。
答案 2 :(得分:62)
LocalDate.of( 1985 , 1 , 1 )
...或...
LocalDate.of( 1985 , Month.JANUARY , 1 )
当Java首次启动和发展时,java.util.Date
,java.util.Calendar
和java.text.SimpleDateFormat
类的速度过快。这些课程没有很好地设计或实施。尝试了改进,因此您发现了弃用。不幸的是,改进的尝试基本上失败了你应该完全避免这些类。它们在Java 8中被新类取代。
java.util.Date同时包含日期和时间部分。您忽略了代码中的时间部分。因此,Date类将按照JVM的默认时区定义的一天开始,并将该时间应用于Date对象。因此,代码的结果将根据其运行的机器或设置的时区而有所不同。可能不是你想要的。
如果您只想要日期,没有时间部分,例如出生日期,您可能不想使用Date
对象。您可能只想以ISO 8601格式YYYY-MM-DD
存储日期字符串。或者使用Joda-Time的LocalDate
对象(见下文)。
用Java学习的第一件事:避免臭名昭着的java.util.Date& Java捆绑的java.util.Calendar类。
正如the answer by user3277382中正确指出的那样,在Java 8中使用Joda-Time或新的java.time.* package。
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的代码几乎与Joda-Time的代码相同。
我们获得一个时区(ZoneId
),并构建一个分配给该时区的日期时间对象(ZonedDateTime
)。然后使用Immutable Objects模式,我们根据旧对象的同一时刻(自epoch以来的纳秒数)创建新的日期时间,但指定了其他时区。最后,我们得到一个LocalDate
,它没有时间或时区,但是在确定该日期时注意到时区适用(Oslo中的新日期早于New York中的新日期例子)。
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 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和& SimpleDateFormat
现在位于Joda-Time的maintenance mode项目建议迁移到java.time类。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310。
您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
和more。
答案 3 :(得分:11)
我将此问题视为a newer question的副本,其中询问了在特定年份,月份和日期获取Date
的未弃用方法是什么。
到目前为止,答案是使用Calendar
类,直到Java 8出现之前都是如此。但是从Java 8开始,执行此操作的标准方法是:
LocalDate localDate = LocalDate.of(1985, 1, 1);
然后,如果您确实需要java.util.Date
,则可以使用this question中的建议。
有关详细信息,请查看{8}的the API或the tutorials。
答案 4 :(得分:10)
不推荐使用构造函数的一个原因是year参数的含义不是您所期望的。 javadoc说:
从JDK 1.1版开始,由
Calendar.set(year + 1900, month, date)
替换。
请注意,年份字段是自1900
以来的年数,因此您的示例代码很可能无法按照您的预期执行操作。这就是重点。
通常,Date
API仅支持现代西方日历,具有特殊指定的组件,并且如果设置字段则行为不一致。
Calendar
和GregorianCalendar
API优于Date
,第三方Joda-time API通常被认为是最好的。在Java 8中,他们引入了java.time
包,现在推荐这些包。
答案 5 :(得分:8)
请注意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测试过)
答案 6 :(得分:6)
Date
本身并未弃用。这只是它的很多方法。 See here for details
改为使用java.util.Calendar
。
答案 7 :(得分:5)
大多数Java开发人员目前使用第三方软件包Joda-Time。它被广泛认为是一种更好的实施方式。
Java 8但是会有一个新的java.time.* package。请参阅此文Introducing the New Date and Time API for JDK 8。
答案 8 :(得分:2)
我从Secure Code Guideline for Java那里得到了
本节中的示例按原样广泛使用java.util.Date 可变API类的示例。在一个应用程序中,它将是 最好使用新的Java日期和时间API(java.time。*),该API 被设计为不可变的。
答案 9 :(得分:1)
与binnyb建议的类似,您可以考虑使用较新的日历> GregorianCalendar方法。请参阅这些最近的文档:
http://download.oracle.com/javase/6/docs/api/java/util/GregorianCalendar.html
答案 10 :(得分:1)
通过使用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
答案 11 :(得分:1)
不建议使用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
答案 12 :(得分:0)
new GregorianCalendar(1985, Calendar.JANUARY, 1).getTime();
(Java-8之前的方式)
答案 13 :(得分:0)
Date构造函数期望以1900年以来的年份格式,从零开始的月份,并将小时/分钟/秒/毫秒设置为零。
Date result = new Date(year, month, day);
因此,对于已过时的Date构造函数使用Calendar替换(从零开始的年份,从零开始的月份,从一个开始的日子),我们需要类似以下内容:
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());
以下是日期,日历和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));