Date vs TimeStamp vs calendar?

我有时会对java中不同的Date类型及其实际用法感到困惑。 在这里,我想总结一下我的理解

java.sql.Date :-一个围绕毫秒值的瘦包装器,允许JDBC将其标识为SQL DATE值

java.sql.Timestamp :- java.util.Date的一个瘦包装器,允许JDBC API将其标识为SQL TIMESTAMP值。 它增加了保持SQL TIMESTAMP小数秒值的function,允许将小数秒的指定精度设置为纳秒

我见过大多数项目更喜欢Timestamp而不是date。 我认为其主要原因是时间戳可以保持值达到纳秒精度,而数据可以保持到毫秒。 正确?

Calendar :-此类专为日期操作而设计,例如: – 用于在特定时刻和一组日历字段(如YEAR,MONTH,DAY_OF_MONTH,HOUR等)之间进行转换,以及用于操作日历字段,例如获得下周的日期。虽然我不知道为什么这个类是抽象的,只有一个实现存在,即GregorianCalendar。

java.sql.Timestamp java.util.Date一个瘦包装器,允许JDBC API将其标识为SQL TIMESTAMP值。

如果检查java.sql.Timestamp JavaDoc ,则该类非常明确地从java.util.Date 扩展 (如java.sql.Date所做)。 在实际项目java.util.Date ,在数据库java.util.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个不同的日历: BuddhistCalendarJapaneseImperialCalendarGregorianCalendar 。 此代码从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 ? 因为您必须在提供时使用抽象类和接口,而不是直接使用实现。 这里有更好的解释: “编程到接口”是什么意思?

除此之外,如果您将使用日期和时间,我建议使用像Joda-Time这样的库,它已经处理并解决了当前Java Date API的许多问题,并且还提供了在java.util.Date检索此日期和时间对象的方法java.util.Date味道。

java.time

您必须首先了解与Java早期版本捆绑在一起的那些旧的日期时间类是一个令人困惑的混乱的糟糕设计类与黑客。 他们是业界首次尝试使用复杂的日期时间处理设施,值得称赞。 但最终他们失败了。

它们已被Java 8及更高版本中内置的新java.time框架所取代。

  • java.sql.Date – 改为使用java.time.LocalDate
  • java.sql.Timestamp – 改为使用java.time.Instant
  • java.util.CalendarGregorianCalendar – 改为使用java.time.ZonedDateTime

仅限日期,没有时间或时区,请使用java.time.LocalDate 。 在UTC的时间轴上片刻,使用java.time.Instant 。 要为Instant分配不同的时区,请使用java.time.ZonedDateTime

了解UTC的偏移量仅仅是UTC之前或之后的小时数和分钟数。 时区是特定地区人民使用的偏移的过去,现在和将来变化的历史。

如果您的日期时间值具有与UTC相关的偏移而不是时区,则使用OffsetDateTime类表示该OffsetDateTime 。 然后调用其toInstant方法以获取要在类似于SQL标准TIMESTAMP WITH TIME ZONE类型的列中发送到数据库的Instant对象。

SQL标准类型TIMESTAMP WITHOUT TIME ZONE没有 ,没有)故意缺少任何时区概念或从UTC偏移。 遗留日期时间类无法表示此类值。 现在,在java.time中 ,我们有LocalDateTime

如果JDBC驱动程序符合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.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧遗留日期时间类,如java.util.DateCalendarSimpleDateFormat

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

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

您可以直接与数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC驱动程序 。 不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

  • Java SE 8Java SE 9Java SE 10及更高版本
    • 内置。
    • 带有捆绑实现的标准Java API的一部分。
    • Java 9增加了一些小function和修复。
  • Java SE 6Java SE 7
    • 许多java.timefunction都被反向移植到ThreeTen-Backport中的 Java 6和7。
  • Android的
    • 更高版本的Android捆绑java.time类的实现。
    • 对于早期的Android(<26), ThreeTenABP项目采用ThreeTen-Backport (如上所述)。 请参见如何使用ThreeTenABP ….

ThreeTen-Extra项目使用其他类扩展了java.time。 该项目是未来可能添加到java.time的试验场。 您可以在这里找到一些有用的课程,如IntervalYearWeekYearQuarter等。

原始问题的第一行包含短语“java中不同的日期类型及其实际用法”

时间戳数据类型的实际用法与它所说的完全相同 – SQL用于记录通常用于事务排序的精确时间顺序值的时间戳。 时间戳通常仅在内部使用…纳秒计数。 外部时间戳数据有用例,但它们相对较少。

日期类型以毫秒精度处理99%的外部非科学数据需求。