时间格式不正确(Format of time is incorrect)

其他开发 IT屋
问 题
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())));

Current output:

Duration: 00:00:05.0234

Desired output:

Duration: 00:00:05.2345

I also tried another method, still no good:

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);

Current output:

Duration: 00:00:01.4340

Desired output:

Duration: 00:00:01.4345

I have googled for some time. Any ideas what is causing this?

解决方案

First of all, you're mistaking 2 different concepts:

  1. A time of the day, such as 10 AM or 15:30:45
  2. A duration, which is an amount of time, such as 1 year, 2 months and 10 days or 10 hours, 25 minutes and 30 seconds

Although both might use the same words (such as "hours" and "minutes"), they're not the same thing. A duration is not attached to a chronology (10 hours and 25 minutes relative to what?), it's just the amount of time, by itself.

SimpleDateFormat and DateTimeFormatter are designed to format dates and times of the day, but not durations. Although converting a duration to a time and "pretending" it's a time of the day to format it might work, it's not the right way.

Unfortunately, there are no built-in formatters for a duration. So you'll have to format it manually.

Another detail is that you are multiplying 1.4345 by 1000 (resulting in 1434.5), and then casting to a long(so the value is rounded to 1434) - the last digit is lost.

One way to do it is to parse the string to a double and then multiply by 1 billion to get the value as nanoseconds (I don't know if you'll work with more than 4 digits, so I'm considering nanosecond precision):

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

Now we must format it manually. First I've extracted the number of hours, minutes, seconds and nanoseconds from the total nanos value:

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;

Then I created an auxiliary method to build the output:

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

And used it to join the pieces:

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);

The output is:

00:00:01.4345

本文地址:IT屋 » Format of time is incorrect

问 题
  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())));


目前输出:





$ b

所需输出:



blockquote>

持续时间:00:00:05.2345



我也尝试了另一种方法,仍然不行: / p>

 字符串realTimeStr =“1.4345”; 
Double realTimeDbl = Double.parseDouble(realTimeStr);
DateTimeFormatter formatter =
DateTimeFormatter.ofPattern(“HH:mm:ss.SSSS”)。withZone(ZoneId.of(“UTC”));
即时瞬间= Instant.ofEpochMilli((long)(realTimeDbl * 1000));
String t = formatter.format(instant);
System.out.println(“Duration:”+ t);


目前输出:


$ p


$ b

所需输出:

blockquote>

时间:00:00:01.4345



我已经搜索了一段时间。任何想法是什么造成这种情况?


解决方案
首先,你误解了两个不同的概念:
$ b

  1. 一天中的时间,例如 10 AM 或 15:30:45

  2. 一个持续时间,它是一个时间量,如 1年,2 10个月10天或<10小时25分30秒
  3. 使用相同的词(如“小时”和“分钟”),它们不是同一个东西。一个持续时间没有附加到年表(相对于10小时25分钟),这只是时间量本身。



    <> SimpleDateFormat 和 DateTimeFormatter 旨在格式化日期和时间,但不是持续时间。尽管将持续时间转换为时间并“假装”是格式化的一天中的某个时间,但这不是正确的方法。



    不幸的是,没有构建-in格式化程序一段时间。所以你必须手动格式化。



    另外一个细节是你将 1.4345 乘以1000在 1434.5 ),然后铸造到 long 1434 ) - 最后一位数字丢失。

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

      //将字符串值转换为总计纳秒
    int nanosPerSecond = 1_000_000_000;
    long nanos =(long)(Double.parseDouble(realTimeStr)* nanosPerSecond);


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

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


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

      //辅助方法
    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);

    //在最后删除多余的零
    String output = sb.toString()。replaceAll(“0 * $”,“”);
    System.out.println(输出);


    输出是:

    lockquote

    00:00:01.4345

    本文地址:IT屋 » 时间格式不正确