有人可以建议当前的“最佳实践”吗 DateCalendar 类型。

当编写新代码时,最好总是支持 Calendar 超过 Date, ,或者是否存在这样的情况 Date 是更合适的数据类型?

有帮助吗?

解决方案

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

就个人而言,我倾向于使用任何时间(以毫秒为单位)作为长(或适当的长)或日历。

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

其他提示

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

两者,日期日历,有很多设计问题这两个都不是新代码的好解决方案。

  • DateCalendar 实际上是相同的基本概念(都代表一个 瞬间 并且是底层的包装器 long 价值)。

  • 有人可能会争辩说 Calendar 实际上比 Date 是的,因为它似乎提供了有关一周中的某一天和一天中的时间之类的具体事实,而如果您更改它 timeZone 财产,混凝土变成了牛奶冻!这两个对象都不能真正用作存储 年月日 或者 一天中的某个时间 为此原因。

  • 使用 Calendar 仅作为计算器,当给定时 DateTimeZone 对象,将为您进行计算。避免将其用于应用程序中的属性类型。

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

  • 如果您喜欢冒险,请使用 Joda-Time,尽管恕我直言,它不必要地复杂,并且无论如何很快都会被 JSR-310 日期 API 取代。

  • 我之前已经回答过,自己推出并不难 YearMonthDay 类,它使用 Calendar 在引擎盖下进行日期计算。我对这项建议投了反对票,但我仍然相信它是有效的,因为 乔达时间 (和 JSR-310)对于大多数用例来说确实过于复杂。

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

日历最适合操纵日期。

  

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

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

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

对于最佳实践,我倾向于在域模型之外尽可能多地使用不可变对象。它显着降低了任何副作用的机会,它由编译器为您完成,而不是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);

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

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

太长了;博士

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

总是偏爱才是最好的 Calendar 超过 Date

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

细节

奥托玛拉的回答 Lokni 建议使用现代技术是正确的 java.time 类而不是麻烦的旧遗留日期时间类(Date, Calendar, , ETC。)。但该答案建议错误的类作为等效项(请参阅我对该答案的评论)。

使用java.time

java.time 类是 广阔的 改进了传统的日期时间类、昼夜差异。旧的类设计不佳、混乱且麻烦。您应该尽可能避免使用旧的类。但是,当您需要在旧/新之间进行转换时,可以通过调用 new 方法添加到 老的 类。

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

搜索 Stack Overflow 会提供数百个有关使用 java.time 的示例问题和答案。但这里有一个快速概要。

Instant

获取当前时刻 Instant. 。这 Instant 类代表时间线上的一个时刻 世界标准时间 分辨率为 纳秒 (最多九 (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. 。搜索 Stack Overflow 以获得更多讨论。

弦乐

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

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


关于 java.time

java.time 框架内置于 Java 8 及更高版本中。这些课程取代了麻烦的旧课程 遗产 日期时间类,例如 java.util.Date, Calendar, & SimpleDateFormat.

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

要了解更多信息,请参阅 甲骨文教程. 。并在 Stack Overflow 上搜索许多示例和解释。规格为 JSR 310.

用一个 JDBC驱动程序 符合 数据库连接4.2 或者稍后,您可以交换 java.time 对象直接与您的数据库。不需要字符串也不需要 java.sql.* 类。

从哪里获取 java.time 类?

三十额外 项目通过附加类扩展了 java.time。该项目是 java.time 未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如 Interval, YearWeek, YearQuarter, , 和 更多的.

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

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

您可以创建 ZonedDateTime <来自旧版 <的/ code> 对象代码> java.util.Date 对象如下:

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

我一直主张 Joda-time 。这就是原因。

  1. API一致且直观。与java.util.Date/Calendar API
  2. 不同
  3. 它不会遇到线程问题,不像 java.text.SimpleDateFormat 等。(我看到很多客户端问题与未意识到标准日期/时间格式不是线程安全的)
  4. 它是新的Java日期/时间API的基础( JSR310 ,计划用于Java 8.因此,您将使用将成为核心Java API的API。
  5. 编辑:如果可以迁移到Java 8,Java 8引入的Java日期/时间类现在是首选解决方案

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

应重新制定日期。它应该将年,月,日,小时,分钟,秒作为单独的字段,而不是长整数。存储与此日期相关联的日历和时区可能更加出色。

在我们的自然对话中,如果在2013年11月1日纽约时间下午1点设置预约,这是一个DateTime。它不是日历。所以我们也应该能够在Java中以这样的方式进行交谈。

当日期存储为长整数(自1970年1月1日以来的毫秒数)时,计算其当前日期取决于日历。不同的日历会给出不同的日期。这是出于绝对时间(例如大爆炸后1万亿秒)的前景。但通常我们也需要一种方便的对话方式,比如封装年,月等的对象。

我想知道Java是否有新的进展来协调这两个目标。也许我的java知识太旧了。

Btw“date”通常被标记为“过时/弃用” (我不确切地知道为什么) - 在那里写了一些关于它的东西 Java:为什么不推荐使用Date构造函数,以及我该怎么用?

通过 新日期(int year,int month,int day) 看起来只是构造函数的问题,推荐的方法是通过Calendar和set params分开..( 日历cal = Calendar.getInstance();

我在日期需要一些特定操作时使用日历,比如移动时间,但是当我需要格式化日期以适应您的需求时,我发现它很有用,最近我发现Locale有很多有用的操作,我现在正在使用Locale!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top