Reputation: 4877
i'm trying to solve a seemingly simple problem, but just can't quite get my mind around it.
i have two times startTime
and stopTime
, which can be considered to be in the format: hh:mm:ss
[24hr format].
Now given a third time - timeToTest
- i need to find out if timeToTest
lies between startTime
and stopTime
. There is no date information involved, other than just the times.
So for example - if i have startTime
= '22:30:00'
and stopTime
= '03:30:00'
, then for timeToTest
= '01:14:23'
, the test should return true.
I've tried a solution with java.util.Date
by converting the times to milliseconds using getTime()
, but with any interval which rolls over the 24 hr barrier, the logic fails.
I'm trying to build a solution using Java - but i believe the logic is language independent.
Upvotes: 3
Views: 6296
Reputation: 79075
The java.util
Date-Time API and their formatting API, SimpleDateFormat
are outdated and error-prone. It is recommended to stop using them completely and switch to the modern Date-Time API*.
Also, quoted below is a notice from the home page of Joda-Time:
Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.
Solution using java.time
, the modern Date-Time API:
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
public class Main {
public static void main(String[] args) {
String strStartTime = "22:30:00", strStopTime = "03:30:00", strTestTime = "01:14:23";
LocalDate today = LocalDate.now();
LocalDateTime startTime = today.atTime(LocalTime.parse(strStartTime));
LocalDateTime stopTime = today.atTime(LocalTime.parse(strStopTime));
if (stopTime.isBefore(startTime))
stopTime = stopTime.plusDays(1);
LocalDateTime testTime = today.atTime(LocalTime.parse(strTestTime));
if (testTime.isBefore(startTime))
testTime = testTime.plusDays(1);
if (!testTime.isBefore(startTime) && !testTime.isAfter(stopTime))
System.out.println(strTestTime + " is at or after " + strStartTime + " and is before or at " + strStopTime);
}
}
Output:
01:14:23 is at or after 22:30:00 and is before or at 03:30:00
Note: If the start time and stop time are not inclusive, change the condition as follows:
if (testTime.isAfter(startTime) && testTime.isBefore(stopTime))
System.out.println(strTestTime + " is after " + strStartTime + " and is before " + strStopTime);
Learn more about the modern Date-Time API from Trail: Date Time.
* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.
Upvotes: 2
Reputation: 103
anirvan's solution using JodaTime :
public class TimeInterval24H {
private final LocalTime start;
private final LocalTime end;
public TimeInterval24H(LocalTime start, LocalTime end) {
this.start = start;
this.end = end;
}
public TimeInterval24H(Date start, Date end) {
this(new LocalTime(start), new LocalTime(end));
}
public boolean contains(Date test) {
return contains(new LocalTime(test));
}
public boolean contains(LocalTime test) {
if (isAccrossTwoDays()) {
return (test.isAfter(getStart()) || test.isBefore(getEnd()));
} else {
return (test.isAfter(getStart()) && test.isBefore(getEnd()));
}
}
boolean isAccrossTwoDays() {
return getEnd().isBefore(getStart());
}
public LocalTime getStart() {
return start;
}
public LocalTime getEnd() {
return end;
}
}
Upvotes: 2
Reputation: 882
I strongly recommend java.util.Calendar, the before() and after() can be useful. However, you'll need a date like 5/18/2011 specified together with your time. Is it possible to specify a mock date (or a pair of date in your case) to leverage the Calendar?
Upvotes: 0
Reputation: 4877
So the simplest solution i could come up with, sticking to plain old java.util.Date
, is shown below:
String d1 = "21:00:00";
String d2 = "04:00:00";
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String dToTest = "16:00:00";
boolean isSplit = false, isWithin = false;
Date dt1 = null, dt2 = null, dt3 = null;
dt1 = sdf.parse(d1);
dt2 = sdf.parse(d2);
dt3 = sdf.parse(dToTest);
isSplit = (dt2.compareTo(dt1) < 0);
System.out.println("[split]: " +isSplit);
if (isSplit)
{
isWithin = (dt3.after(dt1) || dt3.before(dt2));
}
else
{
isWithin = (dt3.after(dt1) && dt3.before(dt2));
}
System.out.println("Is time within interval? " +isWithin);
feel free to point out any mistakes - would love to work and fix it.
Upvotes: 5
Reputation: 1500425
How about:
The first step can probably be broken down pretty easily:
All of this is likely to be somewhat easier to write in Joda Time than using java.util.*, by the way :)
Upvotes: 1
Reputation: 328594
You must add a "day" where "0" == current day, "1" == next day and so on. So in fact when stopTime == '03:30:00'
it should be '27:30:00'
(i.e. on the next day).
In your case, if the stopTime < startTime
, then add 86400 seconds.
Upvotes: 2