態查詢
的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'類不*代表時間軸上的時刻;它代表了對可能時刻的模糊想法。 –