java - 倒计时在 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";
解决方案
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 秒
你的代码出了什么问题?
首先,不要使用SimpleDateFormat
and,Date
因为它们设计不佳且早已过时。即使你坚持使用Date
,你也绝对应该远离它的getTimezoneOffset
方法。它自 1997 年以来已被弃用,因为它跨时区工作不可靠。
为什么您的代码在您提到的月份中给出不正确的结果是因为它总是将一天计算为 24 小时。3 月 28 日,欧盟将过渡到夏令时 (DST),因此这一天只有 23 小时,因此会产生正好 1 小时的误差。今年 10 月 31 日可能会发生相反的过渡(我认为还没有决定,但 Java 认为已经决定了),所以这一天是 25 小时,以平衡之后的日期。直到明年暑假。
这就引出了下一点:不要自己做时间数学。太容易出错了。即使你做对了,读者也很难说服自己它是对的。你有一个可靠的日期和时间库,很乐意为你做这件事。
关联
Oracle 教程:日期时间解释如何使用 java.time。
推荐阅读
- sql - 如何强制 Postgres 以数值精度计算
- c# - 添加列表
作为现有列表的新元组 > - sql - Django ORM 二进制精确
- google-chrome - 如何从 Chrome 访问 github.com/lucas-clemente/quic-go 服务器?
- jwt - 我有模数和指数如何使用 JavaScript 为某些有效负载生成 JWE
- c# - 如何在值对象中删除值对象 [DDD]
- javascript - VueJS:未捕获的类型错误:vue__WEBPACK_IMPORTED_MODULE_4__.default 不是构造函数
- python - 将顺序数据从 .txt 文件转换为数据框
- java - Gradle:是否可以在 gradle 插件中定义 CustomTask 并从 build.gradle 中扩展该类?
- machine-learning - NLP 用于结构化数据和映射值