Java日期与日历

Mar*_*itt 358 java calendar date

有人可以建议当前的"最佳实践" DateCalendar类型.

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

cle*_*tus 375

Date是一个更简单的类,主要是出于向后兼容的原因.如果您需要设置特定日期或进行日期算术,请使用日历.日历还处理本地化.之前的Date日期操作函数已被弃用.

就个人而言,当有选择时,我倾向于使用毫秒作为长(或适当的长)或日历.

日期和日历都是可变的,在API中使用时往往会出现问题.

  • 仅供参考,非常麻烦的旧日期时间类,如[`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html),[ `java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html)和`java.text.SimpleDateFormat`现在是[遗产]( https://en.wikipedia.org/wiki/Legacy_system),由[*java.time*]取代(https://docs.oracle.com/javase/10/docs/api/java/time/package- summary.html)Java 8及更高版本中内置的类.请参阅[*Tutorial*by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). (3认同)

dme*_*ter 66

新代码的最佳方式(如果您的策略允许第三方代码)是使用Joda Time库.

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

  • 有关是使用Joda Time还是坚持使用标准JDK类的讨论,请参阅http://stackoverflow.com/questions/589870/should-i-use-java-date-and-time-classes-or-go-with-一,第三方库样乔达 (30认同)
  • 我第二个建议使用joda时间.它更易于使用和理解,并提供了更多可以使用的功能. (7认同)
  • 因为问题是关于使用日期和日历而不使用第三方库,这会给项目增加单一的供应商依赖风险. (7认同)
  • 在 Java 8 提供 [java.time 包](https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html) 之前,这是“最佳方式” . (4认同)
  • 我不知道它是否值得投票,但它没有回答这个问题.可能只是作为评论更好. (3认同)

oxb*_*kes 57

  • Date并且Calendar实际上是相同的基本概念(两者都代表了一个瞬间,并且是基础long价值的包装).

  • 人们可能会争辩说Calendar实际上甚至比实际上更加破碎Date,因为它似乎提供了关于诸如星期几和时间等事情的具体事实,而如果你改变它的timeZone属性,具体就会变成白痴!由于这个原因,这两个对象都不能用作年月日时间的存储.

  • 使用Calendar仅作为一个计算器其中,由于在DateTimeZone对象,会为你做计算.避免将其用于应用程序中的属性类型.

  • 使用SimpleDateFormat连同TimeZoneDate生成显示字符串.

  • 如果你喜欢冒险使用Joda-Time,虽然它是不必要的复杂恕我直言,并且很快就会被JSR-310 date API取代.

  • 我之前已经回答过,在你自己的YearMonthDay课程中使用它并不困难,它可以Calendar在引擎盖下进行日期计算.我对这个建议进行了投票,但我仍然相信这是一个有效的建议,因为Joda-Time(和JSR-310)对于大多数用例来说真的太复杂了.


KLE*_*KLE 25

日期最适合存储日期对象.它是持久的,序列化的......

日历最适合操纵日期.

注意:我们有时也喜欢java.lang.Long而不是Date,因为Date是可变的,因此不是线程安全的.在Date对象上,使用setTime()和getTime()在两者之间切换.例如,应用程序中的常量日期(示例:零1970/01/01,或者您设置为2099/12/31的应用END_OF_TIME;那些将空值替换为开始时间和结束时间非常有用,尤其是当你将它们保存在数据库中时,因为SQL对于null来说是如此奇特).


Arc*_*ano 17

如果可能,我通常使用日期.尽管它是可变的,但实际上不推荐使用mutators.最后它基本上包裹了一个代表日期/时间的长.相反,如果我必须操纵值,我会使用日历.

您可以这样想:只有当您需要使用可以轻松操作的字符串然后使用toString()方法将它们转换为字符串时,才使用StringBuffer.同样,如果我需要操作时态数据,我只使用Calendar.

对于最佳实践,我倾向于在域模型之外尽可能多地使用不可变对象.它显着降低了任何副作用的机会,它由编译器为您完成,而不是JUnit测试.您可以通过在类中创建私有最终字段来使用此技术.

并回到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);
Run Code Online (Sandbox Code Playgroud)


And*_*yle 15

Dates应该用作不可变时间点; Calendars是可变的,如果您需要与其他类协作以提出最终日期,则可以传递和修改.考虑它们类似于StringStringBuilder,你就会明白我是如何认为他们应该被使用.

(是的,我知道Date实际上并不是技术上不可变的,但意图是它不应该是可变的,如果没有任何东西调用已弃用的方法那么它就是这样.)


Bas*_*que 12

TL;博士

建议当前的"最佳实践" DateCalendar

总是喜欢Calendar过来是最好的Date

完全避免使用这些遗留类.请改用java.time类.

细节

通过Ortomala答案 Lokni是正确运用现代暗示java.time类,而不是麻烦的旧的遗留日期时间类(Date,Calendar,等).但是那个答案表明错误的等级是等同的(参见我对该答案的评论).

使用java.time

java.time类是对传统日期时间类,日夜差异的巨大改进.旧的课程设计糟糕,令人困惑,麻烦.你应该尽可能避免使用旧课程.但是当你需要转换为旧/新转换时,你可以通过调用新方法添加到类来实现.

有关转换的更多信息,请参阅我的答案和另一个问题的漂亮图表,将java.util.Date转换为"java.time"类型?.

搜索Stack Overflow在使用java.time时提供了数百个示例问题和解答.但这是一个快速的概要.

Instant

获取当前时刻Instant.该Instant级表示时间轴上的时刻UTC,分辨率为纳秒(最多9个(9)小数的位数).

Instant instant = Instant.now();
Run Code Online (Sandbox Code Playgroud)

ZonedDateTime

要通过某个特定区域的挂钟时间镜头看到相同的同时时刻,请应用时区()来获得a .ZoneIdZonedDateTime

时区

指定适当的时区名称,格式continent/region,如America/Montreal,Africa/CasablancaPacific/Auckland.切勿使用3-4字母缩写,例如ESTIST因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!).

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone();
Run Code Online (Sandbox Code Playgroud)

抵消

时区是区域与UTC的偏移量变化的历史记录.但有时你只给出一个没有完整区域的偏移量.在这种情况下,请使用该OffsetDateTime课程.

ZoneOffset offset = ZoneOffset.parse( "+05:30" );
OffsetDateTime odt = instant.atOffset( offset );
Run Code Online (Sandbox Code Playgroud)

使用时区优于仅使用偏移.

LocalDateTime

类中的"本地" Local…表示任何地点,而不是特定地点.所以这个名字可能违反直觉.

LocalDateTime,LocalDateLocalTime故意缺乏有关偏移或时区的任何信息.所以它们并不代表实际时刻,它们不是时间轴上的点.如果有疑问或混淆,请使用ZonedDateTime而不是LocalDateTime.搜索Stack Overflow进行更多讨论.

字符串

不要将日期时间对象与表示其值的字符串混淆.您可以解析字符串以获取日期时间对象,并且可以从日期时间对象生成字符串.但字符串永远不是日期时间本身.

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


关于java.time

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

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

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

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

从哪里获取java.time类?

ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval,YearWeek,YearQuarter,和更多.


Ort*_*kni 10

使用Java 8,应该使用新的java.time包.

对象是不可变的,时区和日光节省被考虑在内.

您可以ZonedDateTime从旧java.util.Date对象创建对象,如下所示:

    Date date = new Date();
    ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());
Run Code Online (Sandbox Code Playgroud)


Bri*_*new 9

我总是提倡乔达时间.这就是原因.

  1. API一致且直观.与java.util.Date/Calendar API不同
  2. 它没有遇到线程问题,不像java.text.SimpleDateFormat等.(我看到很多客户端问题与未意识到标准日期/时间格式不是线程安全的)
  3. 它是新的Java日期/时间API(JSR310,计划用于Java 8)的基础.因此,您将使用将成为核心Java API的API.

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

  • 我最后一次看,JODA和JSR-310看起来*非常不同,即使它们都是由Stephen Colebourne写的.也就是说,JODA会向您介绍JSR-310也解决的日期时间问题的复杂性 (3认同)
  • 鉴于java.util.Date和Calendar类的已知问题,建议Joda-Time(或JSR 310)似乎对我负责.我们不是在谈论品味或审美风格的问题.如果有人问他们是否应该乘坐红色汽车或银色汽车,而且我知道红色汽车的轮胎漏气,而且银色汽车有一个破损的散热器,我应该选车还是应该建议叫出租车?这个问题的答案现在看似显而易见,因为即便是Sun/Oracle也决定抛弃那些破坏者并购买新车:JSR 310:日期和时间API. (3认同)
  • 因为问题是关于使用日期和日历而不使用第三方库,这会给项目增加单一的供应商依赖风险. (2认同)
  • 我保持最佳做法就是不要使用那些类 (2认同)
  • 仅供参考,[*Joda-Time*](http://www.joda.org/joda-time/) 项目现在处于[维护模式](https://en.wikipedia.org/wiki/Maintenance_mode),建议迁移到 [*java.time*](http://docs.oracle.com/javase/10/docs/api/java/time/package-summary.html) 类。请参阅 [Oracle 教程](https://docs.oracle.com/javase/tutorial/datetime/TOC.html)。 (2认同)

Sil*_*cea 8

派对上有点晚了,但Java在JDK 8中有一个新的Date Time API.您可能希望升级JDK版本并接受标准.没有更多凌乱的日期/日历,没有更多的第三方罐子.