I am currently getting an IllegalArgumentException
thrown at these lines of code:
Time timeIn = Time.valueOf( res.getCheckInTime().toString());
Time timeOut = Time.valueOf( res.getCheckOutTime().toString());
Both arguments are LocalTime
storing the local time such as 11:05
:
res.getCheckInTime()
res.getCheckOutTime()
Can anyone help me out here?
CodePudding user response:
Why do you need to use res.getCheckInTime().toString()
? Couldn't use the Time.valueOf(LocalTime s)
method?
See the following example:
public static void main(String[] args) {
LocalTime checkInTime = LocalTime.now();
LocalTime checkOutTime = LocalTime.now().plusHours(12);
Time timeIn = Time.valueOf(checkInTime);
Time timeOut = Time.valueOf(checkOutTime);
System.out.println("timeIn => " timeIn);
System.out.println("timeOut => " timeOut);
}
To convert a java.time.LocalTime
object to java.sql.Time
:
Time t = Time.valueOf( myLocalTime ) ;
To go the other direction, from legacy class java.sql.Time
to modern class java.time.LocalTime
:
LocalTime lt = t.toLocalTime() ;
No strings involved.
CodePudding user response:
TL;DR: use the safe & concise Time.valueOf(LocalTime)
as suggested by Samuel Cruz, e.g. Time.valueOf( res.getCheckInTime() )
.
Pitfalls when using String-based conversion
The String-variant has 2 pitfalls:
LocalTime.toString()
produces variable output-formats that may cause givenIllegalArgumentException
when used withTime.valueOf(String)
- two implied assumptions: (a) non-deterministic output causes (b) message-less, thus not very helpful, exception that let's the user guess which value was passed as argument and why it was illegal.Also the JavaDoc for
Time.valueOf(String)
as quoted by Jim Garrison is misleading. In current implementation (OpenJDK) you can pass any other integer-sequence separated by 2 colons, like-33:9999:88
. Although not a valid ISO-time in formatHH:mm:ss
, it is apparently interpreted as time-value and may lead to serious side-effects! Did you expect"13:40:28" == Time.valueOf("-33:9999:88")
as result ?
time.LocalTime
has non-deterministic toString
format
Don't use LocalTime.toString()
because it's output format is non-deterministic and may vary in precision, worst-case omitting seconds! It tries to reduce the output to significant parts, minimum format is "HH:mm" as in JavaDoc summary.
For reliable and SQL-compliant String-format use LocalTime.format(DateTimeFormatter.ISO_LOCAL_TIME)
. It may always produce format like HH:mm:ss
as required by java.sql.Time
.
java.sql.Time
can convert LocalTime
directly
It should work when passing the argument to factory-method java.sql.Time.valueOf()
:
- either as ISO-formatted time
String("11:05:00")
(up to seconds!). ⚠️ Warning: Potential side-effects if passed String contains invalid ISO-time, e.g."99:123:88"
or even"0:-1:-3"
(see example below). - or directly as
java.time.LocalTime
. ✔️ Recommended as safest.
Solution: illustrates argument variants & side-effects
public static void main(String[] args) throws java.lang.Exception {
Reservation res = new Reservation("11:05", "18:05");
System.out.println(res);
System.out.printf("toString returns '11:05:00' as expected? %s\n", "11:05:00".equals(res.getCheckInTime()));
String isoTimeFormat = res.getCheckOutTime().format(DateTimeFormatter.ISO_LOCAL_TIME);
System.out.printf("explicit format() returns '%s' as expected by SQL? %s\n", isoTimeFormat, "18:05:00".equals(isoTimeFormat));
Time timeIn = Time.valueOf(res.getCheckInTime()); // recommended argument type
Time timeOut = Time.valueOf(res.getCheckOutTime().format(DateTimeFormatter.ISO_LOCAL_TIME));
Time timeTest = Time.valueOf("33:99:88"); // dangerous fun-fact
System.out.println("sql.Time in: " timeIn " , out: " timeOut);
}
static class Reservation {
LocalTime checkIn;
LocalTime checkOut;
public Reservation(String in, String out) {
this.checkIn = LocalTime.parse(in);
this.checkOut = LocalTime.parse(out);
}
public LocalTime getCheckInTime() {
return checkIn;
}
public LocalTime getCheckOutTime() {
return checkOut;
}
public String toString() {
return String.format("Reservation {checkIn: %s, checkOut: %s}", getCheckInTime(), getCheckOutTime());
}
}
Try runnable demo on IDEone.
See also:
- Dariawan tutorial: java.sql.Time Examples
CodePudding user response:
Javadoc:
public static Time valueOf(String s)
Converts a string in JDBC time escape format to a Time value.
Parameters: s - time in format "hh:mm:ss" Returns: a corresponding Time object
The only accepted format is hh:mm:ss