android SimpleDataFormat中的java错误

wnrlj8wa  于 2021-07-07  发布在  Java
关注(0)|答案(2)|浏览(319)

我用simpledateformat在android中格式化时间。目标是从包含时间(以毫秒为单位)的long中获取人类可读的时间表示:

var simpleDateFormat = SimpleDateFormat("s.SS")
 simpleDateFormat.timeZone = TimeZone.getTimeZone("UTC")
 var result = simpleDateFormat.format(timeInMillis)

我遇到了以下非常奇怪的错误:timeinmillis的最后一个数字是7或8,前面的数字是5,格式化是错误的,因为1/100秒的结果太小了。
例子:
时间单位:毫秒=1570
结果期望值:1.57
结果实际值1.56
有人能重现这个错误吗?我在哪里可以报告?

ctehm74n

ctehm74n1#

对此行为的解释是,android SimpleDataFormat在这里使用了不准确的浮点数学:

// BEGIN Android-added: Better UTS#35 conformity for fractional seconds.
case PATTERN_MILLISECOND: // 'S'
    // Fractional seconds must be treated specially. We must always convert the parsed
    // value into a fractional second [0, 1) and then widen it out to the appropriate
    // formatted size. For example, an initial value of 789 will be converted
    // 0.789 and then become ".7" (S) or ".78" (SS) or "0.789" (SSS) or "0.7890" (SSSS)
    // in the resulting formatted output.
    if (current == null) {
        value = (int) (((double) value / 1000) * Math.pow(10, count));
        zeroPaddingNumber(value, count, count, buffer);
    }
    break;
// END Android-added: Better UTS#35 conformity for fractional seconds.

例如,表达式 (int) (((double) value / 1000) * Math.pow(10, count)) 对于值570和计数2,产生56。
正如其他回答者所指出的,在android开发中有更好的datetimes替代方案。例如java8.java.time desugaring。

a6b3iqyw

a6b3iqyw2#

我不知道你想怎么做。

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

public class Main {
    public static void main(String args[]) {
        long timeInMillis = 1570;
        var simpleDateFormat = new SimpleDateFormat("s.SS");
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
        var result = simpleDateFormat.format(timeInMillis);
        System.out.println(result);
    }
}

输出:

1.570

在ideone上也检查一下。
注意,api的日期时间 java.util 以及它们的格式化api, SimpleDateFormat 过时且容易出错。建议完全停止使用它们,并切换到现代日期时间api。在trail:date-time了解有关现代日期时间api的更多信息。
注意:如果您正在为一个android项目工作,并且您的android api级别仍然不符合java-8,请检查通过desugaring提供的java8+api以及如何在android项目中使用threetenabp。
使用现代日期时间api:

import java.time.Instant;
import java.time.LocalTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String args[]) {
        long timeInMillis = 1570;
        var dtf = DateTimeFormatter.ofPattern("s.SS");
        LocalTime time = Instant.ofEpochMilli(timeInMillis).atOffset(ZoneOffset.UTC).toLocalTime();
        System.out.println(time.format(dtf));
    }
}

输出:

1.57

相关问题