我有时会对java中不同的Date类型及其实际用法感到困惑。这里 我想总结一下我的理解
java.sql.Date :-
一个围绕毫秒值的瘦包装器,允许JDBC将其标识为SQL DATE值
java.sql.Timestamp :-
java.util.Date的瘦包装器,允许JDBC API将其识别为SQL
TIMESTAMP值。它通过允许规范添加了保存SQL TIMESTAMP小数秒值的功能
小秒的精度为纳秒
我见过大多数项目更喜欢Timestamp而不是date。我认为其主要原因是Timestamp可以保持值直到 纳秒精度,而数据可以保持毫秒。正确的吗?
Calendar :-
此类专为日期操作而设计,例如: - 用于在特定时刻和a之间进行转换
一组日历字段,例如YEAR,MONTH,DAY_OF_MONTH,HOUR等,以及用于操作日历字段,例如获取
下周的日期。虽然我不知道为什么这个类是抽象的,只有一个实现存在,即GregorianCalendar。
答案 0 :(得分:15)
java.sql.Timestamp
围绕java.util.Date
的瘦包装器,允许JDBC API将其标识为SQL TIMESTAMP值。
如果您选中java.sql.Timestamp
JavaDoc,则此类扩展非常明确java.util.Date
(如java.sql.Date
所示)。在现实世界的项目中,您必须在数据库中存储数据java.util.Date
,并且大多数java.sql.Timestamp
因为它存储日期和时间值,而java.sql.Date
只存储日期值。
另一方面,java.util.Calendar
是抽象的,因为除了java.util.GregorianCalendar
之外还有更多的实现。如果您从HotSpot看到Calendar#getInstance
的代码,则会看到它调用createCalendar(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT))
,此方法代码使用3种不同的日历:BuddhistCalendar
,JapaneseImperialCalendar
和{{3 }}。此代码从JDK 7源代码复制:
private static Calendar createCalendar(TimeZone zone,
Locale aLocale) {
Calendar cal = null;
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype == null) {
// Calendar type is not specified.
// If the specified locale is a Thai locale,
// returns a BuddhistCalendar instance.
if ("th".equals(aLocale.getLanguage())
&& ("TH".equals(aLocale.getCountry()))) {
cal = new BuddhistCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
} else if (caltype.equals("japanese")) {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else if (caltype.equals("buddhist")) {
cal = new BuddhistCalendar(zone, aLocale);
} else {
// Unsupported calendar type.
// Use Gregorian calendar as a fallback.
cal = new GregorianCalendar(zone, aLocale);
}
return cal;
}
现在,为什么要直接使用Calendar
代替GregorianCalendar
?因为您必须在提供时使用抽象类和接口,而不是直接使用实现。这里有更好的解释:GregorianCalendar
除此之外,如果您将使用日期和时间,我建议使用像What does it mean to "program to an interface"?这样的库,它已经处理并解决了当前Java Date API的许多问题,并提供了检索此日期的方法和时间对象java.util.Date
味道。
答案 1 :(得分:11)
你必须首先明白,与早期版本的Java捆绑在一起的那些旧的日期时间类是一个令人困惑的混乱的糟糕设计类与黑客。他们是业界首次尝试使用复杂的日期时间处理设施,值得称赞。但最终他们失败了。
它们已被Java 8及更高版本中内置的新java.time框架所取代。
java.sql.Date
- 使用java.time.LocalDate
代替java.sql.Timestamp
- 使用java.time.Instant
代替java.util.Calendar
& GregorianCalendar
- 使用java.time.ZonedDateTime
代替仅限日期,没有时间或时区,请使用java.time.LocalDate
。暂时在UTC的时间轴上,使用java.time.Instant
。要为即时分配不同的时区,请使用java.time.ZonedDateTime
。
了解UTC的偏移量仅仅是UTC之前或之后的小时数和分钟数。时区是特定地区人民使用的偏移的过去,现在和将来变化的历史。
如果您的日期时间值具有与UTC相关的偏移而不是时区,请使用OffsetDateTime
类表示该值。然后调用其toInstant
方法,以类似于SQL标准Instant
的类型的列的形式获取要发送到数据库的TIMESTAMP WITH TIME ZONE
对象。
SQL标准类型TIMESTAMP WITHOUT TIME ZONE
(不带,带)故意缺少任何时区概念或从UTC偏移。遗留日期时间类无法表示此类值。现在,在 java.time 中,我们有LocalDateTime
。
如果JDBC driver符合JDBC 4.2或更高版本,则可以直接与数据库交换 java.time 对象。无需再次使用java.sql日期项类型。
myPreparedStatement.setObject( … , instant ) ;
并检索。
Instant instant = myResultSet.getObject( … , Instant.class ) ;
调整特定地区(时区)人员使用的挂钟时间。
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
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。
答案 2 :(得分:1)
原始问题的第一行包含短语“java中不同的日期类型及其实际用法”
时间戳数据类型的实际用法与它所说的完全相同 - SQL用于记录通常用于事务排序的精确时间顺序值的时间戳。时间戳通常仅在内部使用...纳秒计数。有外部时间戳数据的用例,但它们相对较少。
日期类型以毫秒精度处理99%的外部非科学数据需求。