可能有人请告知当前的“最佳实践”围绕Date
和Calendar
类型。
当编写新的代码,它是最好的总是青睐Calendar
上Date
,还是有情况,其中Date
是比较合适的数据类型?
可能有人请告知当前的“最佳实践”围绕Date
和Calendar
类型。
当编写新的代码,它是最好的总是青睐Calendar
上Date
,还是有情况,其中Date
是比较合适的数据类型?
日期是一个简单的类,它主要是针对有向后兼容的原因。 如果您需要设定特定日期或做日期计算,使用日历。 日历也处理本地化。 日期的前一个日期操作功能,至今已弃用。
我个人倾向于以毫秒为使用时间较长(或长,如适用)或日历时,有一个选择。
日期和日历是可变的,这往往要么使用一个API的时候提出的问题。
新代码(如果您的策略允许第三方代码)的最好方法是使用约达时间库 。
无论, 日期和日历 ,有这么多的设计问题,无论是对新代码良好的解决方案。
Date
和Calendar
实际上是同一个基本概念(均表示在某个时刻 ,并围绕底层封装long
值)。
有人可能会争辩说, Calendar
实际上是更坏了不是Date
的,因为它似乎提供了这样的事情的一周和时间的一天具体的事实,而如果你改变它timeZone
属性,具体变成牛奶冻! 无论对象是为年-月-日或时间的天的这个原因商店真正有用的。
使用Calendar
只是作为一个计算器其中,由于当Date
和TimeZone
的对象,会为你做计算。 避免了在应用程序中性能打字使用。
使用SimpleDateFormat
一起TimeZone
和Date
来生成显示字符串。
如果你喜欢冒险的感觉使用乔达时间,虽然它是不必要的复杂恕我直言,很快将在任何情况下,JSR-310最新API所取代。
我以前回答说,这是不难推出自己的YearMonthDay
类,它使用Calendar
引擎盖的日期计算下。 我downvoted您的建议,但我仍然认为这是一个有效的,因为乔达时间 (和JSR-310 )是真的那么过于复杂的大多数使用情况。
日期是最好的保存日期的对象。 它是一个持久化,序列化一个...
日历是最好的操作日期。
注:我们有时也有利于java.lang.Long中了日期,因为日期是可变的,因此不是线程安全的。 在日期对象,使用时刻设定()和的getTime(),以在两者之间切换。 例如,一个恒定的日期在应用程序(例如:零1970/01/01,或时被设置为2099年12月31日的应用性END_OF_TIME;这些都是以取代空值的开始时间和结束时间是非常有用的,特别是当你坚持他们在数据库,SQL是空值如此奇特)。
如果可能的话我一般使用日期。 虽然是可变的,在存取器实际上是过时。 最后,它基本上包装了一个长会代表的日期/时间。 相反,我会用日历如果我必须控制值。
你可以认为它是这样的:你只有只有当你需要有一个字符串,你可以很容易地操作,然后使用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);
Date
也应该被用作时间不变点; Calendar
s为可变的,并且可以被传递,如果你需要与其他班级合作,拿出最后的修改日期。 认为它们类似于String
和StringBuilder
,你就会明白我是如何认为他们应该被使用。
(是的,我知道时间其实不是技术上一成不变的,但目的是,它不应该是可变的,如果没有调用过时方法则是这样。)
建议当前的“最佳实践”围绕
Date
和Calendar
是它最好的总是青睐
Calendar
上Date
完全避免这些遗留类 。 使用java.time类来代替。
Instant
Date
) ZonedDateTime
GregorianCalendar
) OffsetDateTime
LocalDateTime
在通过Ortomala答案 Lokni是正确运用现代暗示java.time类,而不是麻烦的旧的遗留日期时间类( Date
, Calendar
等)。 但是这个答案提示错误的类等效(见我对答案的评论)。
该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/Montreal
, Africa/Casablanca
,或Pacific/Auckland
。 切勿使用3-4个字母的缩写,如EST
或IST
,因为它们不是真正的时区,不规范,甚至不是唯一的(!)。
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…
类是指任何地方,而不是某一特定地区。 因此,名称可以是反直觉的。
LocalDateTime
, LocalDate
,和LocalTime
特意缺乏关于偏移或时区的任何信息。 因此,他们并不代表实际的时刻,他们不是在时间轴上的点。 如果有疑问或者困惑,使用ZonedDateTime
而非LocalDateTime
。 搜索栈溢出了更多的讨论。
不要用代表其值的字符串混为一谈日期时间对象。 您可以解析字符串得到一个日期时间对象,并且可以生成日期时间对象的字符串。 但字符串是永远的日期,时间本身。
了解标准ISO 8601名的格式,在java.time类默认情况下使用。
该java.time框架是建立在Java 8和更高版本。 这些类取代麻烦的老传统日期时间类,如java.util.Date
, Calendar
,和SimpleDateFormat
。
该乔达-时间的项目,现在在维护模式 ,建议迁移到java.time类。
要了解更多信息,请参阅甲骨文教程 。 和搜索堆栈溢出了很多例子和解释。 规范是JSR 310 。
使用JDBC驱动程序与兼容JDBC 4.2或更高版本,您可以直接与数据库交换java.time对象。 无需字符串,也不是的java.sql。*类。
从哪里获取java.time类?
该ThreeTen-额外项目与其他类扩展java.time。 该项目是为将来可能增加的java.time试验场。 您可以在这里找到一些有用的类,比如Interval
, YearWeek
, YearQuarter
,和更多 。
在Java 8中,新java.time包应该被使用。
对象是不可改变的,时区和夏令时都考虑到。
您可以创建一个ZonedDateTime
从旧的对象java.util.Date
对象是这样的:
Date date = new Date();
ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());
我一贯主张乔达时间 。 这里的原因。
编辑:与Java 8引入了Java的日期/时间类现在是首选的解决方案,如果你可以迁移到Java 8
有点晚在党,但Java在JDK 8中的新日期时间API您可能需要升级你的JDK版本,拥抱标准。 没有更多的凌乱日期/日历,没有更多的第三方jar文件。
日期应重新开发。 取而代之的是一个长整数,它应该持有的年,月,日,时,分,秒,作为单独的领域。 这可能是即使是好的存储该日期关联的日历和时区。
在我们的自然对话,如果建立约定在2013年11月1日下午1点纽约时间,这是一个DateTime。 它不是一个日历。 因此,我们应该能够交谈像这样在Java中也是如此。
当(由于1970年1月1日或东西的毫秒)日期存储为长整型,计算其当前日期依赖于日历。 不同的日历将给予不同的日期。 这是从预期的给予的绝对时间(例如万亿秒后大爆炸)。 但往往我们也需要对话的一种方便的方式,就像一个对象封装年月等。
我不知道是否有在Java中的新进展调和这两个目标。 也许我的Java知识太旧。
顺便说一句“日期”通常被标记为“过时/弃用”(我不知道为什么) -一些关于它写的有Java的:为什么日期构造过时,我应该使用什么呢?
它看起来像它的通过新的日期(年整型,诠释月,日整型)only-方式,推荐的方式构造的一个问题是通过日历和单独设置PARAMS ..( 日历CAL = Calendar.getInstance();)
我使用的日历,当我需要在日期一些特定的操作,例如在时间感动,但我时间找到它帮助时,您需要格式化的日期,以适应您的需求,最近我发现,区域设置有很多有用的操作和methods.So的我使用的语言环境,现在!