0

I need to define different periods in the week. I then need to pass a series of Calendar objects to see which period these Calendar objects correspond to.

e.g. Period1:

    Mon 12:00-15:00
    Tue 14:00-17:00

Period2:

    Wed,Thu 09:00-17:00

Period3:

    Thur 17:00-24:00
    Fri  00:00-24:00

What is the best way to define these periods in code to pass in calendar objects to see which one if any they correspond to?

Youcef LAIDANI
  • 55,661
  • 15
  • 90
  • 140
OneXer
  • 303
  • 9
  • 20

2 Answers2

1

Always favour the java.time classes (or Joda-Time or the ThreeTen backport if you aren't on Java 8 yet). See this article for the 'why'.

I would use a DayOfWeek and two LocalTimes

class WeekPeriod
{
    private final DayOfWeek day;
    private final LocalTime start;
    private final LocalTime end;

    //constructor and methods
}

Combine these into three Set<WeekPeriod>s to represent your three examples.

Michael
  • 41,989
  • 11
  • 82
  • 128
  • Good answer. Prefer to receive your times to check as `ZonedDateTime` or `LocalDateTime`. Extract day of week and time of day through `getDayOfWeek()` and `toLocalTime()` and compare to the fields of each `WeekPeriod` object. If you cannot avoid `Calendar` objects, make sure you get `GregorianCalendar` and convert using [GregorianCalendar.toZonedDateTime()](https://docs.oracle.com/javase/9/docs/api/java/util/GregorianCalendar.html#toZonedDateTime--). – Ole V.V. May 24 '18 at 09:06
  • I think Duration will be better here with DayOfWeek apart from whats is laready mentioned. A Duration measures an amount of time using time-based values. – Amit May 24 '18 at 09:07
  • @Amit A `Duration` doesn’t tell you whether the period began at `09:00` or at `14:00`. You may use a start time and a `Duration` in combination of course. Which to prefer depends on the concrete situation and requirements. – Ole V.V. May 24 '18 at 09:11
  • @OleV.V. Right. I did consider a `LocalTime` and a `Duration` but it seemed more confusing. You can extract a `Duration` from two `LocalTime`s simply enough anyway (and if that becomes a performance problem, memo it). – Michael May 24 '18 at 09:18
1

Java 7 and ThreeTen Backport

Michael’s answer is good. I’d just like to supply a few details. Since you mentioned in another question that you are using Java 7, I present code for Java 7.

First, the date-time classes that Michael is using, are not built into Java 7, but have been backported. So get the ThreeTen Backport that he mentions and import the date-time classes from the org.threeten.bp package:

import org.threeten.bp.DateTimeUtils;
import org.threeten.bp.DayOfWeek;
import org.threeten.bp.LocalTime;
import org.threeten.bp.ZoneId;
import org.threeten.bp.ZonedDateTime;

Then add the following method to Michael’s WeekPeriod class:

public boolean isInPeriod(ZonedDateTime dateTime) {
    DayOfWeek dowToCheck = dateTime.getDayOfWeek();
    LocalTime timeToCheck = dateTime.toLocalTime();
    return dowToCheck.equals(day)
            && ! timeToCheck.isBefore(start)
            && timeToCheck.isBefore(end);
}

If you prefer the parameter to be a LocalDateTime or an OffsetDateTime, just change it, the code is the same. You can overload the method, of course, to accept all three types.

If you cannot avoid getting Calendar objects, write one or two overloaded methods for them too. Convert your Calendar to a ZonedDateTime and call the above method. It‘s a bit more straightforward if your Calendar is a GregorianCalendar, which it probably is:

public boolean isInPeriod(GregorianCalendar cal) {
    return isInPeriod(DateTimeUtils.toZonedDateTime(cal));
}

If it isn’t:

public boolean isInPeriod(Calendar cal) {
    ZoneId zone = DateTimeUtils.toZoneId(cal.getTimeZone());
    return isInPeriod(DateTimeUtils.toInstant(cal).atZone(zone));
}

All of the above works in Java 7 and in Java 6 too. I have tested on jdk1.7.0_79.

Java 8 and later

For anyone reading along and using Java 8 or later:

  • Import the date-time classes from the java.time package instead (don’t use ThreeTen Backport).
  • Instead of using DateTimeUtils convert using the methods that have been built into Calendar and GregorianCalendar from Java 8. For the GregorianCalendar use cal.toZonedDateTime(). For other Calendar subclasses use cal.getTimeZone().toZoneId() and then cal.toInstant().

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161