Shariq Ali
Shariq Ali

Reputation: 33

Convert Double to java.sql.Time

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

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 338634

tl;dr

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

java.time

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

Convert

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

mentallurg
mentallurg

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

Related Questions