Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/373.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java当前日期和过去日期之间的差值,以年、月、日、小时、分、秒为单位_Java_Date_Datetime_Difference_Date Difference - Fatal编程技术网

Java当前日期和过去日期之间的差值,以年、月、日、小时、分、秒为单位

Java当前日期和过去日期之间的差值,以年、月、日、小时、分、秒为单位,java,date,datetime,difference,date-difference,Java,Date,Datetime,Difference,Date Difference,我知道这个问题以前在这里被问过很多次,但是我还没有找到任何与我的情况相关的东西。我试图找出当前日期时间和前一个日期时间之间的差异,每个日期时间的格式为yyyy-MM-dd HH:MM:ss.s。根据给出的答案,我得出了以下代码: SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.s"); String earliestRunTime = "2017-12-16 01:30:08.0"; Date current

我知道这个问题以前在这里被问过很多次,但是我还没有找到任何与我的情况相关的东西。我试图找出当前日期时间和前一个日期时间之间的差异,每个日期时间的格式为yyyy-MM-dd HH:MM:ss.s。根据给出的答案,我得出了以下代码:

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.s");
String earliestRunTime = "2017-12-16 01:30:08.0";
Date currentDate = new Date();
log.info("Current Date: {}", format.format(currentDate));

try {
    Date earliestDate = format.parse(earliestRunTime);

    long diff = currentDate.getTime() - earliestDate.getTime();

    long diffSeconds = diff / 1000 % 60;
    long diffMinutes = diff / (60 * 1000) % 60;
    long diffHours = diff / (60 * 60 * 1000) % 24;
    long diffDays = diff / (24 * 60 * 60 * 1000) % 30;
    long diffMonths = diff / (30 * 24 * 60 * 60 * 1000) % 12;
    long diffYears = diff / (12 * 30 * 24 * 60 * 60 * 1000);

    return String.format("%s years, %s months, %s days, %s hours, %s minutes, %s seconds",
            diffYears, diffMonths, diffDays, diffHours, diffMinutes, diffSeconds);


    }
catch (Exception e) {
    e.printStackTrace();
    return e.getMessage();
}
当我运行代码时,JSON返回以下结果:

lifetime: "41 years, -1 months, 14 days, 9 hours, 42 minutes, 37 seconds"
我这里有两个问题:

我41岁和一个负数的计算错在哪里? 有没有更好的方法让我这么做?我目前的设置不考虑闰年或365天一年,我需要考虑到这些。 我41岁和一个负数的计算错在哪里

因为分母会溢出。您需要使用Long:

long diffMonths = diff / (30 * 24 * 60 * 60 * 1000L) % 12; //Notice the L at the end
long diffYears = diff / (12 * 30 * 24 * 60 * 60 * 1000L); //Notice the L at the end
还要注意,12*30是一年中天数的一个非常糟糕的近似值

有没有更好的方法让我这么做

对。使用Java8中的DurationAPI


很难给出准确的答案,因为这个问题有点模糊。例如,如果一年中有一年是闰年,而您正在比较日期2020/03/28和2021/03/28,结果应该是什么?1年还是1年1天?2020年是闰年,所以在03/28之后,也有03/29,使用与您相同的方法,您需要明确地将分母标识为长值。目前,它假定它们是整数,这会导致数字溢出-这意味着计算的值对于整数来说太大。这可以解释为什么会得到负值/任意值。解决方法很简单:

SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.s");
String earliestRunTime = "2017-12-16 01:30:08.0";
Date currentDate = new Date();
log.info("Current Date: {}" + format.format(currentDate));

try {
    Date earliestDate = format.parse(earliestRunTime);

    long diff = currentDate.getTime() - earliestDate.getTime();

    long diffSeconds = diff / 1000L % 60L;
    long diffMinutes = diff / (60L * 1000L) % 60L;
    long diffHours = diff / (60L * 60L * 1000L) % 24L;
    long diffDays = diff / (24L * 60L * 60L * 1000L) % 30L;
    long diffMonths = diff / (30L * 24L * 60L * 60L * 1000L) % 12L;
    long diffYears = diff / (12L * 30L * 24L * 60L * 60L * 1000L);

    return String.format("%s years, %s months, %s days, %s hours, %s minutes, %s seconds",
            diffYears, diffMonths, diffDays, diffHours, diffMinutes, diffSeconds);


}
catch (Exception e) {
    e.printStackTrace();
    return e.getMessage();
}
我41岁和一个负数的计算错在哪里? 除了使用臭名昭著的麻烦且早已过时的SimpleDataFormat类和同样过时的日期之外,您的代码中还存在以下错误:

您正在将08.0解析为8秒0秒。在我的JDK-11上,SimpleDataFormat选择0秒,放弃我认为正确的8秒。SimpleDateFormat无法解析秒上的一个小数,只能解析三个小数,因此此错误的解决方案是完全放弃SimpleDateFormat。 正如其他人所说,乘法中存在int溢出。例如,30*24*60*60*1000应该给出2592000000,但是由于int不能容纳这个数字,因此得到的是-170297296。由于这是一个负数,下面的除法给出的月数为负数。 所罗门·斯洛在评论中指出,一个月可能是28天、29天、30天或31天。当将所有月份设置为30天时,您可能会面临天数和月份不正确的风险,最后可能会出现年份错误的风险。当我今天运行你的代码时,正确答案应该是1年4个月13天,但我得到了19天,6天太多了。 您没有考虑夏季DST和其他时间异常。这可能会导致一天的时间为23或25小时,从而产生错误。 或者总结一下:你的错误是你试图“手工”计算。日期和时间的数学太复杂,容易出错。您应该始终将其留给经过充分验证的库类

有没有更好的方法让我这么做?我目前的设置不考虑闰年或365天一年,我需要把这些纳入 账户 是的,有一个更好的方法。最好的方法可能是使用ThreeTen额外项目中的PeriodDuration类,请参见下面的链接。我现在不打算在我的计算机上安装该库,因此我将仅展示使用内置类的良好且现代化的解决方案:

    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss.S");
    LocalDateTime currentDateTime = LocalDateTime.now(ZoneId.of("Australia/Sydney"));
    String earliestRunTime = "2017-12-16 01:30:08.0";
    LocalDateTime earliestDateTime = LocalDateTime.parse(earliestRunTime, dtf);

    // We want to find a period (years, months, days) and a duration (hours, minutes, seconds).
    // To do that we cut at the greatest possible whole number of days
    // and then measure the period before the cut and the duration after it.
    LocalDateTime cut = earliestDateTime.plusDays(
            ChronoUnit.DAYS.between(earliestDateTime, currentDateTime));

    Period p = Period.between(earliestDateTime.toLocalDate(), cut.toLocalDate());
    Duration d = Duration.between(cut, currentDateTime);

    String result = String.format("%s years, %s months, %s days, %s hours, %s minutes, %s seconds",
            p.getYears(), p.getMonths(), p.getDays(),
            d.toHours(), d.toMinutesPart(), d.toSecondsPart());

    System.out.println(result);
当我刚才运行代码时,我得到:

1年4个月13天19小时26分7秒

在现代java日期和时间API java.time中,周期是年、月和天的数量,持续时间是小时、分钟、秒和秒到纳秒的分数。既然你想要两者,我就使用这两个类

我使用的Duration的toxxpart方法是在Java9中引入的。如果您使用的是Java8或Three-Ten Backport,打印分钟和秒的过程会稍微复杂一些。搜索java格式持续时间或类似内容以了解如何使用

我仍然没有把夏天的时间考虑在内。为此,我们需要知道最早运行时字符串的时区,然后使用ZonedDateTime而不是LocalDateTime。否则代码将非常相似

链接 解释如何使用java.time
结果应该是怎样的?如果差异为1年,您是要打印1年、12个月、365天还是1年、0个月、0天?只是想一想:如果向下报告到第二个很重要,但时间跨度可以包括28、29、30或31天的月份,那么也许你需要重新思考你的用例。@NeplatnyUdaj理想情况下,差异应该是1年,0个月,0天。@SolomonSlow很好,我甚至不认为
你使用的是几年前被java.time取代的糟糕类。切勿使用日期。闰年应处理为1年1天。