Java8LocalDateTime的周末过滤器

Java8LocalDateTime的周末过滤器,java,filter,java-8,java-time,Java,Filter,Java 8,Java Time,我想编写一个布尔值函数,如果给定的LocalDateTime位于两个特定时间点之间,则返回true,否则返回false 具体来说,如果给定的日期在格林威治标准时间星期五22:00和星期日23:00之间,我希望有一个LocalDateTime过滤器 骨架可以如下所示: public boolean isWeekend(LocalDateTime dateTime) { //Checks if dateTime falls in between Friday's 22:00 GMT and

我想编写一个布尔值函数,如果给定的
LocalDateTime
位于两个特定时间点之间,则返回true,否则返回false

具体来说,如果给定的日期在格林威治标准时间星期五22:00和星期日23:00之间,我希望有一个
LocalDateTime
过滤器

骨架可以如下所示:

public boolean isWeekend(LocalDateTime dateTime) {
    //Checks if dateTime falls in between Friday's 22:00 GMT and Sunday's 23:00 GMT
    //return ...???
}
这基本上是一个周末过滤器,我想知道是否有一个新的Java8时间库(或任何其他现有的过滤器方法)的简单解决方案


我知道如何检查一周中的某一天、某个小时等,但避免重新发明轮子。

我编写了一个小程序来实现这一点

节目

public class TestWeekend {
    private static final int FRIDAY = 5;
    private static final int SATURDAY = 6;
    private static final int SUNDAY = 7;
    private static final Integer WEEKEND_START_FRIDAY_CUT_OFF_HOUR = 22;
    private static final Integer WEEKEND_END_SUNDAY_CUT_OFF_HOUR = 23;
    private static List<Integer> weekendDaysList = Arrays.asList(FRIDAY, SATURDAY, SUNDAY);

    public static void main(String []args) throws FileNotFoundException {
        System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,22,18,39)));
        System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,22,21,59)));
        System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,22,22,0)));
        System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,23,5,0)));
        System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,24,8,0)));
        System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,24,22,59)));
        System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,24,23,0)));
        System.out.println(" is weekend - "+isWeekend(LocalDateTime.of(2016,4,25,11,5)));
    }

    public static  boolean isWeekend(LocalDateTime dateTime) {
        System.out.print("Date - "+dateTime+" , ");
        if(weekendDaysList.contains(dateTime.getDayOfWeek().getValue()) ){
            if(SATURDAY ==  dateTime.getDayOfWeek().getValue()){
                return true;
            }
            if(FRIDAY == dateTime.getDayOfWeek().getValue() && dateTime.getHour() >=WEEKEND_START_FRIDAY_CUT_OFF_HOUR){
               return true;
            }else if(SUNDAY == dateTime.getDayOfWeek().getValue() && dateTime.getHour()  < WEEKEND_END_SUNDAY_CUT_OFF_HOUR ){
                return   true;
            }
        }
        //Checks if dateTime falls in between Friday's 22:00 GMT and Sunday's 23:00 GMT
         return false;
    }

 }
公共类TestWeekend{
私人静态最终整数星期五=5;
私人静态最终int周六=6;
私人静态最终整数周日=7;
私人静态最终整数周末\开始\周五\截止\小时=22;
私人静态最终整数周末结束周日截止时间小时=23;
private static List weekendDaysList=Arrays.asList(星期五、星期六、星期日);
公共静态void main(字符串[]args)引发FileNotFoundException{
System.out.println(“is weekend-”+isWeekend(LocalDateTime.of(2016,4,22,18,39));
System.out.println(“is weekend-”+isWeekend(LocalDateTime.of(2016,4,22,21,59));
System.out.println(“is weekend-”+isWeekend(LocalDateTime.of(2016,4,22,22,0));
System.out.println(“is weekend-”+isWeekend(LocalDateTime.of(2016,4,23,5,0));
System.out.println(“is weekend-”+isWeekend(LocalDateTime.of(2016,4,24,8,0));
System.out.println(“is weekend-”+isWeekend(LocalDateTime.of(2016,4,24,22,59));
System.out.println(“is weekend-”+isWeekend(LocalDateTime.of(2016,4,24,23,0));
System.out.println(“is weekend-”+isWeekend(LocalDateTime.of(2016,4,25,11,5));
}
公共静态布尔值isWeekend(LocalDateTime-dateTime){
系统输出打印(“日期-”+日期时间+”,”;
if(weekendDaysList.contains(dateTime.getDayOfWeek().getValue()){
如果(星期六==dateTime.getDayOfWeek().getValue()){
返回true;
}
如果(星期五==dateTime.getDayOfWeek().getValue()&&dateTime.getHour()>=WEEKEND\u START\u FRIDAY\u CUT\u OFF\u HOUR){
返回true;
}else if(SUNDAY==dateTime.getDayOfWeek().getValue()&&dateTime.getHour()
您希望这样的库如何工作?你仍然需要告诉它你的周末开始和结束的时间,结果不会比简单的时间短很多

boolean isWeekend(LocalDateTime dt) {
    switch(dt.getDayOfWeek()) {
        case FRIDAY:
            return dt.getHour() >= ...;
        case SATURDAY:
            return true;
        case SUNDAY:
            return dt.getHour() < ...;
        default:
            return false;
    }
}
boolean isWeekend(LocalDateTime dt){
开关(dt.getDayOfWeek()){
案件星期五:
返回dt.getHour()>=。。。;
案件星期六:
返回true;
案件星期日:
返回dt.getHour()<。。。;
违约:
返回false;
}
}
时态查询 time框架包括一个用于询问日期时间值的体系结构:。接口的一些实现可以在复数命名类中找到

您也可以编写自己的实现。是,表示它声明了一个方法。方法是

这是我第一次尝试实现
临时查询
。这是完整的课程。免费使用(),但风险完全由您自己承担

棘手的部分是问题的要求是周末由UTC定义,而不是时区或传递的日期时间值的偏移量。因此,我们需要将传递的日期时间值调整为UTC。虽然
Instant
在逻辑上是等效的,但我使用了,因为它更灵活。具体来说,
OffsetDateTime
提供了一种方法

警告:我不知道我是不是在用正统的方法做事,因为我没有完全理解java.time的设计基础,正如它的创造者所希望的那样。具体而言,我不确定将
临时助理ta
转换为a是否正确。但它似乎工作得很好

如果该类与
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 + " }";
    }

}
我添加了一个用于调试和记录的静态
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 );
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 );
现在是这个星期五早上。不应该在周末

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 );
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 );
星期五晚些时候。应该是真的,在周末之内

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 );
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 );
跑步的时候

周末是:周日从2200到2300UTCQUERY{22:00Z |[周五、周六、周日]| 23:00Z}

现在:2016-04-26T20:35:01.014-04:00[美国/蒙特利尔]周末:假

星期五1000:2016-04-29T10:00-04:00[美国/蒙特利尔]在周末:假

星期五2330:2016-04-29T23:30-04:00[美国/蒙特利尔]在周末:对

Local…
不表示本地 提到这个问题……说您想将
LocalDateTime
与UTC(周末开始/停止)中的值进行比较是没有意义的。
LocalDateTime
与UTC之间没有偏移时区。虽然命名可能与直觉相反,
Local…
类意味着它们可以应用于没有特定区域的任何区域。因此,它们没有任何意义,它们不是时间线上的一个点,除非应用指定的偏移量或时区


这个完整的答案假设您对这个术语感到困惑,并且确实打算比较时间线上的一个实际时刻。

一个简单的
TemporalQuery
就可以做到:

static class IsWeekendQuery implements TemporalQuery<Boolean>{

    @Override
    public Boolean queryFrom(TemporalAccessor temporal) {
        return temporal.get(ChronoField.DAY_OF_WEEK) >= 5;
    }
}
或者,特别是UTC时间(现在使用
)(
someListOfDates.stream()
   .filter(isWeekend)
   .forEach(System.out::println);