You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求支持类JIRA时间格式的时间解析库:可转Millis并做timestamp运算

嘿,针对你要解析2y 1M 3w 4d 12h 20m 10s这种时间跨度字符串、转成毫秒后和时间戳做加减的需求,我给你几个实际项目里用过的靠谱方案,分语言给你说:

Java 8+ 原生方案(无需第三方库)

如果你用的是Java 8及以上版本,完全可以用自带的日期API搞定,只需要写个简单的正则解析逻辑就行。需要注意的是,年、月这类单位的时长不固定(比如2月有28/29天,闰年366天),必须基于给定的时间戳来计算才准确:

import java.time.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TimeSpanParser {
    // 匹配你的时间格式的正则
    private static final Pattern TIME_SPAN_PATTERN = Pattern.compile(
        "(?:(\\d+)y\\s?)?" +
        "(?:(\\d+)M\\s?)?" +
        "(?:(\\d+)w\\s?)?" +
        "(?:(\\d+)d\\s?)?" +
        "(?:(\\d+)h\\s?)?" +
        "(?:(\\d+)m\\s?)?" +
        "(?:(\\d+)s\\s?)?"
    );

    // 解析时间跨度并和时间戳做加法,减法的话把plus改成minus就行
    public static long calculateNewTimestamp(String timeSpan, long originalTimestamp) {
        Matcher matcher = TIME_SPAN_PATTERN.matcher(timeSpan.trim());
        if (!matcher.matches()) {
            throw new IllegalArgumentException("格式不对哦,得是类似2y 1M 3w这种格式");
        }

        // 把时间戳转成LocalDateTime,方便做时间加减
        LocalDateTime baseTime = Instant.ofEpochMilli(originalTimestamp)
                                        .atZone(ZoneId.systemDefault())
                                        .toLocalDateTime();

        // 逐个解析单位并做加减
        if (matcher.group(1) != null) baseTime = baseTime.plusYears(Long.parseLong(matcher.group(1)));
        if (matcher.group(2) != null) baseTime = baseTime.plusMonths(Long.parseLong(matcher.group(2)));
        if (matcher.group(3) != null) baseTime = baseTime.plusWeeks(Long.parseLong(matcher.group(3)));
        if (matcher.group(4) != null) baseTime = baseTime.plusDays(Long.parseLong(matcher.group(4)));
        if (matcher.group(5) != null) baseTime = baseTime.plusHours(Long.parseLong(matcher.group(5)));
        if (matcher.group(6) != null) baseTime = baseTime.plusMinutes(Long.parseLong(matcher.group(6)));
        if (matcher.group(7) != null) baseTime = baseTime.plusSeconds(Long.parseLong(matcher.group(7)));

        // 转回到毫秒时间戳
        return baseTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    // 示例用法
    public static void main(String[] args) {
        String timeSpan = "2y 1M 3w 4d 12h 20m 10s";
        long now = System.currentTimeMillis();
        long newTime = calculateNewTimestamp(timeSpan, now);
        System.out.println("原始时间戳:" + now);
        System.out.println("加完跨度后的时间戳:" + newTime);
    }
}
Java 7及以下:用Joda-Time库

如果还在维护Java 7的老项目,Joda-Time绝对是首选,它的时间处理API比原生的好用太多,而且能直接解析你这种格式:

import org.joda.time.*;
import org.joda.time.format.PeriodFormatter;
import org.joda.time.format.PeriodFormatterBuilder;

public class JodaTimeParser {
    private static final PeriodFormatter FORMATTER = new PeriodFormatterBuilder()
        .appendYears().appendSuffix("y ")
        .appendMonths().appendSuffix("M ")
        .appendWeeks().appendSuffix("w ")
        .appendDays().appendSuffix("d ")
        .appendHours().appendSuffix("h ")
        .appendMinutes().appendSuffix("m ")
        .appendSeconds().appendSuffix("s")
        .toFormatter();

    public static long calculateNewTimestamp(String timeSpan, long originalTimestamp) {
        Period period = FORMATTER.parsePeriod(timeSpan.trim());
        DateTime baseTime = new DateTime(originalTimestamp);
        // 减法的话用minus(period)
        return baseTime.plus(period).getMillis();
    }

    public static void main(String[] args) {
        String timeSpan = "2y 1M 3w 4d 12h 20m 10s";
        long now = System.currentTimeMillis();
        System.out.println("新时间戳:" + calculateNewTimestamp(timeSpan, now));
    }
}
Python 方案(原生库搞定)

Python的话,标准库datetime加正则就能解决,唯一需要注意的是timedelta不支持年、月,得手动处理:

import re
from datetime import datetime, timedelta

def calculate_new_timestamp(time_span, original_timestamp):
    pattern = re.compile(
        r'(?:(\d+)y\s?)?'
        r'(?:(\d+)M\s?)?'
        r'(?:(\d+)w\s?)?'
        r'(?:(\d+)d\s?)?'
        r'(?:(\d+)h\s?)?'
        r'(?:(\d+)m\s?)?'
        r'(?:(\d+)s\s?)?'
    )
    match = pattern.fullmatch(time_span.strip())
    if not match:
        raise ValueError("格式不对,请输入类似2y 1M 3w的字符串")

    # 把毫秒时间戳转成datetime(Python的timestamp是秒级,所以除以1000)
    base_dt = datetime.fromtimestamp(original_timestamp / 1000)

    # 处理年和月
    years = int(match.group(1)) if match.group(1) else 0
    months = int(match.group(2)) if match.group(2) else 0
    if years or months:
        new_year = base_dt.year + years
        new_month = base_dt.month + months
        # 处理月份溢出(比如12月加1月变成次年1月)
        new_year += (new_month - 1) // 12
        new_month = (new_month - 1) % 12 + 1
        # 处理日期超出当月天数的情况(比如3月31日加1月变成4月30日)
        try:
            base_dt = base_dt.replace(year=new_year, month=new_month)
        except ValueError:
            base_dt = base_dt.replace(year=new_year, month=new_month, day=1) + timedelta(days=32)
            base_dt = base_dt.replace(day=1) - timedelta(days=1)

    # 处理周、天、时、分、秒
    delta = timedelta(
        weeks=int(match.group(3)) if match.group(3) else 0,
        days=int(match.group(4)) if match.group(4) else 0,
        hours=int(match.group(5)) if match.group(5) else 0,
        minutes=int(match.group(6)) if match.group(6) else 0,
        seconds=int(match.group(7)) if match.group(7) else 0
    )
    new_dt = base_dt + delta  # 减法的话改成base_dt - delta
    # 转回毫秒时间戳
    return int(new_dt.timestamp() * 1000)

# 示例用法
if __name__ == "__main__":
    time_span = "2y 1M 3w 4d 12h 20m 10s"
    now = 1690000000000  # 示例毫秒时间戳
    print("新时间戳:", calculate_new_timestamp(time_span, now))
几个关键提醒
  • 年、月不能直接转固定毫秒:因为它们的时长不是固定值,必须基于具体的时间戳计算才准确。
  • 格式兼容:如果你的输入可能没有空格(比如2y1M3w),把正则里的\s?改成\s*或者直接去掉就行。
  • 减法运算:只需要把代码里的加法操作改成减法(比如Java的plus改成minus,Python的+改成-)。

内容的提问来源于stack exchange,提问作者mongolol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:51:54