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

Java中是否存在支持ISO 8601周的类及基础时间操作?

Java 11+ 处理ISO 8601周数据的方案

Java标准库(Java 11及以上)没有专门用于表示ISO 8601周格式(如2012-W48)的内置类,但可以通过两种方式实现你需要的时间操作:

方案一:基于LocalDate扩展实现

利用LocalDate结合DateTimeFormatter.ISO_WEEK_DATE解析,默认补全周内的具体日期(ISO周的第一天为周一,补-1即可),再通过标准时间API完成比较和间隔计算。

1. 解析周字符串

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class WeekUtils {
    private static final DateTimeFormatter ISO_WEEK_FORMATTER = DateTimeFormatter.ISO_WEEK_DATE;

    // 解析ISO周字符串,默认取周的第一天(周一)
    public static LocalDate parseToWeekStart(String weekStr) {
        return LocalDate.parse(weekStr + "-1", ISO_WEEK_FORMATTER);
    }
}

2. 周比较

直接使用LocalDate的isBefore/isAfter方法,周起始日期的先后即可代表整个周的先后:

LocalDate weekAStart = WeekUtils.parseToWeekStart("2012-W48");
LocalDate weekBStart = WeekUtils.parseToWeekStart("2013-W03");

boolean weekABeforeWeekB = weekAStart.isBefore(weekBStart); // 返回true

3. 计算间隔周数

使用ChronoUnit.WEEKS.between方法计算两个周起始日的间隔:

import java.time.temporal.ChronoUnit;

long weeksInterval = ChronoUnit.WEEKS.between(weekAStart, weekBStart); // 返回5

方案二:自定义ISOWeek类(更贴合需求)

如果需要更直观的周对象表示,可以自定义一个ISOWeek类,封装年份和周数,实现比较和间隔计算逻辑,完全基于Java标准库:

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.time.temporal.WeekFields;
import java.util.Objects;

public class ISOWeek implements Comparable<ISOWeek> {
    private final int year;
    private final int week;
    private static final WeekFields ISO_WEEK_FIELDS = WeekFields.ISO;

    public ISOWeek(int year, int week) {
        if (week < 1 || week > ISO_WEEK_FIELDS.getWeekOfYear().range().getMaximum()) {
            throw new IllegalArgumentException("无效周数: " + week);
        }
        this.year = year;
        this.week = week;
    }

    // 从ISO周字符串解析
    public static ISOWeek parse(String weekStr) {
        String[] parts = weekStr.split("-W");
        if (parts.length != 2) {
            throw new IllegalArgumentException("无效ISO周格式: " + weekStr);
        }
        return new ISOWeek(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]));
    }

    // 判断当前周是否早于另一个周
    public boolean isBefore(ISOWeek other) {
        return compareTo(other) < 0;
    }

    // 判断当前周是否晚于另一个周
    public boolean isAfter(ISOWeek other) {
        return compareTo(other) > 0;
    }

    // 计算与另一个周的间隔周数
    public long weeksBetween(ISOWeek other) {
        LocalDate thisWeekStart = LocalDate.of(year, 1, 1)
                .with(ISO_WEEK_FIELDS.weekOfYear(), week)
                .with(ISO_WEEK_FIELDS.dayOfWeek(), 1);
        LocalDate otherWeekStart = LocalDate.of(other.year, 1, 1)
                .with(ISO_WEEK_FIELDS.weekOfYear(), other.week)
                .with(ISO_WEEK_FIELDS.dayOfWeek(), 1);
        return ChronoUnit.WEEKS.between(thisWeekStart, otherWeekStart);
    }

    @Override
    public int compareTo(ISOWeek other) {
        if (year != other.year) {
            return Integer.compare(year, other.year);
        }
        return Integer.compare(week, other.week);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ISOWeek isoWeek = (ISOWeek) o;
        return year == isoWeek.year && week == isoWeek.week;
    }

    @Override
    public int hashCode() {
        return Objects.hash(year, week);
    }

    @Override
    public String toString() {
        return String.format("%04d-W%02d", year, week);
    }
}

使用示例

ISOWeek weekA = ISOWeek.parse("2012-W48");
ISOWeek weekB = ISOWeek.parse("2013-W03");

System.out.println(weekA.isBefore(weekB)); // 输出true
System.out.println(weekA.weeksBetween(weekB)); // 输出5

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 04:10:58