首页 > 解决方案 > 倒计时在 4 月和 10 月之间增加一小时

问题描述

我正在开发简单的倒计时应用程序来告诉我距离某个 GMT 时间还有多长时间。

例子:

输入:01-05-2021-02-00-00

输出:(如果输入的时间是本地时间)72 天 15 小时 21 分钟 49 秒

输出(如果输入的时间是格林威治标准时间):72 天,17 小时,21 分钟,33 秒

...我相信应该有 16 小时而不是 17 小时。

在输入时间为 4 月 1 日至 10 月 31 日之前,一切正常。我给它格林威治标准时间,并将其转换为我的本地(柏林+1)时间。如果输入的时间来自提到的时间间隔,它会显示柏林和格林威治标准时间之间的 +2 小时差异。因为它只在一年中的特定时期(任何一年)都是这样,所以看起来很奇怪我不知道出了什么问题?

我的代码:

String result = "";
        
        
        String date = input;
        
        SimpleDateFormat date_format = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
        Date target_date = null;
        try {
            target_date = date_format.parse(date);
        } catch (ParseException e) {
          result += e.getMessage(); 
        }
        
        Date now = new Date();      
        
        long secs = 0;
        if(local_time_radio_btn.isSelected()) {
            secs = (target_date.getTime() - now.getTime()) / 1000;
        }else {
            int offset = target_date.getTimezoneOffset();
            long n = 1000 * offset * 60;
            long gmt = target_date.getTime() -n;
            long now_gmt = now.getTime();           
            secs = (gmt - now_gmt) / 1000;
        }
        
        long days = secs / (60*60*24);
        secs = secs % (60*60*24);
        long hours = secs / (60*60);    
        secs = secs % (60*60);
        long mins = secs / 60;
        secs = secs % 60;

        result += days+" days, "+hours+" hours, "+mins+" mins, "+secs +" secs";

标签: javadatetimecountdown

解决方案


java.time

我强烈建议您使用现代 Java 日期和时间 API java.time 进行日期和时间工作。

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-uuuu-HH-mm-ss");
    
    String input = "01-05-2021-02-00-00";

    LocalDateTime targetLdt = LocalDateTime.parse(input, formatter);

    // German time case
    ZoneId zone = ZoneId.of("Europe/Berlin");

    ZonedDateTime now = ZonedDateTime.now(zone);
    ZonedDateTime target = targetLdt.atZone(zone);
    long days = ChronoUnit.DAYS.between(now, target);
    ZonedDateTime afterDays = now.plusDays(days);
    Duration timeDiff = Duration.between(afterDays, target);
    
    String result = days + " days, " + timeDiff.toHours() + " hours, "
            + timeDiff.toMinutesPart() + " mins, "
            + timeDiff.toSecondsPart() + " secs";
    
    System.out.println(result);

当我刚才运行代码时(柏林的 2021-02-18T17:23:35.47),输出为:

71 天 8 小时 36 分 24 秒

对于 UTC(或 GMT)情况,您只需要更改一行:

    // GMT case
    ZoneId zone = ZoneOffset.UTC;

71 天 9 小时 36 分 24 秒

你的代码出了什么问题?

首先,不要使用SimpleDateFormatand,Date因为它们设计不佳且早已过时。即使你坚持使用Date,你也绝对应该远离它的getTimezoneOffset方法。它自 1997 年以来已被弃用,因为它跨时区工作不可靠。

为什么您的代码在您提到的月份中给出不正确的结果是因为它总是将一天计算为 24 小时。3 月 28 日,欧盟将过渡到夏令时 (DST),因此这一天只有 23 小时,因此会产生正好 1 小时的误差。今年 10 月 31 日可能会发生相反的过渡(我认为还没有决定,但 Java 认为已经决定了),所以这一天是 25 小时,以平衡之后的日期。直到明年暑假。

这就引出了下一点:不要自己做时间数学。太容易出错了。即使你做对了,读者也很难说服自己它是对的。你有一个可靠的日期和时间库,很乐意为你做这件事。

关联

Oracle 教程:日期时间解释如何使用 java.time。


推荐阅读