推荐使用Joda-Time的DateMidnight

LocalDate#toDateMidnight内容如下:

从v1.5开始,build议您避免使用DateMidnight,并使用toDateTimeAtStartOfDay()代替,因为下面详细列出了这个例外。

如果默认时区在午夜切换到夏令时并且此LocalDate表示切换date,则此方法将引发exception。 问题在于,在规定的date没有午夜的时间,因此抛出exception。

事实上,在某些时区不存在午夜似乎是足够的理由,以避免完全使用DateMidnight (假设您的代码没有使用已知不具有此DST情况的固定时区,并且将永远不需要使用不同的时区未来)。

但是, DateMidnight不被弃用,并且在DateMidnight类本身的javadoc中没有类似的build议或警告。 此外, DateMidnight构造函数愉快地接受即时和时区,使得在给定的一天中不存在午夜,而不是像LocalDate#toDateMidnight一样抛出IllegalArgumentException 。 结果DateMidnight行为就像一个DateTime时间在一天的开始。

当某一天午夜不存在时,为什么LocalDate#toDateMidnightDateMidnight构造函数不引发时抛出exception? 如果有的话, DateMidnight的推荐用例是什么?

没有很好的理由使用DateMidnightLocalDate是更好的select。 那是因为午夜在某些时区不会发生一次,彻底搞乱了课程的可用性,并在应用程序中造成了错误。

构造函数被修复,以避免最糟糕的问题,但是看到一个DateMidnight对象的内部毫秒值指向01:00不是很好。

新的DateTime()。 withTimeAtStartOfDay()被推荐。

或者更好地使用LocalDate方法toDateTimeAtStartOfDay直接绕过DateTime对象的创build(关于上面的答案 )。

 new LocalDate().toDateTimeAtStartOfDay( myDateTimeZone ) 

TL;博士

使用java.time类,特别是LocalDate::atStartOfDay而不是“午夜”的滑动想法。

 ZoneId z = ZoneId.of( "America/Montreal" ); // A time zone. ZonedDateTime todayStart = LocalDate.now( z ).atStartOfDay( z ); // Produces a LocalDate (a whole day without time zone), then transforms into a `ZonedDateTime` (a moment on the timeline) 

java.time

由于Joda-Time项目现在处于维护模式,团队build议迁移到java.time类,我将使用java.time添加示例。

如果您想要整体表示整个一天,请使用LocalDate类。 LocalDate类代表没有时间和没有时区的只有date的值。

时区对确定date至关重要。 对于任何特定的时刻,date在全球各地按照地区而不同。 例如, 巴黎午夜过后的几分钟, 法国是一个新的一天,而在魁北克蒙特利尔仍然是“昨天”。

 ZoneId z = ZoneId.of( “America/Montreal” ); LocalDate today = LocalDate.now( z ); 

正如本页所讨论的那样,试图确定一天的结束是很糟糕的做法。 一方面,在一天的最后一秒,你有一个无限可分的分数问题。 你会毫不犹豫地解决毫秒,微秒,纳秒或其他的东西,因为所有这些都是常用的? 相反,使用新的一天的第一时刻。

让java.time确定一天中第一个时刻的挂钟时间。 不要认为时间将是00:00:00 ,因为夏令时(DST)等exception情况可能意味着第一时间是诸如01:00:00的时间。 目前在多个国家的时区使用这种DST调整。

因此,为了获得一个时间,在时间线上的一个实际点,在一天的开始时间调用LocalDate::atStartOfDay 。 请注意,这是方法名称的withTimeAtStartOfDay版本,比Joda-Time的withTimeAtStartOfDay方法中使用的版本更短。 在ZoneId指定所需/预期的时区以生成ZonedDateTime对象。

 ZoneId z = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = today.atStartOfDay( z ); 

半开

那么如何performance一段时间? 如果我想查明这一天的开始和结束,那我该怎么做呢? date时间工作中常用的解决scheme是半开放方法。 在这种方法中,跨度的开始是包含性的,而结束是排他性的 。 所以“今天”意味着从一天中的第一个时刻开始,直到第二天的第一时刻,但包括在内。

 ZonedDateTime zdtStartToday = LocalDate.now( z ).atStartOfDay( z ); ZonedDateTime zdtStartTomorrow = zdtStartToday.plusDays( 1 ); 

顺便说一下, ThreeTen-Extra项目在这样的时间跨度上有一个方便的Interval类。

 Interval todayInterval = Interval.of( zdtStartToday.toInstant() , zdtStartTomorrow.toInstant() ) 

关于java.time

java.time框架内置于Java 8及更高版本中。 这些类取代了麻烦的旧date时间类,如java.util.Date.Calendarjava.text.SimpleDateFormat

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

要了解更多信息,请参阅Oracle教程 。 并search堆栈溢出了很多例子和解释。

大部分的java.timefunction在ThreeTen-Backport中移植到Java 6&7中,并进一步适用于ThreeTenABP中的 Android (请参阅如何使用… )。

ThreeTen-Extra项目将java.time扩展到其他类。 这个项目是未来可能增加java.time的一个试验场。 你可能会在这里find一些有用的类,比如IntervalYearWeekYearQuarter 等等 。

看看我在我的代码中的例外

 Illegal instant due to time zone offset transition (daylight savings time 'gap'): 2015-03-27T00:00:00.000 (Asia/Amman) org.joda.time.IllegalInstantException: Illegal instant due to time zone offset transition (daylight savings time 'gap'): 2015-03-27T00:00:00.000 (Asia/Amman) 

现在我解决了它的使用

 LocalDate currentDate=new LocalDate(); someMethodSetsTheDate(currentDate.toDateTimeAtStartOfDay().toDate()); 

代替

 someMethodSetsTheDate(new DateMidnight(date.getYear(), date.getMonthOfYear(), date.getDayOfMonth()).toDate()); 

现在我的build议是使用.toDateTimeAtStartOfDay()来避免类似的例外。

请随时编辑我的答案感谢