态查询
的java.time框架短得多包括架构,询问有关日期时间值:Temporal Query。 TemporalQuery
接口的一些实现可以在复数名为TemporalQueries
的类中找到。
您可以编写自己的实现,以及。 TemporalQuery
是functional interface,这意味着它有一个声明的方法。该方法是queryFrom
。
这是我第一次尝试在执行TemporalQuery
,所以拿一粒盐。这是完整的课程。免费使用(ISC License),但完全需要您自担风险。
棘手的部分是问题的要求是周末通过UTC来定义,而不是时区或通过日期时间值的偏移量。所以我们需要将传入的日期时间值调整为UTC。虽然Instant
在逻辑上等同,我用OffsetDateTime
与offset of UTC,因为它是更灵活的。具体而言,OffsetDateTime
提供了getDayOfWeek
方法。
CAVEAT:我不知道我是否正在做一个正统的方法,因为我没有完全理解它的创建者所期望的java.time设计的基础。具体而言,我不知道我的TemporalAccessor ta
转换为java.time.chrono.ChronoZonedDateTime
是否合适。但它似乎运作良好。
如果此类与Instant
实例以及ChronoZonedDateTime
/ZonedDateTime
一起使用会更好。
package com.example.javatimestuff;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
/**
* Answers whether a given temporal value is between Friday 22:00 UTC
* (inclusive) and Sunday 23:00 UTC (exclusive).
*
* @author Basil Bourque.
*
* © 2016 Basil Bourque
* This source code may be used according to the terms of the ISC License (ISC). (Basically, do anything but sue me.)
* https://opensource.org/licenses/ISC
*
*/
public class WeekendFri2200ToSun2300UtcQuery implements TemporalQuery<Boolean> {
static private final EnumSet<DayOfWeek> WEEKEND_DAYS = EnumSet.of (DayOfWeek.FRIDAY , DayOfWeek.SATURDAY , DayOfWeek.SUNDAY);
static private final OffsetTime START_OFFSET_TIME = OffsetTime.of (LocalTime.of (22 , 0) , ZoneOffset.UTC);
static private final OffsetTime STOP_OFFSET_TIME = OffsetTime.of (LocalTime.of (23 , 0) , ZoneOffset.UTC);
@Override
public Boolean queryFrom (TemporalAccessor ta) {
if ( ! (ta instanceof java.time.chrono.ChronoZonedDateTime)) {
throw new IllegalArgumentException ("Expected a java.time.chrono.ChronoZonedDateTime such as `ZonedDateTime`. Message # b4a9d0f1-7dea-4125-b68a-509b32bf8d2d.");
}
java.time.chrono.ChronoZonedDateTime czdt = (java.time.chrono.ChronoZonedDateTime) ta;
Instant instant = czdt.toInstant();
OffsetDateTime odt = OffsetDateTime.ofInstant (instant , ZoneOffset.UTC);
DayOfWeek dayOfWeek = odt.getDayOfWeek();
if ( ! WeekendFri2200ToSun2300UtcQuery.WEEKEND_DAYS.contains (dayOfWeek)) {
// If day is not one of our weekend days (Fri-Sat-Sun), then we know this moment is not within our weekend definition.
return Boolean.FALSE;
}
// This moment may or may not be within our weekend. Very early Friday or very late Sunday is not a hit.
OffsetDateTime weekendStart = odt.with (DayOfWeek.FRIDAY).toLocalDate().atTime (START_OFFSET_TIME); // TODO: Soft-code with first element of WEEKEND_DAYS.
OffsetDateTime weekendStop = odt.with (DayOfWeek.SUNDAY).toLocalDate().atTime (STOP_OFFSET_TIME); // TODO: Soft-code with last element of WEEKEND_DAYS.
// Half-Open -> Is equal to or is after the beginning, AND is before the ending.
// Not Before -> Is equal to or is after the beginning.
Boolean isWithinWeekend = ( ! odt.isBefore (weekendStart)) && (odt.isBefore (weekendStop));
return isWithinWeekend;
}
static public String description() {
return "WeekendFri2200ToSun2300UtcQuery{ " + START_OFFSET_TIME + " | " + WEEKEND_DAYS + " | " + STOP_OFFSET_TIME + " }";
}
}
让我们用TemporalQuery
。虽然定义TemporalQuery
需要一些工作,用它是如此非常简单和容易:
- 实例化一个
TemporalQuery
对象。
- 适用于我们的日期时间对象。
(在我们的例子中java.time.chrono.ChronoZonedDateTime
任何情况下,如ZonedDateTime
)
在使用中。
WeekendFri2200ToSun2300UtcQuery query = new WeekendFri2200ToSun2300UtcQuery();
我添加静态description
方法调试和记录,以确认查询的设置。这是我自己发明的方法,不需要TemporalQuery
接口。
System.out.println ("Weekend is: " + WeekendFri2200ToSun2300UtcQuery.description());
今天是星期二。不应该在周末。
ZonedDateTime now = ZonedDateTime.now (ZoneId.of ("America/Montreal"));
Boolean nowIsWithinWeekend = now.query (query);
System.out.println ("now: " + now + " is in weekend: " + nowIsWithinWeekend);
现在这个星期五早上。周末应该不是。
ZonedDateTime friday1000 = ZonedDateTime.of (LocalDate.of (2016 , 4 , 29) , LocalTime.of (10 , 0) , ZoneId.of ("America/Montreal"));
Boolean friday1000IsWithinWeekend = friday1000.query (query);
System.out.println ("friday1000: " + friday1000 + " is in weekend: " + friday1000IsWithinWeekend);
而在本周五晚些时候。在周末内应该为TRUE。
ZonedDateTime friday2330 = ZonedDateTime.of (LocalDate.of (2016 , 4 , 29) , LocalTime.of (23 , 30) , ZoneId.of ("America/Montreal"));
Boolean friday2330IsWithinWeekend = friday2330.query (query);
System.out.println ("friday2330: " + friday2330 + " is in weekend: " + friday2330IsWithinWeekend);
运行时。
周末是:WeekendFri2200ToSun2300UtcQuery {22:00Z | [星期五,星期六,星期日] | 23:00Z}
现在:2016-04-26T20:35:01.014-04:00 [美国/蒙特利尔]是在周末:假
friday1000:2016-04-29T10:00-04:00 [美洲/蒙特利尔]是周末:假
friday2330:2016-04-29T23:30-04:00 [美国/蒙特利尔]是周末:真
Local…
并不意味着本地
参考问题...说你想c将UTC值(周末开始/停止)的值与LocalDateTime
相比毫无意义。 A LocalDateTime
没有UTC的偏移时区。虽然命名可能是违反直觉的,但类别意味着它们可以适用于没有特定地点的任何地点。所以它们没有意义,它们不是时间轴上的一个点,直到您应用指定的偏移量或时区。
这整个答案假设你对这个术语感到困惑,并打算比较时间线上的实际时刻。(使用.now()
得到一个值来测试)
static class IsWeekendQuery implements TemporalQuery<Boolean>{
@Override
public Boolean queryFrom(TemporalAccessor temporal) {
return temporal.get(ChronoField.DAY_OF_WEEK) >= 5;
}
}
它会被称为像这样:
LocalDateTime没有时区信息 - 所以在这里说GMT没有意义...... – assylias
由于assylias评论说,如果你真的在UTC的时间轴上工作,你应该使用'即时'对象。 'LocalDateTime'类不*代表时间轴上的时刻;它代表了对可能时刻的模糊想法。 –