我来自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));
为什么?而应该使用什么(尤其是在上述情况下)呢?
Answers:
Date
不赞成使用特定的构造函数,而Calendar
应改用它。在JavaDoc
对日描述了构造已被弃用,以及如何使用,以取代他们Calendar
。
java.util.Date
,java.util.Calendar
和java.text.SimpleDateFormat
现在的遗产,由取代java.time内置到Java 8和更高等级。请参见Oracle 教程。
该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
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(<timezone id>));
java.time.*
如果要更改代码,则这些类是更好的选择。
LocalDate.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
。或使用LocalDate
Joda-Time中的对象(请参见下文)。
用Java学习的第一件事:避免与Java捆绑在一起的臭名昭著的java.util.Date和java.util.Calendar类。
正如user3277382的答案正确指出的那样,请在Java 8中使用Joda-Time或新的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
在这种情况下,java.time的代码与Joda-Time几乎相同。
我们得到一个时区(ZoneId
),并构造一个分配给该时区(ZonedDateTime
)的日期时间对象。然后,使用不可变对象模式,我们根据旧对象的同一瞬间(自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
。
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
要了解更多信息,请参见Oracle教程。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310。
您可以直接与数据库交换java.time对象。使用与JDBC 4.2或更高版本兼容的JDBC驱动程序。不需要字符串,不需要类。java.sql.*
在哪里获取java.time类?
该ThreeTen-额外项目与其他类扩展java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。
构造函数被弃用的原因之一是year参数的含义与您期望的不一样。Javadoc说:
从JDK 1.1版开始,由取代
Calendar.set(year + 1900, month, date)
。
请注意,year字段是自以来的年数1900
,因此您的示例代码很可能不会执行您期望的操作。这就是重点。
通常,Date
API仅支持现代西方日历,具有特殊指定的组件,并且如果您设置字段,则行为会不一致。
在Calendar
和GregorianCalendar
API是比好Date
,和第三方乔达时间的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测试)
Date
本身不被弃用。这只是它的很多方法。有关详细信息,请参见此处。
使用java.util.Calendar
代替。
目前,大多数Java开发人员都使用第三方软件包Joda-Time。人们普遍认为它是一种更好的实现。
但是,Java 8将具有新的java.time。*包。请参阅本文,介绍JDK 8的新日期和时间API。
由于不推荐使用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
Date
和Calendar
在2019年提出的建议不多。
与binnyb建议的类似,您可以考虑使用更新的Calendar> GregorianCalendar方法。请参阅以下最新文档:
http://download.oracle.com/javase/6/docs/api/java/util/GregorianCalendar.html
您可以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
Instant
和)取代ZonedDateTime
。
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));
new GregorianCalendar(1985, Calendar.JANUARY, 1).getTime();
(Java-8之前的方式)