Make sure the date range applies to the time range

Sam works as a part-time truck driver. He receives a special allowance if he travels from 02:00 to 06:00. His boss wants to know what all the trips concerned this time period. Below are the details of his last 4 trips.

Shutdown 1:

StartDateTime: 01-JAN-2017 00.15.00
EndDateTime: 03-JAN-2017 01.45.00

Touch: True

Shutdown 2:

StartDateTime: 04-JAN-2017 13.00.00
EndDateTime: 05-JAN-2017 13.00.00

Touch: True

Trip 3:

StartDateTime: 06-JAN-2017 00.00.00
EndDateTime: 06-JAN-2017 05.00.00

Touch: True

Trip 4:

StartDateTime: 06-JAN-2017 06.01.00
EndDateTime: 06-JAN-2017 23.00.00

Touch: False

java, , -, . , ?

:

    public boolean isTripTouchingTimeRange(Date startDate, Date endDate, AllowanceDefinition def) {

    int checkConstant = HOURS_IN_A_DAY - (def.getEndMinute() - def.getStartMinute());
    // HOURS_IN_A_DAY = 1440 MINUTES (2400 HRS) ; def.getEndMinute() = 360
    // MINUTES (0600 HRS) ; def.getStartMinute() = 120 MINUTES (0200 HRS)

    DateTime start = new DateTime(startDate);
    DateTime end = new DateTime(endDate);
    if (DateUtil.subtractDates(start.toDate(), end.toDate()) > checkConstant) {
        return true;
    } else if (end.withTimeAtStartOfDay().isAfter(start.withTimeAtStartOfDay())
            && (end.getMinuteOfDay() > def.getStartMinute())) {
        return true;
    } else if (start.getMinuteOfDay() <= def.getEndMinute() && def.getStartMinute() <= end.getMinuteOfDay()) {
        return true;
    }
    return false;
    }
+4
3

.

, . .

,

TimeAngle = Pi * TimeHrs / 12

, , "":

  • , 0..2 * Pi. :
    • 00:00 0
    • TripStartAngle = Pi * StartTripTimeHrs / 12.
      , 06:00 Pi*6/12 = Pi/2 = 90 degree ( 24- )
    • TripEndAngle = Pi * EndTripTimeHrs / 12. (- ), 2 * Pi.
      , 15:00 Pi*15/12 = 1.25 * Pi.
      03:00 - Pi*3/12 = Pi/4 - less than starting Pi/2, so add 2*Pi, and result is 2.25*Pi
+2

, , -, (, , ), . , .

Interval trees , .

, , "" , 0200/0600. , .,.

20 , - . (, 1 2)

20 , , .

0200/0600 . startDateTime 0000 0600 (), 0200/0600 startDateTime, .

duration = endDateTime - startDateTime mustStartTime = 0200 - duration mustEndTime = 0600 + duration touched = (startDateTime >= mustStartTime && endDateTime <= mustEndTime)

3

  • StartDateTime: 06-JAN-2017 00.00.00
  • EndDateTime: 06-JAN-2017 05.00.00
  • Touched: True

duration = 5 hours mustStartTime = 2100 = 0200 - 5 mustEndTime = 1100 = 0600 + 5 touched = (0000 >= 2100 && 0500 <= 1100) = (true && true)

4

  • StartDateTime: 06-JAN-2017 06.01.00
  • EndDateTime: 06-JAN-2017 23.00.00
  • Touched: False

duration = 16hr 59min mustStartTime = 1001 = 0200 - 16 hr 59 min mustEndTime = 2159 = 0500 + 16 hr 59 min touched = false = (0601 >= 1001 && 2300 <= 2159) = (false && false)

5

  • StartDateTime: 06-JAN-2017 03.00.00
  • EndDateTime: 06-JAN-2017 04.00.00
  • Touched: True

duration = 1 hour mustStartTime = 0100 = 0200 - 1 hour mustEndTime = 0700 = 0600 + 1 hour touched = true = (0300 >= 0100 && 0400 <= 0700) = (true && true)

6

  • StartDateTime: 06-JAN-2017 00.00.00
  • EndDateTime: 06-JAN-2017 01.30.00
  • Touched: False

duration = 1hr 30 min mustStartTime = 0030 = 0200 - 1hr 30 min mustEndTime = 0730 = 0600 + 1hr 30 min touched = false = (0000 >= 0030 && 0130 <= 0730) = (false && true)

7

  • StartDateTime: 06-JAN-2017 05.00.00
  • EndDateTime: 06-JAN-2017 06.00.00
  • Touched: True

duration = 1 hour mustStartTime = 0100 = 0200 - 1 hour mustEndTime = 0700 = 0600 + 1 hour touched = (0500 >= 0100 && 0600 <= 0700) = (true && true)

Update

. ! , !

public class OverlappingDateRangeUtil {

    /**
     * 1000 ms * 60 s * 60 m
     */
    public static final long MS_IN_AN_HOUR = 1000 * 60 * 60;

    public static final long MS_IN_TWO_HOURS = 2 * MS_IN_AN_HOUR;

    public static final long MS_IN_SIX_HOURS = 3 * MS_IN_TWO_HOURS;

    public static final long MS_IN_TWENTY_HOURS = 20 * MS_IN_AN_HOUR;

    private static boolean tripLongerThanTwentyHours(long duration) {
        return duration >= MS_IN_TWENTY_HOURS;
    }

    private static long getTruncDateFor0200And0600(Date start) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(start);

        int startHour = cal.get(Calendar.HOUR);

        cal.set(Calendar.HOUR, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        boolean after0600 = startHour >=6 && start.getTime() % 60000 > 0;
        if(after0600) {
            cal.add(Calendar.DATE, 1);
        }
        return cal.getTimeInMillis();
    }

    public static boolean dateRangeTouches0200to0600(Date start, Date end) {
        boolean toReturn = false;
        long duration = end.getTime() - start.getTime();
        if(tripLongerThanTwentyHours(duration)) {
            toReturn = true;
        }
        else {
            long truncTestDate = getTruncDateFor0200And0600(start);
            long oh200 = truncTestDate + MS_IN_TWO_HOURS;
            long oh600 = truncTestDate + MS_IN_SIX_HOURS;
            long mustStart = oh200 - duration;
            long mustEnd = oh600 + duration;
            toReturn = start.getTime() >= mustStart && end.getTime() <= mustEnd;
        }
        return toReturn;
    }
}

public class OverlappingDateRangeUtilTest {

    private DateFormat dateTimeFormat;

    @Before
    public void setUp() throws Exception {
        dateTimeFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
    }

    @Test
    public void testDateRangeTouches0200to0600() throws ParseException {
        Date trip1Start = dateTimeFormat.parse("01/01/2017 00:15:00");
        Date trip1End = dateTimeFormat.parse("01/03/2017 01:45:00");
        assertTrue(OverlappingDateRangeUtil.dateRangeTouches0200to0600(trip1Start, trip1End));

        Date trip2Start = dateTimeFormat.parse("01/04/2017 13:00:00");
        Date trip2End = dateTimeFormat.parse("01/05/2017 13:00:00");
        assertTrue(OverlappingDateRangeUtil.dateRangeTouches0200to0600(trip2Start, trip2End));

        Date trip3Start = dateTimeFormat.parse("01/06/2017 00:00:00");
        Date trip3End = dateTimeFormat.parse("01/06/2017 05:00:00");
        assertTrue(OverlappingDateRangeUtil.dateRangeTouches0200to0600(trip3Start, trip3End));

        Date trip4Start = dateTimeFormat.parse("01/06/2017 06:01:00");
        Date trip4End = dateTimeFormat.parse("01/06/2017 23:00:00");
        assertFalse(OverlappingDateRangeUtil.dateRangeTouches0200to0600(trip4Start, trip4End));

        Date trip5Start = dateTimeFormat.parse("01/06/2017 06:01:00");      
        Date trip5End = dateTimeFormat.parse("01/06/2017 06:01:00");
        assertFalse(OverlappingDateRangeUtil.dateRangeTouches0200to0600(trip5Start, trip5End));

        Date trip6Start = dateTimeFormat.parse("01/06/2017 04:00:00");      
        Date trip6End = dateTimeFormat.parse("01/06/2017 04:00:00");
        assertTrue(OverlappingDateRangeUtil.dateRangeTouches0200to0600(trip6Start, trip6End));

        Date trip7Start = dateTimeFormat.parse("01/06/2017 03:00:00");      
        Date trip7End = dateTimeFormat.parse("01/06/2017 04:00:00");
        assertTrue(OverlappingDateRangeUtil.dateRangeTouches0200to0600(trip7Start, trip7End));

        Date trip8Start = dateTimeFormat.parse("01/06/2017 00:00:00");      
        Date trip8End = dateTimeFormat.parse("01/06/2017 01:30:00");
        assertFalse(OverlappingDateRangeUtil.dateRangeTouches0200to0600(trip8Start, trip8End));
    }

}
0

.

. (DST) . , , Turkey (2016), Russia (2016, 2014, 2011), Venezuela (2016, 2007) .

, , . , DST 23 25 . DST 2 , 2 , . , DST .

, . + .

" ", , . , , . - , 26 , 14 UTC 12 . , , .

0

Source: https://habr.com/ru/post/1668733/


All Articles