首页 > 解决方案 > 将 Double 转换为 java.sql.Time

问题描述

我正在从 Excel 文件中的单元格读取数据。我有双倍的时间(毫秒)值,即 0.36712962962962964。

我需要将此值转换为 java.sql.Time 格式。我尝试使用各种方法对其进行解析,但失败了。以下是代码。

timeInDouble = 0.36712962962962964; Time time = new Time(Long.parseLong(timeInDouble.toString()));

此代码的输出是:

java.lang.NumberFormatException: For input string: "0.36712962962962964"

这种转换的正确方法是什么?

标签: javaparsingtimedoubledatetime-conversion

解决方案


tl;博士

现代解决方案使用java.timeLocalTime

将您的字符串输入转换为double,作为一天的一小部分,乘以一天中的纳秒数(或毫秒数),再加上一天中的 00:00:00 时间。

LocalTime
.MIN
.plusNanos (
    (long)
    (
            TimeUnit.HOURS.toNanos ( 24 )
            *
            Double.parseDouble ( "0.36712962962962964" )
    )
)

08:48:40

java.time

这个java.sql.Time类是一个可怕的黑客,假装是一天中的时间,但实际上是通过子类化实现的java.util.Date永远不要使用这个类。

随着 JSR 310 的采用,这个类成为了传统,被这个类所取代java.time.LocalTime。ALocalTime真正表示没有日期且没有时区上下文或与 UTC 偏移的时间。

我假设您说 Microsoft Excel 提供的这个十进制数字代表一天 24 小时的一小部分是正确的。顺便说一句,这是表示一天中某个时间的糟糕方式。更好的方法是使用标准ISO 8601格式的文本。

首先将您的输入解析为double原语。通常情况下,我会建议BigDecimal使用准确性类,但我猜测 Excel 使用浮点技术来处理这个数字,所以我们也会这样做。

// Parse your input string as a `double`.
String input = "0.36712962962962964";
double fractionOf24Hours = Double.parseDouble ( input );

该输入可能代表一天 24 小时的一小部分。所以让我们计算一天的纳秒数。我想 Excel 使用毫秒而不是纳秒,但最终结果可能是相同的。

// Calculate the number of nanoseconds in a day.
long nanosIn24Hours = TimeUnit.HOURS.toNanos ( 24 );

我们有一个常数LocalTime.MIN来表示一天中的时间 00:00:00。再加上代表我们一天中所需分数的纳秒数。

// Start at time-of-day zero, adding the amount of time in nanos.
long nanosToAdd = ( long ) ( nanosIn24Hours * fractionOf24Hours );
LocalTime localTime = LocalTime.MIN.plusNanos ( nanosToAdd );

请参阅在 IdeOne.com 上实时运行的代码

localTime.toString(): 08:48:40

转变

如果您必须有java.sql.Time对象与尚未更新为java.time的旧代码进行互操作,则可以来回转换。查看添加到旧类的新方法。

java.sql.Time t = Time.valueOf( localTime ) ;

推荐阅读