TimeUnit从毫秒转换为天不适合我

时间:2018-05-25 18:59:39

标签: java time timestamp timeunit

我试图在几天内得到两个时间戳的差异,而TimeUnit正在为我返回完全错误的结果。

这是我的代码:

long ts = 1522242239952L;
long now = 1527274162820L;
long difference = now - ts;
int ageInDays = (int) TimeUnit.MILLISECONDS.convert(difference, TimeUnit.DAYS);
int ageInDays2 = (int) (difference/(1000 * 60 * 60 * 24));
System.out.println(ageInDays);
System.out.println(ageInDays2);

输出是:

-1756844032
58

为什么TimeUnit计算错误?

3 个答案:

答案 0 :(得分:3)

您误解了TimeUnit文档:

  

长转换(long sourceDuration,TimeUnit sourceUnit)

     

将给定单位的给定持续时间转换为此单位。

你的源单位是MILLISECONDS,你想要DAYS所以该行应该是

var records = [
    {
        "category" : "chinese",
        "name": "noodles"
    },
    {
        "category" : "chinese",
        "name": "veg"  
    },
    {
        "category" : "Indian",
        "name": "Dal"  
    },
    {
        "category" : "Indian",
        "name": "Rajma"  
    },
    {
        "category" : "chinese",
        "name": "chicken"  
    },
    {
        "category" : "continental",
        "name": "fish"
    },
    {
        "category" : "continental",
        "name": "Veg"
    },
    {
        "category" : "Indian",
        "name": "Paratha" 
    }
];


var newcat = {};
var arr = {};
var isPresent = false;
var cat;

for (let i=0; i < records.length; i++) {
    cat= records[i].category
    for(let item in newcat) {
        if(cat == item) {
            isPresent= true
            break;
        }
        else {
            isPresent= false
        }
    }
    if(isPresent== false){
        newcat[cat] = []
    }
    newcat[cat].push(records[i])
}

console.log(newcat);

答案 1 :(得分:3)

因为你正在向后使用TimeUnit.convert。尝试

TimeUnit.DAYS.convert(difference, TimeUnit.MILLISECONDS);

或只是

TimeUnit.MILLISECONDS.toDays(difference);

参考:https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/TimeUnit.html#convert(long,%20java.util.concurrent.TimeUnit)

答案 2 :(得分:0)

  

为什么TimeUnit计算错误?

其他答案是正确的:您正在进行与预期相反的转换。 TimeUnit.MILLISECONDS.convert(difference, TimeUnit.DAYS);将天数转换为毫秒。

但你怎么得到一个负数?这是因为int溢出。正确执行相反的转换并产生434 758 135 795 200 000.这比32位int可以容纳的要大得多。因此,当您转换为int时,最重要的位被切断。偶然的是,最终成为int的符号位的位是1,意思是否定的。我通常避免在没有范围检查的情况下进行这样的演员表演。你可能想要获得同样的习惯。 Math.toIntExact()在这里非常有帮助。

如何修复:java.time

其他答案仍然基本正确。我仍然想提出一些建议。

如果您认为从一天的16:04到第二天的16:04的时间是1天,那么您需要考虑时区以获得正确的结果。例如:

    ZoneId zone = ZoneId.of("Africa/Mogadishu");
    ZonedDateTime birth = Instant.ofEpochMilli(ts).atZone(zone);
    long ageInDays = ChronoUnit.DAYS.between(birth, ZonedDateTime.now(zone));
    System.out.println(ageInDays);

在这种情况下,刚刚运行代码的结果也是您所期望的结果:

  

58

如果另一方面,无论挂钟读取什么,您都将1天定义为24小时,这里是一种以亚秒精度获得年龄的方法。您随时可以转换为几天。

    Instant birth = Instant.ofEpochMilli(ts);
    Duration age = Duration.between(birth, Instant.now());
    System.out.println(age);
    System.out.println(age.toDays());

输出:

PT1398H52M13.994841S
58

两条线中的第一条表示年龄为1398小时52分13.994841秒。第二行与之前的结果一致。

两个片段背后的想法也可以合并和混合。总而言之,我认为java.time提供了一些使用TimeUnit更难以获得的可能性,以及一些非常清晰且不言自明的代码,在这些代码中您不会轻易犯同问题中的错误

<强>链接: