时间格式不正确

时间:2017-09-06 19:39:58

标签: java time formatting duration

String realTimeStr = "5.2345";
Double realTimeDbl = Double.parseDouble(realTimeStr);
long   realTimeLng = (long) (realTimeDbl*1000);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSSS", Locale.getDefault());      
log("Duration: " + sdf.format(new Date(realTimeLng - TimeZone.getDefault().getRawOffset())));

当前输出:

  

持续时间:00:00:05.0234

期望的输出:

  

持续时间:00:00:05.2345

我也尝试了另一种方法,但仍然没有好处:

String realTimeStr = "1.4345";
Double realTimeDbl = Double.parseDouble(realTimeStr);               
DateTimeFormatter formatter =               
    DateTimeFormatter.ofPattern("HH:mm:ss.SSSS").withZone(ZoneId.of("UTC"));            
Instant instant = Instant.ofEpochMilli((long)(realTimeDbl*1000));
String t = formatter.format(instant);
System.out.println("Duration: " + t);

当前输出:

  

持续时间:00:00:01.4340

期望的输出:

  

持续时间:00:00:01.4345

我用Google搜索了一段时间。是什么原因引起了这个?

4 个答案:

答案 0 :(得分:1)

首先,您误解了两个不同的概念:

  1. 一天的时间,例如10 AM15:30:45
  2. 持续时间,为amount of time,例如 1年,2个月和10天 10小时25分30秒秒
  3. 虽然两者都可能使用相同的词(例如"小时"和"分钟"),但它们并不是一回事。一个持续时间没有附加到年表(相对于什么时间10小时25分钟),它只是时间量本身。

    SimpleDateFormatDateTimeFormatter用于设置日期和时间的格式,但不包括持续时间。虽然将持续时间转换为时间并且假装"它是一天中某个时间格式化它可能有用,但这不是正确的方法。

    不幸的是,一段时间内没有内置格式化程序。因此,您必须手动格式化。

    另一个细节是,您将1.4345乘以1000(得到1434.5),然后投射long(因此值会四舍五入至1434) - 最后一位数字丢失。

    一种方法是将字符串解析为double,然后乘以10亿,得到的值为纳秒(我不知道你是否会使用超过4位的数字,所以我考虑纳秒级精度):

    // convert the string value to a total of nanoseconds
    int nanosPerSecond = 1_000_000_000;
    long nanos = (long) (Double.parseDouble(realTimeStr) * nanosPerSecond);
    

    现在我们必须手动格式化它。首先,我从总纳米值中提取了小时数,分钟数,秒数和纳秒数:

    long hours = nanos / nanosPerSecond / 3600;
    nanos -= hours * 3600 * nanosPerSecond;
    long minutes = nanos / nanosPerSecond / 60;
    nanos -= minutes * 60 * nanosPerSecond;
    long seconds = nanos / nanosPerSecond;
    nanos -= seconds * nanosPerSecond;
    

    然后我创建了一个辅助方法来构建输出:

    // auxiliary method
    public void addValue(long value, StringBuilder sb) {
        if (value < 10) {
            sb.append("0");
        }
        sb.append(value);
    }
    

    用它来加入各个部分:

    StringBuilder sb = new StringBuilder();
    addValue(hours, sb);
    sb.append(":");
    addValue(minutes, sb);
    sb.append(":");
    addValue(seconds, sb);
    sb.append(".");
    addValue(nanos, sb);
    
    // remove the extra zeroes in the end
    String output = sb.toString().replaceAll("0*$", "");
    System.out.println(output);
    

    输出结果为:

      

    00:00:01.4345

答案 1 :(得分:1)

您可以使用 java.time.Duration,它以 ISO-8601 standards 为模型,并作为 JSR-310 implementation 的一部分与 Java-8 一起引入。 Java-9 引入了一些更方便的方法。

演示:

import java.time.Duration;

public class Main {
    public static void main(String[] args) {
        String realTimeStr = "5.2345";
        Double realTimeDbl = Double.parseDouble(realTimeStr);
        long nanos = (long) (realTimeDbl * 1000_000_000);
        Duration duration = Duration.ofNanos(nanos);
        System.out.println(duration);

        // Custom format
        // ####################################Java-8####################################
        String formattedDuration = String.format("%02d:%02d:%02d.%d", duration.toHours() % 24,
                duration.toMinutes() % 60, duration.toSeconds() % 60, (duration.toNanos() % 1000_000_000) / 100000);
        System.out.println(formattedDuration);
        // ##############################################################################

        // ####################################Java-9####################################
        formattedDuration = String.format("%02d:%02d:%02d.%d", duration.toHoursPart(), duration.toMinutesPart(),
                duration.toSecondsPart(), duration.toNanosPart() / 100000);
        System.out.println(formattedDuration);
        // ##############################################################################

    }
}

输出:

PT5.2345S
00:00:05.2345
00:00:05.2345

Trail: Date Time 了解现代日期时间 API。

答案 2 :(得分:0)

这个问题存在于Joe C注意到的格式中,可能意味着这一行:

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSSS", Locale.getDefault());

尝试更改它,删除一个&#34; S&#34;

SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS", Locale.getDefault());

通知我们是否正确=)

答案 3 :(得分:-1)

package com.stackoverflow.examples;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

public class TimeStamp {
    public static void main(String[] args) {
        String realTimeStr = "5.2345";
        Double realTimeDbl = Double.parseDouble(realTimeStr);
        long realTimeLng = (long) (realTimeDbl * 1000);
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSSs", Locale.getDefault());
        System.out.println("Duration: " + sdf.format(new Date(realTimeLng - TimeZone.getDefault().getRawOffset())));
    }
}

我尝试了SSSs而不是SSSS