铊
LocalTime now = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )
.toLocalTime() ;
Boolean isBetween = ( ! now.isBefore( LocalTime.of( 18 , 0 ) ) // "not before" means "is equal to OR after".
&&
now.isBefore( LocalTime.of( 18 , 30 ) ) ; // Half-Open, beginning is *inclusive* while ending is *exclusive*.
使用java.time
您使用的是旧的日期时间类,这些类被证明设计不好、容易混淆并且很麻烦。他们现在是
legacy
,由java.time类替代。
LocalTime
不要只传递表示时间值的字符串。我们现在有了一种类型
当地时间
班级。
LocalTime start = LocalTime.of( 18 , 0 );
LocalTime stop = LocalTime.of( 18 , 30 );
将这些实例传递给实用工具方法。该方法不必进行任何解析,因此无需引发解析异常。
public static boolean isCurrentTimeBetween( LocalTime start , LocalTime stop ) {
â¦
ZonedDateTime
时区对于确定当前日期和时间至关重要。在任何一个特定的时刻,日期在全球各地各不相同。例如,在
Paris France
在昨天还是新的一天吗
Montréal Québec
.
指定
proper time zone name
格式为
continent/region
,例如
America/Montreal
,
Africa/Casablanca
,或者
Pacific/Auckland
. 切勿使用3-4字母缩写,如
EST
或
IST
就像他们一样
不
真正的时区,不标准,甚至不独特!.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now( z );
为了比较一天中的时间,我们可以简单地提取
当地时间
从那个开始
分区日期时间
. 但是我们有异常的问题,例如夏令时(DST)和政治家重新定义时区。某一特定日期不得有任何下午6点。这个难题的解决方案取决于您的业务环境和业务规则。你可以忽略这个难题,坚持字面上的询问,当前时间是否在你的目标开始-停止时间之间。或者你可以把时区应用到你每天的起止时间,让
分区日期时间
类根据需要进行调整。让我们看看这两种方法。
忽略异常
首先,忽略任何异常。简单而准确地询问当前时间是否介于目标开始时间和停止时间之间。
我们可以从分区日期时间对象中提取时间对象。
LocalTime localTimeNow = zdt.toLocalTime(); // Extract a time-of-day from the zoned date-time object.
把它与我们一天中的停止-开始时间进行比较。注意,我们在这里使用半开放的方法来定义时间跨度。在这种方法中,开始是
包容的
当结尾是
独占
. 这种方法在日期时间工作中很常见,通常是明智的做法。
Boolean isNowOnOrAfterStart = ( ! localTimeNow.isBefore( start ) ) ; // A briefer way of asking "is equal to OR is after" is "is not before".
Boolean isNowBeforeStop = localTimeNow.isBefore( stop );
Boolean isNowInTargetZone = ( isNowOnOrAfterStart && isNowBeforeStop ); // Half-Open: beginning is inclusive while ending is exclusive.
考虑异常情况
接下来我们考虑任何异常情况。我们将一天的开始和停止时间应用于同一时区内的当前日期。我们只从分区日期时间对象提取日期。
LocalDate localDateToday = zdt.toLocalDate();
ZonedDateTime zdtStart = ZonedDateTime.of( localDateToday , start , z );
ZonedDateTime zdtStop = ZonedDateTime.of( localDateToday , stop , z );
学习课堂文档以了解
ZonedDateTime.of
解析无效的时间值。没有完美的方法来解决不存在的时间值,因此您必须决定这个类方法是否符合您的业务规则。
分区日期时间
public static ZonedDateTime of(LocalDate date,
LocalTime time,
ZoneId zone)
从本地日期和时间获取ZonedDateTime的实例。
这将创建一个与输入的本地日期和时间尽可能接近的分区日期时间。时区规则(如夏令时)意味着并非每个本地日期时间都对指定的区域有效,因此可以调整本地日期时间。
本地日期时间和第一个组合形成本地日期时间。然后将本地日期时间解析为时间线上的单个即时。这是通过在区域ID规则定义的本地日期时间内找到与UTC/格林威治的有效偏移量来实现的。
在大多数情况下,本地日期时间只有一个有效的偏移量。在重叠的情况下,当时钟返回时,有两个有效的偏移。此方法使用通常与“夏季”对应的早期偏移量。
在间隙的情况下,当时钟向前跳时,没有有效的偏移。相反,本地日期时间会根据间隙的长度进行调整,以使其更晚。对于典型的一小时夏令时更改,本地日期时间将在一小时后移动到通常对应于“夏季”的偏移量中。
应用与我们上面看到的相同的比较逻辑。
Boolean isNowOnOrAfterStart = ( ! zdt.isBefore( zdtStart ) ) ; // A briefer way of asking "is equal to OR is after" is "is not before".
Boolean isNowBeforeStop = zdt.isBefore( zdtStop );
Boolean isNowInTargetZone = ( isNowOnOrAfterStart && isNowBeforeStop ); // Half-Open: beginning is inclusive while ending is exclusive.
另一种比较方法是使用
Interval
从threeten额外项目中类。那门课很痛苦
Instant
对象,可以从
分区日期时间
物体。这个
Instant
类表示时间线上的某一时刻
UTC
决议为
nanoseconds
(小数点后最多九(9)位)。
Interval interval = Interval.of( zdtStart.toInstant() , zdtStop.toInstant() );
Boolean isNowInTargetZone = interval.contains( zdt.toInstant() );
关于java.time
这个
java.time
框架是在Java 8和之后构建的。这些阶级取代了麻烦的旧阶级。
遗产
日期时间类,如
java.util.Date
,
Calendar
,&
SimpleDateFormat
.
这个
Joda-Time
项目,现在在
maintenance mode
,建议迁移到
java.time时间
课程。
要了解更多信息,请参阅
Oracle Tutorial
. 以及搜索堆栈溢出以获得许多示例和解释。规格为
JSR 310
.
在哪里获取java.time类?
这个
ThreeTen-Extra
Project使用其他类扩展java.time。这个项目是将来可能添加到java.time的一个试验场。您可以在这里找到一些有用的类,例如
Interval
,
YearWeek
,
YearQuarter
和
more
.