I had previously created a question about this but I am still having problems.
I want to create a cooldown for player challenges. Currently there are two types of cooldowns, DAILY and WEEKLY.
The Daily cooldown lasts from the time the challenge is completed until 23:59 of the day, that is if you complete it at 14:00 you would have to wait 9 hours for the challenge to be enabled again.
The weekly cooldown is the same but the challenge is enabled until Thursday night, then the remaining time would be until Thursday night
So I want to get the hours, minutes and seconds until the cooldown ends but I can't get it right, I get giant numbers or it just doesn't work. I have never worked with dates and times, this would be my first time.
When a challenge is completed I store the date and time it was completed, something like this: 10-12-2021 and 20:33:58. Then I get them in the code to calculate the remaining time but when I get the String I get "-1" something like: 7d 10623m 637385s or 1d 2753m 1935s
My code for Daily:
public String getDailyCountdown(UUID uuid, Quest quest) {
QuestProperties questProperties = plugin.getQuestsCache().get(uuid, quest);
String countdownTimePlaceholder = "";
String[] completionDate = questProperties.getCompletionDate().split("-"), completionTime = questProperties.getCompletionTime().split(":");
int completionDay = Integer.parseInt(completionDate[0]), completionMonth = Integer.parseInt(completionDate[1]), completionYear = Integer.parseInt(completionDate[2]);
int completionHour = Integer.parseInt(completionTime[0]), completionMinutes = Integer.parseInt(completionTime[1]), completionSeconds = Integer.parseInt(completionTime[2]);
LocalDateTime fromDateTime = LocalDateTime.of(completionYear, completionMonth, completionDay, completionHour, completionMinutes, completionSeconds);
LocalDateTime toDateTime = LocalDateTime.of(2021, 11, 25, 23, 59, 0);
long current = System.currentTimeMillis();
long durationMillis = Duration.between(fromDateTime, toDateTime).toMillis();
Duration duration = Duration.between(fromDateTime, toDateTime);
long s = duration.getSeconds();
long s2 = s * 1000L;
long waitingTime = current - durationMillis;
long div = waitingTime / 1000L;
long waitingSeconds = s - div, waitingMinutes = waitingSeconds / 60L, waitingTimeHours = waitingMinutes / 60L;
if (durationMillis + s2 > current && durationMillis != 0L) {
if (waitingMinutes > 59L) waitingMinutes -= 60L * waitingTimeHours;
if (waitingMinutes > 0L) countdownTimePlaceholder = waitingMinutes + "m" + countdownTimePlaceholder;
if (waitingTimeHours > 0L) countdownTimePlaceholder = waitingTimeHours + "h" + countdownTimePlaceholder;
return countdownTimePlaceholder;
}
return "-1";
}
My code for Weekly:
QuestProperties questProperties = plugin.getQuestsCache().get(uuid, quest);
String countdownTimePlaceholder;
String[] completionDate = questProperties.getCompletionDate().split("-"), completionTime = questProperties.getCompletionTime().split(":");
int completionDay = Integer.parseInt(completionDate[0]), completionMonth = Integer.parseInt(completionDate[1]), completionYear = Integer.parseInt(completionDate[2]);
int completionHour = Integer.parseInt(completionTime[0]), completionMinutes = Integer.parseInt(completionTime[1]), completionSeconds = Integer.parseInt(completionTime[2]);
LocalDateTime fromDateTime = LocalDateTime.of(completionYear, completionMonth, completionDay, completionHour, completionMinutes, completionSeconds);
LocalDateTime toDateTime = LocalDateTime.now().plusDays(7);
LocalDateTime localDateTime = LocalDateTime.from(fromDateTime);
long days = localDateTime.until(toDateTime, ChronoUnit.DAYS);
long minutes = localDateTime.until(toDateTime, ChronoUnit.MINUTES);
long seconds = localDateTime.until(toDateTime, ChronoUnit.SECONDS);
countdownTimePlaceholder = days + "d" + minutes + "m" + seconds + "s";
return countdownTimePlaceholder;
How could I do it better or make it get the remaining time correctly?
Regards.
Date-time handling is tricky
You said:
I have never worked with dates and times, this would be my first time.
Date-time handling is surprisingly difficult and confusing. Be patient, study well, and run experiments.
Search Stack Overflow, as your issues have already been addressed many times. I’ll try to be brief here. Search to learn more and see more code examples.
Store date-time objects
As commented by Boris The Spider, use java.time to store your date-time values rather than repeatedly parsing their textual representation.
Or is QuestProperties outside your control?
If outside your control, at least simplify your parsing code. Change this:
int completionDay = Integer.parseInt(completionDate[0]), completionMonth = Integer.parseInt(completionDate[1]), completionYear = Integer.parseInt(completionDate[2]);
int completionHour = Integer.parseInt(completionTime[0]), completionMinutes = Integer.parseInt(completionTime[1]), completionSeconds = Integer.parseInt(completionTime[2]);
… to this:
LocalDate ld = LocalDate.of( Integer.parseInt(completionDate[2]) , Integer.parseInt(completionDate[1]) , Integer.parseInt(completionDate[0]) ) ; // year, month, day.
LocalTime lt = LocalTime.of( Integer.parseInt(completionTime[0]) , Integer.parseInt(completionTime[1]) , Integer.parseInt(completionTime[2]) ) ; // hour, minute, second.
Half-Open
Spans of time are usually best handled using Half-Open approach. In Half-Open, the beginning is inclusive while the ending is exclusive. So a day starts at the first moment of the day and runs up to, but does not include, the first moment of the following day.
Your code LocalDateTime.of(2021, 11, 25, 23, 59, 0) fails to account for the last full minute of the day, the minute between 23:59:00 and 00:00:00.
Change to:
LocalDateTime toDateTime = fromDateTime.toLocalDate().plusDays( 1 ).atStartOfDay() ;
Time zone
Your biggest problem is that you are ignoring the crucial issue of time zone. Getting the date, and determining the first moment of the day time, requires a time zone.
A day ends much earlier in the east than in the west. For example, at some moments, the date can be “tomorrow” in Tokyo Japan 🇯🇵 while simultaneously still “yesterday” in Edmonton Canada 🇨🇦.
So if you want to run your cooldowns to the end of the day as seen by the user, then you must account for the user’s time zone. You can query for their current default time zone. But ultimately best to confirm with the user.
ZoneId z = ZoneId.of( "America/Edmonton" ) ;
Capture the current moment as seen in that zone.
ZonedDateTime zdtNow = ZonedDateTime.now( z );
The LocalDateTime is the wrong class for your needs. That class represents a date and a time-of-day but lacks the context of a time zone or offset-from-UTC. We used ZonedDateTime to represent the current moment with a date, a time-of-day, and a time zone.
LocalDateTime = 🗓 + 🕛
ZonedDateTime = 🗓 + 🕛 + 🗺
Get the first moment of the next day. Notice how we ask java.time to determine when the day starts on that date in that zone. Do not assume a day starts at 00:00:00. Days may start at other times.
ZonedDateTime zdtStartOfTomorrow = zdtNow.toLocalDate().plusDays( 1 ).atStartOfDay( z ) ;
Time to elapse
If needed, calculate time to elapse.
Duration d = Duration.between( zdtNow , zdtStartOfTomorrow ) ;
Compare later moments to see if the deadline has passed.
if( ZonedDateTime.now( z ).isAfter( zdtStartOfTomorrow ) ) { … cooldown ended … }
Retrieving moment in UTC
In your case we do not want the current moment. We want to retrieve the user’s moment of last activity from your Quest system.
We parsed need date and the time above, in earlier part of this Answer. But your code did not account for retrieving the time zone. So I will assume the retrieved date and time are as seen « in UTC », with an offset of zero hours-minutes-seconds.
OffsetDateTime odt = OffsetDateTime.of( ld , lt , ZoneOffset.UTC ) ;
Adjust that to the user’s desired time zone.
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;
Capturing the current moment
You asked:
When a challenge is completed I store the date and time it was completed, something like this: 10-12-2021 and 20:33:58.
ZonedDateTime zdt = ZonedDateTime.now( z ) ;
To generate text representing that moment for data exchange, call toString. For text to present to user, let DateTimeFormatter class automatically localize. Both cases have been covered many times already on Stack Overflow.
Related
First time post - I'm newer to java/JavaFx
I'm trying to get my code to save in 15 min incrementalist. The project has an Observable List that houses selectable appointment times.
ApptAddController.java
private final ObservableList<String> times = FXCollections.observableArrayList("8:00 AM", "9:00 AM", "10:00 AM", "11:00 AM", "12:00 PM", "1:00 PM", "2:00 PM", "3:00 PM", "4:00 PM");
ApptDB.Java
The "times" selected goes to the "saveAppt" method
public static boolean saveAppt(int id, String type, String contact, String location, String date, String time) {
//Time stamp for booking times
String tsStart = createTimeStamp(date, time, location, true);
String tsEnd = createTimeStamp(date, time, location, false);
try {
//get date for Appointment createDate
DateTimeFormatter dt = DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss");
String nowString = LocalDateTime.now(Clock.systemUTC()).format(dt);
Statement statement = DBConnection.getConnection().createStatement();
//Query
String queryInsertOne = "INSERT INTO appointment(customerId, type, contact, location, start, end, createDate, lastUpdateBy, createdBy) values ('" + id + "', '" + type + "', '" + contact + "', '" + location + "','" + tsStart + "','" + tsEnd + "','" + nowString + "','" + UserDB.getCurrentUser() + "','" + UserDB.getCurrentUser() + "')";
int updateOne = statement.executeUpdate(queryInsertOne);
return true;
} catch (SQLException e) {
System.out.println("SQLException: " + e.getMessage());
}
return false;
}
The createTimeStamp method is hard coded in the following method with the "00":
public static String createTimeStamp(String date, String time, String location, boolean startMode) {
String t = time.split(":")[0];
int baseH = Integer.parseInt(t);
if(baseH < 8) {
baseH += 12;
}
if(!startMode) {
baseH += 1;
}
String baseD = String.format("%s %02d:%s", date, baseH, "00");
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd kk:mm");
LocalDateTime ldt = LocalDateTime.parse(baseD, dtf);
ZoneId zid;
zid = TimeZone.getDefault().toZoneId();
ZonedDateTime zdt = ldt.atZone(zid);
ZonedDateTime utcDate = zdt.withZoneSameInstant(ZoneId.of("UTC"));
ldt = utcDate.toLocalDateTime();
Timestamp ts = Timestamp.valueOf(ldt);
return ts.toString();
}
Id like to have the appointments be 15 min incrementals. The user will select times at random (8:00, 8:15, 8:30, 8:45). How do I get this code to detect what the user selects and puts int in the database accordingly. If I change "00" to "15" it will hard code every appt for 15 after.
Thanks for your time.
I am not able to follow your code well. So here's some general advice. I should say up front, managing appointments and schedules is a surprisingly complicated problem domain.
You seem to be focused on strings rather than appropriate data types, a common issue with new programmers. Learn to use smart objects, not dumb strings. Notice that none of the code shown below involves strings, except for presentation to users. Values are exchanged with the database as objects, without the use of strings.
Java offers an industry-leading assortment of date-time classes, in the java.time packages. So use them. LocalTime represents a time-of-day. LocalDate represents a date-only, without time-of-day, and without time zone.
For data-entry on the time of appointment, you should be collecting an hour and a minute. Work internally with 24-hour clock LocalTime objects.
List< LocalTime > hourTimes =
List.of(
LocalTime.of( 8 , 0 ) ,
LocalTime.of( 9 , 0 ) ,
LocalTime.of( 10 , 0 ) ,
LocalTime.of( 11 , 0 ) ,
LocalTime.of( 12 , 0 ) ,
LocalTime.of( 13 , 0 ) ,
LocalTime.of( 14 , 0 ) ,
LocalTime.of( 15 , 0 ) ,
LocalTime.of( 16 , 0 )
)
;
If your audience expects a 12-hour clock, present their display with a custom formatter. If your audience expects a 12-hour clock, present their display with a custom formatter.
Locale locale = Locale.US ;
DateTimeFormatter formatterHourOfDay = DateTimeFormatter.ofPattern ( "h a" ).withLocale ( locale ) ;
String output = hourTimes.get( 7 ).format( formatterHourOfDay ) ;
See similar code run live at IdeOne.com.
3 PM
Note that java.time uses immutable objects. So you can freely use the LocalTime object directly from the master list with no need to copy, no need to worry about its values being changed out from under your feet. This also means you can use java.time objects across threads, as they are designed to be thread-safe.
Keep a list of the possible minutes.
List< Integer > minutes = List.of( 0 , 15 , 30 , 45 ) ;
In you user-interface, let the use pick one of those four values, to be mated with their choice from hourTimes above.
Put these values together for your time-of-day to make a new LocalTime.
LocalTime localTime = hourTimes.get( 7 ).plusMinutes( minutes.get( 2 ) ) ; // Adding 0, 15, 30, or 45 minutes to the on-the-hour `LocalTime` object, resulting in another `LocalTime` object.
Combine the time-of-day with your intended date to get a LocalDateTime object.
LocalDate localDate = LocalDate.of( 2020 , Month.JANUARY , 23 ) ;
LocalDateTime localDateTime = LocalDateTime.of( localDate , localTime ) ;
Store that in a database column of SQL-standard type TIMESTAMP WITHOUT TIME ZONE. (that was "WITHOUT", not "WITH")
Generally best to use prepared statements in SQL rather than string-combining.
myPreparedStatement.setObject( … , localDateTime ) ;
In addition, record the intended time zone for that appointment. There is a data type in Java for this, ZoneId. But not in SQL. So record the zone name as text in your database.
ZoneId z = ZoneId.of( "America/Montreal" ) ;
…
myPreparedStatement.setObject( … , z.toString() ) ; // Record name of zone as text.
By the way, no need to pass when the record was created or last updated. You should be configuring your database to set those value automatically on the server-side.
Separate your business logic from your user-interface. Notice that none of my code above relates to JavaFX.
Define a class just for the appointment. This class should know only the needs of an appointment, the business rules for what defines a valid appointment. This class should know nothing about the database, nor the user-interface.
I do not understand what you are trying to do with time zones in your use of ZonedDateTime. It seems you are trying to form a java.sql.Timestamp object. That is the wrong way to go for two reasons. First, that class is one of the terrible legacy date-time classes supplanted by java.time; never use it. Second, that is the wrong way to book appointments. Future appointments should be recorded as two separate parts, (a) date-with-time-of-day and (b) time zone.
Politicians around the world have shown a penchant for frequently changing the offset of the time zones under their jurisdiction. They do so with little, or even no, forewarning. So if you booked 3:45 PM for next January as a moment, as a specific point on the timeline, the time-of-day for that zone's wall-clock time might be changed by then, with 3:45 PM becoming 3:15 PM or 4:45 PM. Imagine if your software booked an appointment for the specific moment that was 3:45 PM before the zone changed its offset-from-UTC. The customers keeping their appointments will be appearing at 3 PM on the current wall-clock time while your appointment book software will show them as early (or late). To avoid this problem, do not schedule appointments as a moment, keep the date-with-time-of-day (LocalDateTime) separated from the time zone (ZoneId).
Combine the two (date-with-time-of-day & time zone) only when building out a schedule where you need specific moments.
ZoneId z = ZoneId.of( zoneNameFromDatabase ) ;
ZonedDateTime zdt = localDateTimeFromDatabase.atZone( z ) ;
If you need to see that moment in UTC, adjust by extracting a Instant object.
Instant instant = zdt.toInstant() ;
But do not store either the ZonedDateTime or Instant for the future. Store them only after the fact, when recording history. And even then, you record OffsetDateTime, as oddly the JDBC spec does not require support for ZonedDateTime or Instant. You would store that OffsetDateTime object in a column of SQL-standard type TIMESTAMP WITH TIME ZONE ("WITH", not "WITHOUT" as seen above).
OffsetDateTime odt = zdt.toOffsetDateTime() ;
myPreparedStatement.setObject( … , odt ) ; // Record history as a moment, a specific point on the timeline.
If I understand correctly, you can and should put LocalTime objects in your ObservableList. Rather than String objects. If so, do that.
Also use SQL datatype time for the times in your database (they may already be, I didn't notice this information in your question). Pass the LocalTime object to your database using a PrepatedStatement. For example:
yourPreparedStatement.setObject(5, startLocalTime);
yourPreparedStatement.setObject(6, endLocalTime);
Do similarly for date, etc., only using the appropriate types both on the Java and the SQL side.
To calculate end time as 15 minutes after start time:
LocalTime endLocalTime = startLocalTime.plusMinutes(15);
I know I am not giving you complete code, but I hope it will get you a step or two further.
I have a date that I want to increase by 15 minutes while a certain condition is met. My problem is that it adds up to 15 minutes just once.
The output per screen would be similar to this operation but with dates.
int i = 10;
while (i <= 100){
i = i + 15;
System.out.println(i);
}
Screen output
10
25
40
55
70
85
100
My code for the dates is the following
while(hour < hourEnd){
hour = new Date();
hour = date.getDate();
Calendar cal = Calendar.getInstance();
cal.setTime(hour);
cal.add(Calendar.MINUTE, 15);
hour = cal.getTime();
}
My problem is that it adds up to 15 minutes just once.
you'll need to create the Date before the loop begins.Otherwise, it will create a new Date at each iteration.
hour = new Date();
Calendar cal = Calendar.getInstance();
while(hour < hourEnd){
cal.setTime(hour);
cal.add(Calendar.MINUTE, 15);
hour = cal.getTime();
}
Avoid legacy classes
Avoid the old legacy date-time classes such as Date and Calendar. They are poorly designed, confusing, and flawed. The java.time framework was added to Java to replace those old classes.
Using java.time
Get the current moment for you desired time zone.
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdtNow = ZonedDateTime.now( z );
Apparently you want to add increments of 15 minutes until reaching the end of the clock hour. Better to think of such spans of time in the Half-Open approach where the beginning is inclusive but the ending is exclusive. That would mean we want to run up to but not including the first moment of the next hour.
ZonedDateTime zdtNextHourStart = zdtNow.plusHours( 1 ).truncatedTo( ChronoUnit.HOURS ) ;
Now loop to increment.
ZonedDateTime zdt = zdtNow ;
List<ZonedDateTime> zdts = new ArrayList<>( 4 );
while( zdt.isBefore( zdtNextHourStart ) ) {
zdts.add( zdt );
System.out.println( zdt );
// Prepare for next loop.
zdt = zdt.plusMinutes( 15 );
}
I'm trying to create a simple Alarm Clock, but I stumbled upon a problem that I can't seem to fix. I'm trying to parse a string to a date so I can get the difference between the current time and the time to set off the alarm.
Here's my code to parse the time:
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
sdf.setTimeZone(getTimezone());
Date date = sdf.parse(args[0]);
Here's my getTimezone() method:
public static TimeZone getTimezone() {
Calendar cal = Calendar.getInstance();
long milliDiff = cal.get(Calendar.ZONE_OFFSET);
String [] ids = TimeZone.getAvailableIDs();
String name = null;
for (String id : ids) {
TimeZone tz = TimeZone.getTimeZone(id);
if (tz.getRawOffset() == milliDiff) {
// Found a match.
name = id;
break;
}
}
return TimeZone.getTimeZone(name);
}
And here's my code for figuring out the difference:
long diff = date.getTime() - System.currentTimeMillis();
So my problem is that the date.getTime() returns 79680000, while System.currentTimeMillis() returns 1473538047978 (This is of course different every time, but for some odd reason, date.getTime() is not).
Which means that I get a negative number when trying to figure out the difference, and therefore I cannot use it.
EDIT: After a little bit of debugging, I realised that it has to do with the year, month and day not being set, however I do not know how to get those.
You did notice that date.getTime() returns 79680000 which is 22 hours and 20 minutes after 1 January 1970. The problem is (as you noticed) that you did not parse year, month and day.
You can do it by:
SimpleDateFormat sdf = new SimpleDateFormat("DD/MM/YYYY hh:mm:ss");
Example input 20/04/2016 20:20:0 returns time as Mon Jan 04 20:20:00 CET 2016 (don't look at the timezone). It is 1451935200000 miliseconds after 1 January 1970.
Note: change string to match your format requirements (the syntax is self-explanatory).
The accepted answer by Ronin is correct. You are trying to put a time-of-day value into a date-time type.
java.time
Also, you are using troublesome old legacy date-time classes. Now supplanted by the java.time classes.
For a time-of-day value without a date and without a time zone, use LocalTime.
LocalTime alarmTime = LocalTime.parse( "12:34" );
Getting current time-of-day requires a time zone.
ZoneId z = ZoneId.of( "America/Montreal" );
LocalTime now = LocalTime.now( z );
But since we are setting an alarm, we care about the date too.
ZonedDateTime now = ZonedDateTime.now( z );
ZonedDateTime alarm = null;
if ( now.toLocalTime().isBefore( alarmTime ) ) {
alarm = ZonedDateTime.of( now.toLocalDate() , alarmTime , z );
} else {. // Else too late for today, so set alarm for tomorrow.
alarm = ZonedDateTime.of( now.toLocalDate().plusDays( 1 ) , alarmTime , z );
}
To calculate the elapsed time until the alarm, use the Duration class.
Duration untilAlarm = Duration.between( now , alarm );
You can interrogate the duration for a total number of milliseconds. But know that java.time classes are capable of handling nanoseconds.
long millis = untilAlarm.toMillis();
Updated.
You are using only time without a date with you date object in code (parses only time). If you add there date to you time, your date should be comparable to your System.getCurrentTimeMillis() call. And if you subtracting current millis from date in the past, you will have negative numbers. I prefer this convertion (date2 is after date1):
long diffInMillies = date2.getTime() - date1.getTime();
return TimeUnit.convert(diffInMillies, TimeUnit.MILLISECONDS);
If we leave Frankfurt at 14:05 and arrives in Los Angeles at 16:40. How long is the flight?
I tried the below :
ZoneId frank = ZoneId.of("Europe/Berlin");
ZoneId los = ZoneId.of("America/Los_Angeles");
LocalDateTime dateTime = LocalDateTime.of(2015, 02, 20, 14, 05);
LocalDateTime dateTime2 = LocalDateTime.of(2015, 02, 20, 16, 40);
ZonedDateTime berlinDateTime = ZonedDateTime.of(dateTime, frank);
ZonedDateTime losDateTime2 = ZonedDateTime.of(dateTime2, los);
int offsetInSeconds = berlinDateTime.getOffset().getTotalSeconds();
int offsetInSeconds2 = losDateTime2.getOffset().getTotalSeconds();
Duration duration = Duration.ofSeconds(offsetInSeconds - offsetInSeconds2);
System.out.println(duration);
But I am not able to get the successful answer which is about 11hrs and 30min. Will some one please help me to figure out the problem above. Thanks you :)
getOffset is the wrong method. That gets the UTC offset for that zone at that point in time. It doesn't help determine the actual time of day.
One way is to explicitly get the Instant represented by each value, using toInstant. Then use Duration.between to calculate the amount of time elapsed.
Instant departingInstant = berlinDateTime.toInstant();
Instant arrivingInstant = losDateTime2.toInstant();
Duration duration = Duration.between(departingInstant, arrivingInstant);
Alternatively, since Duration.between works on Temporal objects, and both Instant and ZonedDateTime implement Temporal, you can just call Duration.between directly on the ZonedDateTime objects:
Duration duration = Duration.between(berlinDateTime, losDateTime2);
And lastly, there are shortcuts like the one atao mentioned that are fine if you want to get directly at a unit of measure such as total seconds. Any of these are acceptable.
Replace:
int offsetInSeconds = berlinDateTime.getOffset().getTotalSeconds();
int offsetInSeconds2 = losDateTime2.getOffset().getTotalSeconds();
Duration duration = Duration.ofSeconds(offsetInSeconds - offsetInSeconds2);
with:
long seconds = ChronoUnit.SECONDS.between(berlinDateTime, losDateTime2);
Duration duration = Duration.ofSeconds(seconds);
EDIT
I like the shorter (and shortest) answer given by Matt Johnson:
Duration duration = Duration.between(berlinDateTime, losDateTime2);
I have some time Strings such as "09:00" and "17:30" and I need to check if the current time is between that range.
I thought I could make this comparison:
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
Date now = new Date();
Date begin;
Date end;
begin = format.parse(begin_string);
end = format.parse(end_string);
if (now.compareTo(begin) > 0 && end.compareTo(now) > 0)
return true;
else
return false;
Turns out that when I parse the strings, the times are parsed correctly, but the date is set to Jan 1st 1970. This way, the code will always return false.
I'd like to know how can I set begin and end to the current date, but with the times from their strings.
You could also just reuse your format object for current time like this way:
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
Date now = new Date();
String time = format.format(now); // format to wall time loosing current date
System.out.println(time);
now = format.parse(time); // reparse wall time
System.out.println(now);
So you transform now to 1970 using implicitly the standard time zone of your system and can then use it for direct comparisons with begin and end.
Date begin = format.parse("09:00");
Date end = format.parse("21:30");
return (begin.before(now) && end.after(now)); // open-bounded interval
Get current time, Calendar.getInstance();
Get another 2 instance of current time, and set time fields based on your input
For example:
Calendar.set(Calendar.HOUR_OF_DAY, 1);
and invoke compare() on the boundry of time
You should really use a Calendar. Then you can individually set the hours and minutes from values parsed from the string. Then get the time in milliseconds and compare those.
Date now = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(now);
cal.set(Calendar.HOUR_OF_DAY, hours);
cal.set(Calendar.MINUTE, minutes);
long time = cal.getTimeInMillis();
You could also use the wonderful Joda library. In my opinion Joda is a much better way to work with Dates and Times.
The bundled java.util.Date & .Calendar classes are notoriously troublesome. Avoid them. Use either Joda-Time library or the new java.time package found in Java 8 (inspired by Joda-Time, defined by JSR 310).
If you truly do not care about time zone or date, use either the Joda-Time LocalTime class or the java.time LocalTime class.
Caution: Naïve programmers often think they need only local time and can therefore ignore time zones, but then live to regret that position.
Joda-Time
If your times are in proper ISO 8601 format (24-hours, correct number of digits), then you can directly pass the string inputs to the constructor of LocalTime without bothering to parse. That class has a built-in ISO 8601 style parser.
String inputStart = "09:00";
String inputStop = "17:30";
LocalTime start = new LocalTime( inputStart );
LocalTime stop = new LocalTime( inputStop );
LocalTime now = LocalTime.now();
// Comparing using Half-Open logic, where beginning is inclusive and ending is exclusive.
boolean isNowContainedWithinInterval = ( ( now.isEqual( start ) ) || ( now.isAfter( start ) ) ) && ( now.isBefore( stop ) );
Dump to console…
System.out.println( "start: " + start );
System.out.println( "stop: " + stop );
System.out.println( "now: " + now );
System.out.println( "isNowContainedWithinInterval: " + isNowContainedWithinInterval );
When run…
start: 09:00:00.000
stop: 17:30:00.000
now: 12:42:06.567
isNowContainedWithinInterval: true
In the real-world, I would add an assertion test proving the stop time is later than the start time, to validate inputs.