ZetCode

Java IsoFields 类

最后修改时间:2025 年 4 月 16 日

java.time.temporal.IsoFields 类为 ISO-8601 日历系统提供了字段。它实现了基于周的字段,如年中的周和年中的季度。这些字段遵循 ISO 标准定义。

IsoFields 是一个实用程序类,具有静态字段和方法。它与时间对象(如 LocalDate 和 LocalDateTime)一起使用。该类帮助处理基于周和基于季度的日期计算。

IsoFields 类概述

IsoFields 定义了几个表示 ISO 字段的常量。这些包括年中的周、年中的季度和季度中的天。该类提供了访问和操作这些字段的方法。

public final class IsoFields {
    public static final TemporalField WEEK_OF_WEEK_BASED_YEAR;
    public static final TemporalField WEEK_BASED_YEAR;
    public static final TemporalField QUARTER_OF_YEAR;
    public static final TemporalField DAY_OF_QUARTER;
    
    public static TemporalUnit WEEK_BASED_YEARS;
    public static TemporalUnit QUARTER_YEARS;
}

代码显示了在 IsoFields 中定义的关键字段和单位。这些使您能够使用 ISO 周日期和季度。这些字段可用于 Java.time API 中的各种时间对象。

获取年中的周

ISO 年中的周与标准周编号不同。周从星期一开始,第 1 周包含一年中的第一个星期四。此示例显示了如何获取 ISO 周数。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.temporal.IsoFields;

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.of(2025, 1, 1);
        
        int weekOfYear = date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
        int weekBasedYear = date.get(IsoFields.WEEK_BASED_YEAR);
        
        System.out.println("Date: " + date);
        System.out.println("ISO Week of Year: " + weekOfYear);
        System.out.println("ISO Week-Based Year: " + weekBasedYear);
        
        // Edge case - date in different ISO year
        LocalDate edgeDate = LocalDate.of(2024, 12, 31);
        System.out.println("\nEdge case - Dec 31, 2024:");
        System.out.println("ISO Week of Year: " + 
            edgeDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR));
        System.out.println("ISO Week-Based Year: " + 
            edgeDate.get(IsoFields.WEEK_BASED_YEAR));
    }
}

此示例演示了 ISO 周编号。请注意,2025 年 1 月 1 日可能属于上一个 ISO 年的第 52 或 53 周。输出显示了正确的 ISO 周和年值。

使用季度

IsoFields 提供了与季度相关的字段。季度编号为 1 到 4,每个季度包含 3 个月。此示例显示了季度操作。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.temporal.IsoFields;

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.of(2025, 5, 15);
        
        int quarter = date.get(IsoFields.QUARTER_OF_YEAR);
        long dayOfQuarter = date.get(IsoFields.DAY_OF_QUARTER);
        
        System.out.println("Date: " + date);
        System.out.println("Quarter: " + quarter);
        System.out.println("Day of Quarter: " + dayOfQuarter);
        
        // Calculate quarter start and end
        LocalDate quarterStart = date.with(IsoFields.DAY_OF_QUARTER, 1);
        LocalDate quarterEnd = quarterStart.plus(2, IsoFields.QUARTER_YEARS)
                                         .minusDays(1);
        
        System.out.println("Quarter starts: " + quarterStart);
        System.out.println("Quarter ends: " + quarterEnd);
    }
}

该示例显示了特定日期的季度信息。它计算季度的开始和结束日期。请注意,QUARTER_YEARS 单位用于时间算术。

添加和减去周

基于 ISO 周的年份可用于时间计算。此示例显示了如何在保持 ISO 周编号的同时添加和减去周。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.temporal.IsoFields;

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.of(2025, 1, 1);
        System.out.println("Original date: " + date);
        
        // Add 2 weeks
        LocalDate plusWeeks = date.plus(2, IsoFields.WEEK_BASED_YEARS);
        System.out.println("After adding 2 weeks: " + plusWeeks);
        
        // Subtract 1 week
        LocalDate minusWeeks = date.minus(1, IsoFields.WEEK_BASED_YEARS);
        System.out.println("After subtracting 1 week: " + minusWeeks);
        
        // Week-based year difference
        LocalDate nextYear = LocalDate.of(2026, 1, 1);
        long weeksBetween = IsoFields.WEEK_BASED_YEARS.between(date, nextYear);
        System.out.println("Week-based years between: " + weeksBetween);
    }
}

此示例演示了基于周的计算。这些操作在跨年边界时保持正确的 ISO 周编号。between 方法计算基于周的年之间的差异。

使用 ISO 字段解析日期

ISO 字段可用于日期解析和格式化。此示例显示了如何使用 ISO 周字段创建格式化程序。

Main.java
package com.zetcode;

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

public class Main {

    public static void main(String[] args) {
        
        // Formatter with ISO week fields
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
            "YYYY-'W'ww-e");
        
        LocalDate date = LocalDate.of(2025, 1, 1);
        String formatted = date.format(formatter);
        System.out.println("Formatted date: " + formatted);
        
        // Parsing back
        LocalDate parsed = LocalDate.parse("2025-W01-3", formatter);
        System.out.println("Parsed date: " + parsed);
        
        // Verify fields
        System.out.println("ISO Week: " + 
            parsed.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR));
        System.out.println("Day of Week: " + parsed.getDayOfWeek());
    }
}

该示例使用 ISO 周模式格式化和解析日期。模式 'YYYY-'W'ww-e' 代表 ISO 年、周数和星期几。请注意大写 'W' 表示字面量,小写 'w' 表示周数。

计算季度日期

此示例演示了使用 IsoFields 的高级季度计算。它显示了如何查找季度边界并执行基于季度的算术运算。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.temporal.IsoFields;

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.of(2025, 8, 15);
        int currentQuarter = date.get(IsoFields.QUARTER_OF_YEAR);
        
        System.out.println("Current quarter: Q" + currentQuarter);
        
        // First day of quarter
        LocalDate quarterStart = date.with(IsoFields.DAY_OF_QUARTER, 1);
        System.out.println("Quarter starts: " + quarterStart);
        
        // Last day of quarter
        LocalDate nextQuarterStart = quarterStart.plus(1, IsoFields.QUARTER_YEARS);
        LocalDate quarterEnd = nextQuarterStart.minusDays(1);
        System.out.println("Quarter ends: " + quarterEnd);
        
        // Days remaining in quarter
        long daysRemaining = quarterEnd.toEpochDay() - date.toEpochDay();
        System.out.println("Days remaining in quarter: " + daysRemaining);
        
        // Add two quarters
        LocalDate futureDate = date.plus(2, IsoFields.QUARTER_YEARS);
        System.out.println("Date after two quarters: " + futureDate);
    }
}

该示例显示了全面的季度计算。它查找季度边界,计算剩余天数,并执行基于季度的算术运算。QUARTER_YEARS 单位确保了正确的季度过渡。

将 ISO 字段与其他时间字段组合

ISO 字段可以与标准时间字段组合以进行复杂的查询。此示例显示了混合字段的使用。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.temporal.IsoFields;
import java.time.temporal.ChronoField;

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.of(2025, 12, 31);
        
        // Mixed field access
        int year = date.get(ChronoField.YEAR);
        int isoWeekYear = date.get(IsoFields.WEEK_BASED_YEAR);
        int month = date.get(ChronoField.MONTH_OF_YEAR);
        int quarter = date.get(IsoFields.QUARTER_OF_YEAR);
        
        System.out.println("Date: " + date);
        System.out.println("Standard year: " + year);
        System.out.println("ISO week year: " + isoWeekYear);
        System.out.println("Month: " + month);
        System.out.println("Quarter: " + quarter);
        
        // Adjust date using mixed fields
        LocalDate adjusted = date.with(IsoFields.QUARTER_OF_YEAR, 2)
                               .with(ChronoField.DAY_OF_MONTH, 15);
        System.out.println("Adjusted date: " + adjusted);
        
        // Complex query
        boolean isLastWeekOfQuarter = 
            date.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) % 13 == 0;
        System.out.println("Is last week of quarter: " + isLastWeekOfQuarter);
    }
}

此示例将 ISO 字段与标准时间字段结合使用。它演示了如何在查询和调整中混合不同的字段类型。复杂的查询显示了多个字段的实际用法。

来源

Java IsoFields 类文档

在本文中,我们涵盖了 Java IsoFields 类的基本方法和功能。了解这些概念对于在 Java 应用程序中使用 ISO 周日期和季度至关重要。

作者

我的名字是 Jan Bodnar,我是一位敬业的程序员,在该领域拥有多年的经验。我从 2007 年开始撰写编程文章,此后撰写了 1,400 多篇文章和八本电子书。凭借超过八年的教学经验,我致力于分享我的知识并帮助他人掌握编程概念。

列出所有Java教程