我来自C#世界,所以对Java还不是很有经验。刚才Eclipse告诉我Date
被弃用了:
Person p = new Person();
p.setDateOfBirth(new Date(1985, 1, 1));
为什么?在这种情况下应该使用什么替代方案?
我来自C#世界,所以对Java还不是很有经验。刚才Eclipse告诉我Date
被弃用了:
Person p = new Person();
p.setDateOfBirth(new Date(1985, 1, 1));
为什么?在这种情况下应该使用什么替代方案?
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();
请查看Java文档中的日期说明:
http://download.oracle.com/javase/6/docs/api/java/util/Date.html
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(<timezone id>));
- Vikas Prasadjava.time.*
类是更好的选择。 - Stephen CLocalDate.of( 1985 , 1 , 1 )
…或者…
LocalDate.of( 1985 , Month.JANUARY , 1 )
java.util.Date
、java.util.Calendar
和java.text.SimpleDateFormat
类在Java第一次推出和发展时被匆忙推出。这些类的设计和实现都不太好。改进尝试过,因此您发现了它们的弃用。不幸的是,改进尝试在很大程度上失败了。您应该完全避免使用这些类。在Java 8中,它们被新类所取代。
java.util.Date
既有日期部分,也有时间部分。您在代码中忽略了时间部分。因此,Date类将采用JVM默认时区定义的一天开始时间,并将该时间应用于Date对象。因此,您的代码结果将根据运行的机器或设置的时区而异。可能不是您想要的。
Date
对象。您可能希望仅存储日期字符串,格式为ISO 8601的YYYY-MM-DD
。或者使用来自Joda-Time的LocalDate
对象(参见下文)。
Java中要学习的第一件事:避免与Java捆绑在一起的臭名昭著的java.util.Date和java.util.Calendar类。
如user3277382的答案所正确指出的那样,请使用Joda-Time或Java 8中的新java.time.*包。
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
ZoneId
),并构建一个分配给该时区的日期时间对象(ZonedDateTime
)。然后使用 Immutable Objects 模式,基于旧对象的相同瞬间(自epoch以来的纳秒计数)创建新的日期时间对象,但分配到其他时区。最后,我们得到一个 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 8 及更高版本内置的。这些类取代了老旧的 遗留 日期时间类,例如 java.util.Date
、Calendar
和 SimpleDateFormat
。
要了解更多,请参阅Oracle教程。并搜索Stack Overflow以获得许多示例和解释。规范是JSR 310。
Joda-Time 项目现在处于维护模式,建议迁移到java.time 类。
您可以直接使用与您的数据库兼容的JDBC驱动程序(符合JDBC 4.2或更高版本)来交换java.time对象。不需要字符串,也不需要java.sql.*
类。Hibernate 5和JPA 2.2支持java.time。
如何获取java.time类?
具体的 Date
构造函数已经被废弃,应使用 Calendar
代替。
JavaDoc 中说明了哪些构造函数已经被废弃,以及如何使用 Calendar
替换它们。
java.util.Date
、java.util.Calendar
和 java.text.SimpleDateFormat
这样的旧日期时间类现在已经成为 遗留系统,被 Java 8 及更高版本内置的 java.time 类所取代。请参阅 Oracle 的 教程。 - Basil Bourque构造函数被弃用的一个原因是,年份参数的含义不是您所期望的。Javadoc中写道:
自JDK版本1.1起,被
Calendar.set(year + 1900, month, date)
替换。
请注意,年份字段是自1900年以来的年数,因此您的示例代码很可能不会执行您所期望的操作。这就是重点。
通常,Date
API仅支持现代西方日历,具有独特指定的组件,并且如果您设置字段,则行为不一致。
Calendar
和GregorianCalendar
API优于Date
,第三方的Joda-time API通常被认为是最好的。在Java 8中,他们引入了java.time
包,现在是推荐的替代方法。
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上进行了测试)大多数Java开发者目前使用第三方包Joda-Time。它被广泛认为是一个更好的实现。
Java 8将有一个新的java.time.* package。请参阅这篇文章,介绍JDK 8的新日期和时间API。
由于日期构造函数已被弃用,您可以尝试使用此代码。
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
Date
和Calendar
是不好的建议。 - Basil BourqueDate 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();
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));