Java: How to check whether given time lies between two times? - java

I want to check whether target time lies between two given times without considering date using Java8 time. Let say if starting time is "21:30" , ending time is "06:30" and target time is "03:00", so program should return true.
#Test
public void posteNuit()
{
DateTimeFormatter format = DateTimeFormatter.ofPattern("HH:mm");
String s = "21:30";
String e = "06:30";
String t = "03:00";
LocalTime startTime = LocalTime.parse(s, format);
LocalTime endTime = LocalTime.parse(e, format);
LocalTime targetTime = LocalTime.parse(t, format);
if ( targetTime.isBefore(endTime) && targetTime.isAfter(startTime) ) {
System.out.println("Yes! night shift.");
} else {
System.out.println("Not! night shift.");
}
}

You've used LocalTime which doesn't store date information, only time.
Then you are trying to check if target time is after start time (03:00 after 21:30). This statement is false.
Your start time should be before end time.
If you need to handle night shift try following:
if (startTime.isAfter(endTime)) {
if (targetTime.isBefore(endTime) || targetTime.isAfter(startTime)) {
System.out.println("Yes! night shift.");
} else {
System.out.println("Not! night shift.");
}
} else {
if (targetTime.isBefore(endTime) && targetTime.isAfter(startTime)) {
System.out.println("Yes! without night shift.");
} else {
System.out.println("Not! without night shift.");
}
}

in your scenario it seems that if startTime > endTime no matter what's targetTime you'll return true.
So update the if statement:
if (( startTime.isAfter(endTime) && targetTime.isBefore(startTime)
&& targetTime.isAfter(endTime) )
|| ( startTime.isBefore(endTime) && targetTime.isBefore(endTime)
&& targetTime.isAfter(startTime) )) {

Related

How to return sum of LocalTime in Java

It wont get the minutes. i need to return minutes.
How to return sum of minutes while iterating over Localtime in Java?
public String userLunchHoursSum(String username) {
List<WorkHour> workHours = workHourRepository.findWorkHoursByUsername(username);
System.out.println(Arrays.toString(workHours.toArray()));
long diff = 0;
LocalTime lunchTime;
long minutes = 0;
LocalTime plusMinutes = null;
for (WorkHour workHour : workHours) {
lunchTime = workHour.getLunch_time().toLocalTime(); //00:30:00
plusMinutes = lunchTime.plusMinutes(lunchTime.getMinute());
}
if(workHours.size()!= 0) {
return Long.toString(plusMinutes.getMinute());
}
return "00:00";
}
getLunch_time returns java.sql.Time.
As mentioned, you should be storing duration instead of localtime. If this is something you have no control over, consider migrating the database or creating a intermediate parsing function. Example code that I have not run, because I don't know what is in WorkHour.
// leave the string formatting to other functions
public long userLunchHoursSum(String username) {
List<WorkHour> workHours = workHourRepository.findWorkHoursByUsername(username);
Duration totalDuration = Duration.ZERO;
for (WorkHour workHour : workHours) {
// save your time in the appropriate format beforehand
// do not use local time to store duration.
Duration lunchTime = Duration.between(LocalTime.MIDNIGHT, workHour.getLunch_time().toLocalTime()); //00:30:00
totalDuration = totalDuration.plus(lunchTime);
}
return totalDuration.toMinutes();
}

Check if 1st timepicker earlier than 2nd timepicker

I have 2 timepicker which represent start and finish. It means the start time must be earlier than the finish.
My idea is to use Calendar class and use getTimeInMillis to do the validation, but its not working :
Calendar calFrom = Calendar.getInstance();
Calendar calTo = Calendar.getInstance();
calFrom.set(Calendar.HOUR_OF_DAY, timeSchedule.getCurrentHour());
calFrom.set(Calendar.MINUTE, timeSchedule.getCurrentMinute());
calTo.set(Calendar.HOUR_OF_DAY, toTime.getCurrentHour());
calTo.set(Calendar.MINUTE, toTime.getCurrentMinute());
if(calFrom.getTimeInMillis() > calTo.getTimeInMillis())
{
Crouton.makeText(MyActivity.this, "error", Style.ALERT).show();
}
When i debug the above code, although the timeSchedule is earlier then toTime, the value of calFrom.getTimeInMillis() is bigger than calTo.getTimeInMillis().
Please kindly help me, Thanks for your time.
int fromHour = calFrom.getCurrentHour();
int toHour = calTo.getCurrentHour();
int fromMin = calFrom.getCurrentMinute();
int toMin= calTo.getCurrentMinute();
if (fromHour >toHour )
{
System.out.println ("from time is greater");
}
else if (fromHour==toHour)
{
if (fromMin>toMin)
{
System.out.println ("from time is greater");
}
else
{
System.out.println ("To time is greater");
}
}
else
{
System.out.println ("To time is greater");
}

Implementing Instagram-like time formatting with Joda-Time

If there isn't an easy way currently, I'll just build out the functionality, but I'm new to Joda-Time and was wondering if there is a simple way to do this:
Basically, you have a time in ISO8601 format, and you create a new DateTime(time); using Joda-Time.
Now, if the time was 5 seconds ago, I'd like it to read "5s", if it was 10 minutes ago, "10m", 17 hours ago, "17h", 3 weeks ago, "3w".
Clearly, if something was written 79 seconds ago, it realizes that this is more than 1 minute, and instead opts to check this in minutes, and instead says "1m" instead of "79s".
Update:
So far, my quick solution is this:
public void setTimestamp() {
DateTime now = DateTime.now();
if (DateTimeComparator.getInstance().compare(timeCreated, now.minusSeconds(1)) == 1) {
timestamp = "1s";
} else if (DateTimeComparator.getInstance().compare(timeCreated, now.minusMinutes(1)) == 1) {
timestamp = Seconds.secondsBetween(timeCreated, now).getSeconds() + "s";
} else if (DateTimeComparator.getInstance().compare(timeCreated, now.minusHours(1)) == 1) {
timestamp = Minutes.minutesBetween(timeCreated, now).getMinutes() + "m";
} else if (DateTimeComparator.getInstance().compare(timeCreated, now.minusDays(1)) == 1) {
timestamp = Hours.hoursBetween(timeCreated, now).getHours() + "h";
} else if (DateTimeComparator.getInstance().compare(timeCreated, now.minusWeeks(1)) == 1) {
timestamp = Days.daysBetween(timeCreated, now).getDays() + "d";
} else if (DateTimeComparator.getInstance().compare(timeCreated, now.minusYears(1)) == 1) {
timestamp = Weeks.weeksBetween(timeCreated, now).getWeeks() + "w";
} else {
timestamp = Years.yearsBetween(timeCreated, now).getYears() + "y";
}
}
It still requires some testing, but from first looks, it seems to work.

How to validate Hour and Minutes that came from a Swing textBox?

I have a window that contains a HH:mm time TextField in it, in 24 hours format
I need to validate if the user entered any non valid hour, like 28:00, 99:00, 24:01.
What's the best and simpler way to do that ?
some code below of what is currently doing that job wrong and giving errors in date parsed.
Today I get an random hour and an user hit 99:99 in that text field.
This code is not mine, but I gotta fix it.
I am stuck with it, tried to validate as a String is useless, and I cannot find a nice way to make it a Date without having to put year, month, etc... too.
Please forget about the return -1 instead of throwing an exception this is old code and this cannot be changed.
to help understand :
Statics.hF2 = SimpleDateFormat (HH:mm)
this.cmpHora.getText() = Is the field with the value
Statics.df_ddmmyy = Another date format
Statics.m2ms = converts minutes to milliseconds
//CODE
public long getDataEmLong ()
{
try
{
Calendar hour= Calendar.getInstance();
new GregorianCalendar().
hour.setTime( Statics.hF2.parse( this.cmpHora.getText() ) );
return Statics.df_ddmmyy.parse( this.cmpData.getText() ).getTime() + Statics.m2ms( hour.get( Calendar.HOUR_OF_DAY ) * 60 ) + Statics.m2ms( hour.get( Calendar.MINUTE ) );
} catch ( Exception e )
{
e.printStackTrace();
return -1;
}
}
Cheers !
Regular expressions to the rescue:
public boolean validTime24(String time) {
return time.matches("^([01]\d|2[0-3]):[0-5]\d$")
}
This will validate the format of the string. Then you can parse out the time from there.
Insert this in your class, and perform the validateTime method from inside your junk code.
public boolean validateTime(String timeString) {
if (timeString.length() != 5) return false;
if (!timeString.substring(2, 3).equals(":")) return false;
int hour = validateNumber(timeString.substring(0, 2));
int minute = validateNumber(timeString.substring(3));
if (hour < 0 || hour >= 24) return false;
if (minute < 0 || minute >= 60) return false;
return true;
}
public int validateNumber(String numberString) {
try {
int number = Integer.valueOf(numberString);
return number;
} catch (NumberFormatException e) {
return -1;
}
}
You can use JFormattedTextField with proper Date or Time Format set. The field will return you proper values.
Since Java 8 you can use DateTimeFormatter:
public boolean validate(String time) {
try {
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm");
timeFormatter.parse(time);
return true;
} catch (DateTimeParseException e) {
return false;
}
}

StackOverflowError using joda-time new Period(long)

First, sorry this is so long. I probably don't need all the code, but wanted to be sure.
Second, my actual question is, am I doing something wrong, or is this a bug in the joda-time library?
I'm trying to use joda-time (1.6.1) to calculate, then format time durations.
I'm currently using Period, which may be the wrong choice. Please let me know if it is.
However, even if it is the wrong choice, I'm pretty sure this shouldn't happening.
I'm initialising a Period using milliseconds (by multiplying a duration in seconds by 1000). I'm using the Period so I can then format it and print it:
long durationLong = durationSec * 1000;
Period duration = new Period(durationLong);
PeriodFormatter daysHoursMinutes = new PeriodFormatterBuilder()
.appendHours()
.appendSeparator(":")
.appendMinutes()
.appendSeparator(":")
.appendSeconds()
.toFormatter();
String formattedString = daysHoursMinutes.print(callDuration.normalizedStandard());
I get the Exception below, and have looked through the source to confirm the loop.
Caused by: java.lang.StackOverflowError
at java.util.Hashtable.get(Hashtable.java:274)
at java.util.Properties.getProperty(Properties.java:177)
at java.lang.System.getProperty(System.java:440)
at java.lang.System.getProperty(System.java:412)
at org.joda.time.DateTimeZone.getDefault(DateTimeZone.java:132)
at org.joda.time.DateTimeZone.forID(DateTimeZone.java:190)
at org.joda.time.DateTimeZone.getDefault(DateTimeZone.java:132)
at org.joda.time.DateTimeZone.forID(DateTimeZone.java:190)
...snip (all the same)...
at org.joda.time.DateTimeZone.getDefault(DateTimeZone.java:132)
at org.joda.time.DateTimeZone.forID(DateTimeZone.java:190)
at org.joda.time.DateTimeZone.getDefault(DateTimeZone.java:132)
at org.joda.time.DateTimeZone.forID(Dat
Period(long):
public Period(long duration) {
super(duration, null, null);
}
super(long, PeriodType, Chronology):
protected BasePeriod(long duration, PeriodType type, Chronology chrono) {
super();
type = checkPeriodType(type);
chrono = DateTimeUtils.getChronology(chrono);
iType = type;
iValues = chrono.get(this, duration);
}
DateTimeUtils.getChronology(chrono):
public static final Chronology getChronology(Chronology chrono) {
if (chrono == null) {
return ISOChronology.getInstance();
}
return chrono;
}
ISOChronology.getInstance():
public static ISOChronology getInstance() {
return getInstance(DateTimeZone.getDefault());
}
DateTimeZone.getDefault():
public static DateTimeZone getDefault() {
DateTimeZone zone = cDefault;
if (zone == null) {
synchronized(DateTimeZone.class) {
zone = cDefault;
if (zone == null) {
DateTimeZone temp = null;
try {
try {
temp = forID(System.getProperty("user.timezone"));
} catch (RuntimeException ex) {
// ignored
}
if (temp == null) {
temp = forTimeZone(TimeZone.getDefault());
}
} catch (IllegalArgumentException ex) {
// ignored
}
if (temp == null) {
temp = UTC;
}
cDefault = zone = temp;
}
}
}
return zone;
}
forID(String) calls getDefault(), which creates the loop:
public static DateTimeZone forID(String id) {
if (id == null) {
return getDefault();
}
if (id.equals("UTC")) {
return DateTimeZone.UTC;
}
DateTimeZone zone = cProvider.getZone(id);
if (zone != null) {
return zone;
}
if (id.startsWith("+") || id.startsWith("-")) {
int offset = parseOffset(id);
if (offset == 0L) {
return DateTimeZone.UTC;
} else {
id = printOffset(offset);
return fixedOffsetZone(id, offset);
}
}
throw new IllegalArgumentException("The datetime zone id is not recognised: " + id);
}
As the looping part is only in the joda code, I would say that's a bug.
It has been corrected on the trunk and will be available in V2.0.
Resources :
The reported bug
Looks like it's a bug in that it assumes the user.timezone property will have been set.
That's the way to get round it in this case - just make sure that user.timezone is set appropriately. It's a shame that you have to though.
Joda Time uses "null means default" in a lot of places - unfortunately, in my view. I prefer "null is invalid" usually. In Noda Time (a port of Joda Time to .NET) we're trying to get rid of a lot of this kind of thing - as well as preventing the default time zone from being as prevalent in the first place.

Categories

Resources