Weekend Filter for Java 8 LocalDateTime

I want to write a boolean function that returns true if the given LocalDateTime is between two specific points in time, otherwise false.

In particular, I want to have a LocalDateTime filter if the specified date is between 22:00 GMT on Friday and 23:00 GMT on Sunday.

The skeleton may look like this:

 public boolean isWeekend(LocalDateTime dateTime) { //Checks if dateTime falls in between Friday 22:00 GMT and Sunday 23:00 GMT //return ...??? } 

This is basically a weekend filter, and I wonder if there is a simple solution with the new Java 8 Time library (or any other existing filtering methods).

I know how to check the day of the week, hour, etc., but avoid reinventing the wheel.

+7
java filter java-8 java-time
source share
5 answers

I wrote a small program to achieve this.

PROGRAM

 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 22:00 GMT and Sunday 23:00 GMT return false; } } 
+2
source share

How do you expect such a library to work? You still need to say this when your weekend starts and ends, and it ends up not being much shorter than a simple

 boolean isWeekend(LocalDateTime dt) { switch(dt.getDayOfWeek()) { case FRIDAY: return dt.getHour() >= ...; case SATURDAY: return true; case SUNDAY: return dt.getHour() < ...; default: return false; } } 
+5
source share

Temporary request

The java.time structure includes an architecture for querying a date and time value: Temporal Query . Some implementations of the TemporalQuery interface can be found in the plural name TemporalQueries .

You can also write your own implementation. TemporalQuery is a functional interface that is, it has a single method declared. queryFrom method .

This is my first attempt at implementing TemporalQuery , so grab it with salt. Here is the full class. Free ( ISC License ), but completely at your own peril and risk.

The tricky part is the “Questions” requirement, that the weekend is determined by UTC, not the time zone or offset of the past date and time value. Therefore, we need to adjust the past date-time value in UTC format. Although Instant logically equivalent, I used OffsetDateTime with a UTC offset since it is more flexible. In particular, OffsetDateTime offers the getDayOfWeek method.

CAVEAT: I have no idea that I am doing something in the orthodox method, since I do not fully understand the basics of java.times projects, as provided by its creators. In particular, I'm not sure that my casting TemporalAccessor ta in java.time.chrono.ChronoZonedDateTime is correct. But it seems to work quite well.

It would be better if this class worked with Instant instances, as well as 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 + " }"; } } 

Use this TemporalQuery . Although defining TemporalQuery requires some work, using it is so simple and simple:

Using.

 WeekendFri2200ToSun2300UtcQuery query = new WeekendFri2200ToSun2300UtcQuery (); 

I added a static description method for debugging and logging to check query settings. This is my own method that is not required by the TemporalQuery interface.

 System.out.println ( "Weekend is: " + WeekendFri2200ToSun2300UtcQuery.description () ); 

First today, Tuesday. Should not be at the weekend.

 ZonedDateTime now = ZonedDateTime.now ( ZoneId.of ( "America/Montreal" ) ); Boolean nowIsWithinWeekend = now.query ( query ); System.out.println ( "now: " + now + " is in weekend: " + nowIsWithinWeekend ); 

Now this Friday morning. Should not be at the weekend.

 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 ); 

And late this Friday. Must be TRUE on the weekend.

 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 ); 

At startup.

Weekend: WeekendFri2200ToSun2300UtcQuery {22: 00Z | [FRIDAY, SATURDAY, SUNDAY] | 23: 00Z}

Now: 2016-04-26T20: 35: 01.014-04: 00 [America / Montreal] is on the weekend: false

friday1000: 2016-04-29T10: 00-04: 00 [America / Montreal] is on the weekend: false

friday2330: 2016-04-29T23: 30-04: 00 [America / Montreal] is on the weekend: true

Local… does not mean local

Referring to the question ... saying that you want to compare the values ​​of LocalDateTime with the values ​​in UTC (start / end of the weekend) does not make sense. A LocalDateTime does not have an offset-from-UTC time zone. Although naming can be intuitive, the Local… classes mean that they can be applied to any locality that lacks locality. Thus, they have no meaning, they are not a point on the timeline until you apply the specified offset or time zone.

This whole answer suggests that you were confused by this terminology and intended to compare the actual moment on the timeline.

+3
source share

A simple TemporalQuery will do the trick:

 static class IsWeekendQuery implements TemporalQuery<Boolean>{ @Override public Boolean queryFrom(TemporalAccessor temporal) { return temporal.get(ChronoField.DAY_OF_WEEK) >= 5; } } 

It will be called like this (using .now() to get the value to check):

 boolean isItWeekendNow = LocalDateTime.now().query(new IsWeekendQuery()); 

Or, in particular, UTC time (using .now() to get the value to check):

 boolean isItWeekendNow = OffsetDateTime.now(ZoneOffset.UTC).query(new IsWeekendQuery()); 

Based on your question, there is no reason to create a new instance of IsWeekendQuery every time it is used, so you might want to create a static final TemporalQuery that encapsulates the logic in a lambda expression:

 static final TemporalQuery<Boolean> IS_WEEKEND_QUERY = t -> t.get(ChronoField.DAY_OF_WEEK) >= 5; boolean isItWeekendNow = OffsetDateTime.now(ZoneOffset.UTC).query(IS_WEEKEND_QUERY); 
+2
source share

Hope this helps:

 LocalDateTime localDateTime = LocalDateTime.now(DateTimeZone.UTC); int dayNum = localDateTime.get(DateTimeFieldType.dayOfWeek()); boolean isWeekend = (dayNum == DateTimeConstants.SATURDAY || dayNum == DateTimeConstants.SUNDAY); 

This is the easiest way to do this without using many private constants.

0
source share

All Articles