Sticky Code : Search Nearest Time with Joda Time

Hi Everyone, since couple days ago I was thinking how to find the nearest time without date helper. Okay, let me give you the case. Imagine that you have a work shift, this work shift has a shift start time and shift end time. And then the work shift period maybe has a cross day, meaning that the work shift will be started in the middle of a night and will end on the next day. The parameter which given only plain text time such as 09:00 – 18:00, 22:00 – 07:00. Based on these two parameters (work shift start and work shift end) I have to decide the clocking time whether as IN or OUT status. And the same condition clocking time only contains plain text time such as 07:49, 15:23.

Case Number Shift Period Clocking Time IN / OUT Status
1 08:00 – 17:00 06:59 IN
2 08:00 – 17:00 09:45 IN
3 08:00 – 17:00 16:45 OUT
4 08:00 – 17:00 19:00 OUT
5 22:00 – 04:00 20:59 IN
6 22:00 – 04:00 23:45 IN
7 22:00 – 04:00 02:45 OUT
8 22:00 – 04:00 06:00 OUT

 

Actually, the algorithm to resolve this case is very simple, when clocking time has passed to me I have to compare this clocking time to the work shift start and work shift ends. And if the difference between clocking time vs work shift starts less than clocking time vs work shift end, it would be considered as IN. And if the difference between clocking time vs work shift ends less than clocking time vs work shift start, that means he/she clocking to the attendance machine for OUT purpose.

But the case becomes little bit complex since there is no date helper on the parameter and shift period sometimes has an overnight shift. But don’t worry, Joda Time can resolve this. Let’s have a look at the code below :

public static Period calculationPeriod(String start, String end) {
		DateTimeFormatter formatter = DateTimeFormat.forPattern("HH:mm");
		DateTime startTime = formatter.parseDateTime(start);
		DateTime endTime = formatter.parseDateTime(end);

		Duration duration = null;
		try {
			duration = new Interval(startTime, endTime).toDuration();
		} catch (IllegalArgumentException e) {
			DateTime midNight = formatter.parseDateTime("23:59");

			duration = new Interval(startTime, midNight).toDuration();
			Duration restDuration = new Interval(formatter.parseDateTime("00:00"), endTime.plusMinutes(1)).toDuration();
			duration = duration.plus(restDuration);
		}

		return duration.toPeriod();
	}

This method will try to calculate how many hours and minutes of work shift period. When end-time parameter greater than start-time, the system will throw the Exception. When an exception occurs, the system will try to swift start-time become end-time and vice versa. That means the system will suspect the work shift is an overnight shift.

public static String predictIoStatus(String dutyStart, String dutyEnd, String ioTime) {
		String ioStatus = "";

		// comparison IN
		Period pIn = DateUtils.calculationPeriod(ioTime, dutyStart);
		Period pIn2 = DateUtils.calculationPeriod(dutyStart, ioTime);

		int hourIN  = pIn.getHours() < pIn2.getHours() ? pIn.getHours() : pIn2.getHours();

		// comparison OUT
		Period pOut = DateUtils.calculationPeriod(ioTime, dutyEnd);
		Period pOut2 = DateUtils.calculationPeriod(dutyEnd, ioTime);

		int hourOUT  = pOut.getHours() < pOut2.getHours() ? pOut.getHours() : pOut2.getHours();

		if(hourIN < hourOUT ) {
			ioStatus = "IN";
		} else {
			ioStatus = "OUT";
		}
		return ioStatus;
	}

This method will try to compare the clocking time with the work shift start and work shift ends. As I mentioned above, if difference clocking time vs work shift starts less than clocking time vs work shift end, the system will consider clocking time as IN. Otherwise, the system will consider clocking time as OUT.

Let’s have a look testing result :

public static void main(String[] args) throws Exception {

		String shiftStart1 = "08:00";
		String shiftEnd1 = "17:00";
		String ioTime1 = "06:59";
		String ioStatus1 = predictIoStatus(shiftStart1, shiftEnd1, ioTime1);
		System.out.println("- Case Number 1 : "+ioStatus1);

		String shiftStart2 = "08:00";
		String shiftEnd2 = "17:00";
		String ioTime2 = "09:45";
		String ioStatus2 = predictIoStatus(shiftStart2, shiftEnd2, ioTime2);
		System.out.println("- Case Number 2 : "+ioStatus2);

		String shiftStart3 = "08:00";
		String shiftEnd3 = "17:00";
		String ioTime3 = "16:45";
		String ioStatus3 = predictIoStatus(shiftStart3, shiftEnd3, ioTime3);
		System.out.println("- Case Number 3 : "+ioStatus3);

		String shiftStart4 = "08:00";
		String shiftEnd4 = "17:00";
		String ioTime4 = "19:00";
		String ioStatus4 = predictIoStatus(shiftStart4, shiftEnd4, ioTime4);
		System.out.println("- Case Number 4 : "+ioStatus4);

		String shiftStart5 = "22:00";
		String shiftEnd5 = "04:00";
		String ioTime5 = "20:59";
		String ioStatus5 = predictIoStatus(shiftStart5, shiftEnd5, ioTime5);
		System.out.println("- Case Number 5 : "+ioStatus5);

		String shiftStart6 = "22:00";
		String shiftEnd6 = "04:00";
		String ioTime6 = "23:45";
		String ioStatus6 = predictIoStatus(shiftStart6, shiftEnd6, ioTime6);
		System.out.println("- Case Number 6 : "+ioStatus6);

		String shiftStart7 = "22:00";
		String shiftEnd7 = "04:00";
		String ioTime7 = "02:45";
		String ioStatus7 = predictIoStatus(shiftStart7, shiftEnd7, ioTime7);
		System.out.println("- Case Number 7 : "+ioStatus7);

		String shiftStart8 = "22:00";
		String shiftEnd8 = "04:00";
		String ioTime8 = "06:00";
		String ioStatus8 = predictIoStatus(shiftStart8, shiftEnd8, ioTime8);
		System.out.println("- Case Number 8 : "+ioStatus8);
}
- Case Number 1 : IN
- Case Number 2 : IN
- Case Number 3 : OUT
- Case Number 4 : OUT
- Case Number 5 : IN
- Case Number 6 : IN
- Case Number 7 : OUT
- Case Number 8 : OUT

Leave a Reply