Java的日期VS日历(Java Date vs Calendar)

2019-07-17 13:57发布

可能有人请告知当前的“最佳实践”围绕DateCalendar类型。

当编写新的代码,它是最好的总是青睐CalendarDate ,还是有情况,其中Date是比较合适的数据类型?

Answer 1:

日期是一个简单的类,它主要是针对有向后兼容的原因。 如果您需要设定特定日期或做日期计算,使用日历。 日历也处理本地化。 日期的前一个日期操作功能,至今已弃用。

我个人倾向于以毫秒为使用时间较长(或长,如适用)或日历时,有一个选择。

日期和日历是可变的,这往往要么使用一个API的时候提出的问题。



Answer 2:

新代码(如果您的策略允许第三方代码)的最好方法是使用约达时间库 。

无论, 日期和日历 ,有这么多的设计问题,无论是对新代码良好的解决方案。



Answer 3:

  • DateCalendar实际上是同一个基本概念(均表示某个时刻 ,并围绕底层封装long值)。

  • 有人可能会争辩说, Calendar实际上是更坏了不是Date的,因为它似乎提供了这样的事情的一周和时间的一天具体的事实,而如果你改变它timeZone属性,具体变成牛奶冻! 无论对象是为年-月-日时间的天的这个原因商店真正有用的。

  • 使用Calendar只是作为一个计算器其中,由于当DateTimeZone的对象,会为你做计算。 避免了在应用程序中性能打字使用。

  • 使用SimpleDateFormat一起TimeZoneDate来生成显示字符串。

  • 如果你喜欢冒险的感觉使用乔达时间,虽然它是不必要的复杂恕我直言,很快将在任何情况下,JSR-310最新API所取代。

  • 我以前回答说,这是不难推出自己的YearMonthDay类,它使用Calendar引擎盖的日期计算下。 我downvoted您的建议,但我仍然认为这是一个有效的,因为乔达时间 (和JSR-310 )是真的那么过于复杂的大多数使用情况。



Answer 4:

日期是最好的保存日期的对象。 它是一个持久化,序列化一个...

日历是最好的操作日期。

注:我们有时也有利于java.lang.Long中了日期,因为日期是可变的,因此不是线程安全的。 在日期对象,使用时刻设定()和的getTime(),以在两者之间切换。 例如,一个恒定的日期在应用程序(例如:零1970/01/01,或时被设置为2099年12月31日的应用性END_OF_TIME;这些都是以取代空值的开始时间和结束时间是非常有用的,特别是当你坚持他们在数据库,SQL是空值如此奇特)。



Answer 5:

如果可能的话我一般使用日期。 虽然是可变的,在存取器实际上是过时。 最后,它基本上包装了一个长会代表的日期/时间。 相反,我会用日历如果我必须控制值。

你可以认为它是这样的:你只有只有当你需要有一个字符串,你可以很容易地操作,然后使用toString()方法将它们转换成字符串用StringBuffer。 以同样的方式,如果我需要操作时间的数据,我只用日历。

为了获得最佳的实践,我倾向于使用不可变对象尽可能多的领域模型之外。 这显著减少任何副作用的机会,它是由编译器,而不是一个JUnit测试为你做。 您可以使用在你的类创建私有final字段这种技术。

而回来的StringBuffer的比喻。 下面是一些代码,显示了如何日历和日期之间转换

String s = "someString"; // immutable string
StringBuffer buf = new StringBuffer(s); // mutable "string" via StringBuffer
buf.append("x");
assertEquals("someStringx", buf.toString()); // convert to immutable String

// immutable date with hard coded format.  If you are hard
// coding the format, best practice is to hard code the locale
// of the format string, otherwise people in some parts of Europe
// are going to be mad at you.
Date date =     new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2001-01-02");

// Convert Date to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);

// mutate the value
cal.add(Calendar.YEAR, 1);

// convert back to Date
Date newDate = cal.getTime();

// 
assertEquals(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2002-01-02"), newDate);


Answer 6:

Date也应该被用作时间不变点; Calendar s为可变的,并且可以被传递,如果你需要与其他班级合作,拿出最后的修改日期。 认为它们类似于StringStringBuilder ,你就会明白我是如何认为他们应该被使用。

(是的,我知道时间其实不是技术上一成不变的,但目的是,它不应该是可变的,如果没有调用过时方法则是这样。)



Answer 7:

TL;博士

建议当前的“最佳实践”围绕DateCalendar

是它最好的总是青睐CalendarDate

完全避免这些遗留类 。 使用java.time类来代替。

  • 对于一个时刻UTC ,使用Instant
    (相当于现代的Date
  • 在一个特定的瞬间时区 ,使用ZonedDateTime
    (相当于现代GregorianCalendar
  • 在一个特定的瞬间偏移从-UTC ,使用OffsetDateTime
    (在遗留类没有当量)
  • 对于日期时间(没有一刻)与未知的时区或偏移,使用LocalDateTime
    (在遗留类没有当量)

细节

在通过Ortomala答案 Lokni是正确运用现代暗示java.time类,而不是麻烦的旧的遗留日期时间类( DateCalendar等)。 但是这个答案提示错误的类等效(见我对答案的评论)。

使用java.time

该java.time类是在传统的日期时间类,夜间和天差一个巨大的进步。 旧的类设计拙劣的,混乱和麻烦。 你应该避免老班只要有可能。 但是,当你需要转换到/从旧/新,您可以通过调用新的方法添加到班这样做。

有关转换更多信息,请参阅我的回答和漂亮的图的另一个问题, 转换java.util.Date什么“java.time”型? 。

搜索堆栈溢出给出了几百例的问题和解答有关使用java.time。 但这里是一个快速摘要。

Instant

获得当前时刻与Instant 。 该Instant类表示在时间轴上的时刻UTC ,分辨率为纳秒 (最多9个(9)小数的位数)。

Instant instant = Instant.now();

ZonedDateTime

要查看同一时刻同时通过一些特定区域的镜头挂钟时间 ,应用一个时区( ZoneId )获得ZonedDateTime

时区

指定适当的时区名称 ,格式为continent/region ,如America/MontrealAfrica/Casablanca ,或Pacific/Auckland 。 切勿使用3-4个字母的缩写,如ESTIST ,因为它们不是真正的时区,不规范,甚至不是唯一的(!)。

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone();

抵消

时区是在变化的地区的历史偏移从-UTC 。 但有时你只给出一个不完整的区偏移。 在这种情况下,使用OffsetDateTime类。

ZoneOffset offset = ZoneOffset.parse( "+05:30" );
OffsetDateTime odt = instant.atOffset( offset );

一个时区的使用是最好在使用单纯的偏移。

LocalDateTime

“本地”的Local…类是指任何地方,而不是某一特定地区。 因此,名称可以是反直觉的。

LocalDateTimeLocalDate ,和LocalTime特意缺乏关于偏移或时区的任何信息。 因此,他们并不代表实际的时刻,他们不是在时间轴上的点。 如果有疑问或者困惑,使用ZonedDateTime而非LocalDateTime 。 搜索栈溢出了更多的讨论。

字符串

不要用代表其值的字符串混为一谈日期时间对象。 您可以解析字符串得到一个日期时间对象,并且可以生成日期时间对象的字符串。 但字符串是永远的日期,时间本身。

了解标准ISO 8601名的格式,在java.time类默认情况下使用。


关于java.time

java.time框架是建立在Java 8和更高版本。 这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar ,和SimpleDateFormat

乔达-时间的项目,现在在维护模式 ,建议迁移到java.time类。

要了解更多信息,请参阅甲骨文教程 。 和搜索堆栈溢出了很多例子和解释。 规范是JSR 310 。

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

从哪里获取java.time类?

  • 的Java SE 8Java SE的9 ,后来
    • 内置。
    • 具有捆绑实现标准Java API的一部分。
    • Java的9增加了一些小的功能和修复。
  • Java SE 6中Java SE 7中
    • 多的java.time功能后移植到Java 6和7在ThreeTen-反向移植
  • Android的
    • 后来版本的java.time类的Android束实现的。
    • 对于早期的Android,在ThreeTenABP项目适应ThreeTen -反向移植 (如上所述)。 请参阅如何使用ThreeTenABP ...

ThreeTen-额外项目与其他类扩展java.time。 该项目是为将来可能增加的java.time试验场。 您可以在这里找到一些有用的类,比如IntervalYearWeekYearQuarter ,和更多 。



Answer 8:

在Java 8中,新java.time包应该被使用。

对象是不可改变的,时区和夏令时都考虑到。

您可以创建一个ZonedDateTime从旧的对象java.util.Date对象是这样的:

    Date date = new Date();
    ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());


Answer 9:

我一贯主张乔达时间 。 这里的原因。

  1. 该API是一致的和直观。 不像java.util.Date/Calendar的API
  2. 它不会从线程问题,不像遭受java.text.SimpleDateFormat的等等(我已经看到了与没有意识到标准的日期/时间格式不是线程安全的众多客户端问题)
  3. 这是新的Java日期/时间的API(基础JSR310 ,定于Java的8所以你将可以使用API将成为核心的Java API。

编辑:与Java 8引入了Java的日期/时间类现在是首选的解决方案,如果你可以迁移到Java 8



Answer 10:

有点晚在党,但Java在JDK 8中的新日期时间API您可能需要升级你的JDK版本,拥抱标准。 没有更多的凌乱日期/日历,没有更多的第三方jar文件。



Answer 11:

日期应重新开发。 取而代之的是一个长整数,它应该持有的年,月,日,时,分,秒,作为单独的领域。 这可能是即使是好的存储该日期关联的日历和时区。

在我们的自然对话,如果建立约定在2013年11月1日下午1点纽约时间,这是一个DateTime。 它不是一个日历。 因此,我们应该能够交谈像这样在Java中也是如此。

当(由于1970年1月1日或东西的毫秒)日期存储为长整型,计算其当前日期依赖于日历。 不同的日历将给予不同的日期。 这是从预期的给予的绝对时间(例如万亿秒后大爆炸)。 但往往我们也需要对话的一种方便的方式,就像一个对象封装年月等。

我不知道是否有在Java中的新进展调和这两个目标。 也许我的Java知识太旧。



Answer 12:

顺便说一句“日期”通常被标记为“过时/弃用”(我不知道为什么) -一些关于它写的有Java的:为什么日期构造过时,我应该使用什么呢?

它看起来像它的通过新的日期(年整型,诠释月,日整型)only-方式,推荐的方式构造的一个问题是通过日历和单独设置PARAMS ..( 日历CAL = Calendar.getInstance();)



Answer 13:

我使用的日历,当我需要在日期一些特定的操作,例如在时间感动,但我时间找到它帮助时,您需要格式化的日期,以适应您的需求,最近我发现,区域设置有很多有用的操作和methods.So的我使用的语言环境,现在!



文章来源: Java Date vs Calendar