Reputation: 33
I am reading data from a cell in Excel file. I have the value of time(milliseconds) in Double i.e. 0.36712962962962964.
I need to convert this value to java.sql.Time format. I tried parsing it using various approaches but it fails. Following is the code.
timeInDouble = 0.36712962962962964;
Time time = new Time(Long.parseLong(timeInDouble.toString()));
The output for this code is:
java.lang.NumberFormatException: For input string: "0.36712962962962964"
What is the correct way for this conversion?
Upvotes: 1
Views: 1313
Reputation: 338634
Modern solution use java.time class LocalTime
.
Convert your string input to double
, as a fraction of a day, multiply by the number of nanoseconds (or milliseconds perhaps) in a day, adding to the 00:00:00 time-of-day.
LocalTime
.MIN
.plusNanos (
(long)
(
TimeUnit.HOURS.toNanos ( 24 )
*
Double.parseDouble ( "0.36712962962962964" )
)
)
08:48:40
The java.sql.Time
class is a terrible hack, pretending to be a time-of-day but actually implemented as a moment by subclassing java.util.Date
. Never use this class.
With the adoption of JSR 310, this class became legacy, supplanted by the java.time.LocalTime
class. A LocalTime
truly represents a time-of-day without a date and without the context of a time zone or offset-from-UTC.
I assume you are correct in saying that this decimal number provided by Microsoft Excel represents a fraction of a 24-hour day. By the way, this is a poor way to represent a time-of-day; a better way is to use text in standard ISO 8601 format.
Start by parsing your input into a double
primitive. Normally, I would suggest BigDecimal
class for accuracy, but I am guessing that Excel uses floating-point technology to handle this number, so we will do the same.
// Parse your input string as a `double`.
String input = "0.36712962962962964";
double fractionOf24Hours = Double.parseDouble ( input );
That input presumably represents a fraction of a 24-hour day. So let's calculate the number of nanoseconds in a day. I suppose Excel uses milliseconds rather than nanoseconds, but the end result may be the same.
// Calculate the number of nanoseconds in a day.
long nanosIn24Hours = TimeUnit.HOURS.toNanos ( 24 );
We have the constant LocalTime.MIN
to represent the time-of-day 00:00:00. Add to that the number of nanos representing our desired fraction of a day.
// Start at time-of-day zero, adding the amount of time in nanos.
long nanosToAdd = ( long ) ( nanosIn24Hours * fractionOf24Hours );
LocalTime localTime = LocalTime.MIN.plusNanos ( nanosToAdd );
See this code run live at IdeOne.com.
localTime.toString(): 08:48:40
If you must have java.sql.Time
object to interoperate with old code not yet updated to java.time, you can convert back-and-forth. Look to new methods added to the old classes.
java.sql.Time t = Time.valueOf( localTime ) ;
Upvotes: 1
Reputation: 5207
The double value represents a part of day duration, where 0 is begin and 1 is the end of the day. Contructor of Time class expects the time in milliseconds. In a day there are 24 x 60 x 60 x 1000 milliseconds. First we convert daouble into the number of milliseconds since the beginning of the day. Then create a time using milliseconds.
double timeInDouble = 0.36712962962962964;
// The number of milliseconds since the beginning of the day
long milliseconds = (long) (timeInDouble * 24 * 60 * 60 * 1000);
Time time = new Time(milliseconds);
Upvotes: 0