2

我正在尝试剥离字符串的每个时间单位,例如

字符串“4w10d50m39s”将返回 4 周的 TimeUnit、10 天的 TimeUnit、50 分钟的 TimeUnit 和 39 秒的 TimeUnit。

我怎样才能做到这一点?

上下文:我需要他们将所有转换为毫秒的时间单位相加并将其用作时间戳,它将在 Minecraft 服务器内部使用,用于在特定时间内为用户添加等级的命令,例如:/addrank iLalox Vip 4w5d,这会将到期日期设置为:System.currentMillis() + timeInMillis

4

2 回答 2

2

要提取单位,您可以使用正则表达式

\\d+[wdms]

演示

然后您可以使用matcher从字符串中提取匹配项并创建TimeUnits。中没有Week常数TimeUnit,所以我会amount of weeks * 7以天为单位表示周。

public static void main(String[] args) {
    String test = new String("4w10d50m39s");
    Pattern pattern = Pattern.compile("\\d+[wdms]");
    Matcher matcher = pattern.matcher(test);

    while(matcher.find()) {
        String unit = matcher.group();
        char timeType = unit.charAt(unit.length() - 1);
        int timeAmount = Integer.parseInt(unit.substring(0, unit.length() - 1));
        if(timeType == 'd') {
            System.out.println(TimeUnit.DAYS.toDays(timeAmount) + " DAYS");
        }

        if(timeType == 'm') {
            System.out.println(TimeUnit.MINUTES.toMinutes(timeAmount) + " MINUTES");
        }

        if(timeType == 's') {
            System.out.println(TimeUnit.SECONDS.toSeconds(timeAmount) + " SECONDS");
        }

        if(timeType == 'w') {
            System.out.println(TimeUnit.DAYS.toDays(timeAmount * 7L) + " DAYS IN WEEK");
        }
    }
}

输出:

28 DAYS IN WEEK
10 DAYS
50 MINUTES
39 SECONDS
于 2021-08-20T04:47:51.803 回答
1

来自 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第一个。作为进一步的变体,您可以使用PeriodDurationThreeTen Extra 项目中的类。我没有检查过,但我希望可以将 a 添加PeriodDuration到 a ,ZonedDateTime因为它很有意义。

我需要他们将所有转换为毫秒的时间单位相加并将其用作时间戳,......</p>

为此,您既不需要自己对单位求和,也不需要转换为毫秒。PeriodDuration解析更大的字符串块,并Instant.plus()直接接受Duration我们最终得到的对象。

链接

于 2021-08-20T18:23:23.297 回答