来自 java.time 的 Period、Duration 和 Instant
我建议您使用现代 Java 日期和时间 API java.time 进行日期和时间工作。假设您的到期时间是实时的(不是 Minecraft 时间):
String string = "4w10d50m39s";
String dayBasedString
= string.replaceFirst("(^(?:\\d+w)?(?:\\d+d)?).*$", "$1");
String timeBasedString = string.substring(dayBasedString.length());
Period period = dayBasedString.isEmpty()
? Period.ZERO
: Period.parse("P" + dayBasedString);
assert period.getYears() == 0 : period;
assert period.getMonths() == 0 : period;
Duration dur = timeBasedString.isEmpty()
? Duration.ZERO
: Duration.parse("PT" + timeBasedString);
dur = Duration.ofDays(period.getDays()).plus(dur);
Instant now = Instant.now();
Instant expiration = now.plus(dur);
System.out.format("Now: %s; expiration: %s%n", now, expiration);
我刚才运行代码段时的输出:
现在:2021-08-20T18:24:35.701136Z; 到期:2021-09-27T19:15:14.701136Z
Java 有Period
基于日期的类和基于Duration
时间的类。由于您的字符串是两者,我正在使用这两个类。以及Instant
班级的某个时间点,例如您的等级到期时间。
该类Period
可以本地解析 String like P4w10d
,并且Duration
类一个 like PT50m39s
。挑战是在几周和几天之后以及小时、分钟和秒之前分割你的字符串。我的正则表达式匹配包含周和/或天的字符串的任何(可能为空)部分,并将这部分复制到一个单独的变量中。然后将其余部分复制到另一个变量并不那么复杂。APeriod
可能包含年、月和日(周会自动转换为日)。为了使我的以下计算起作用,我需要假设没有年或月,因为我不知道那是多少天。我还假设一天是 24 小时,即使在现实生活中并非总是如此。
作为一种变体,您可以将 aZonedDateTime
用于当前时间。优点是您可以直接先添加 aPeriod
再添加 a Duration
,而无需将周和天转换为Duration
第一个。作为进一步的变体,您可以使用PeriodDuration
ThreeTen Extra 项目中的类。我没有检查过,但我希望可以将 a 添加PeriodDuration
到 a ,ZonedDateTime
因为它很有意义。
我需要他们将所有转换为毫秒的时间单位相加并将其用作时间戳,......</p>
为此,您既不需要自己对单位求和,也不需要转换为毫秒。Period
并Duration
解析更大的字符串块,并Instant.plus()
直接接受Duration
我们最终得到的对象。
链接