ZetCode

Java WeekFields 类

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

java.time.temporal.WeekFields 类定义了基于周的计算规则。它指定了如何计算周,以及如何确定诸如年内周数之类的基于周的字段。WeekFields 对于特定于区域设置的周处理至关重要。

WeekFields 是不可变的且线程安全的。它提供了对与周相关的时态字段(如月内周数和年内周数)的访问。该类处理不同地区和标准中周定义的差异。

WeekFields 类概述

WeekFields 提供了访问基于周的时态字段的方法。关键组件包括一周的第一天和第一周的最小天数。这些设置会影响日期计算中的周编号。

public final class WeekFields implements Serializable {
    public static WeekFields of(Locale locale);
    public static WeekFields of(DayOfWeek firstDayOfWeek, int minimalDays);
    public DayOfWeek getFirstDayOfWeek();
    public int getMinimalDaysInFirstWeek();
    public TemporalField dayOfWeek();
    public TemporalField weekOfMonth();
    public TemporalField weekOfYear();
    public TemporalField weekOfWeekBasedYear();
}

上面的代码显示了 WeekFields 提供的关键方法。这些方法允许创建周定义并访问与周相关的字段。该类支持 ISO 和特定于区域设置的周定义。

创建 WeekFields 对象

可以使用区域设置或显式参数创建 WeekFields 对象。基于区域设置的方法会自动使用区域周约定。显式创建允许自定义周定义。

Main.java
package com.zetcode;

import java.time.DayOfWeek;
import java.time.temporal.WeekFields;
import java.util.Locale;

public class Main {

    public static void main(String[] args) {
        
        // Using locale (US starts week on Sunday)
        WeekFields usWeekFields = WeekFields.of(Locale.US);
        System.out.println("US first day: " + 
            usWeekFields.getFirstDayOfWeek());
        
        // Using ISO standard (Monday)
        WeekFields isoWeekFields = WeekFields.ISO;
        System.out.println("ISO first day: " + 
            isoWeekFields.getFirstDayOfWeek());
        
        // Custom week definition
        WeekFields customWeekFields = WeekFields.of(
            DayOfWeek.TUESDAY, 4);
        System.out.println("Custom first day: " + 
            customWeekFields.getFirstDayOfWeek());
    }
}

此示例演示了创建 WeekFields 对象的不同方法。美国区域设置使用星期日作为第一天,而 ISO 使用星期一。自定义定义允许使用任何日期,并指定第一周的最小天数。

获取基于周的字段

WeekFields 提供了对几个与周相关的时态字段的访问。这些字段可以与时态对象一起使用以获取周数。这些字段包括年内周数和月内周数。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.Locale;

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.of(2025, 1, 15);
        WeekFields weekFields = WeekFields.of(Locale.US);
        
        // Get week-based fields
        int weekOfYear = date.get(weekFields.weekOfYear());
        int weekOfMonth = date.get(weekFields.weekOfMonth());
        int dayOfWeek = date.get(weekFields.dayOfWeek());
        
        System.out.println("Week of year: " + weekOfYear);
        System.out.println("Week of month: " + weekOfMonth);
        System.out.println("Day of week: " + dayOfWeek);
    }
}

此示例显示了如何从 LocalDate 获取基于周的值。周编号取决于 WeekFields 的配置。一周中的日期根据一周的第一天返回 1 到 7 之间的数字。

比较周定义

不同的区域设置和标准有不同的周定义。WeekFields 使得比较这些差异变得容易。相同的日期在不同的系统下可能具有不同的周数。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.Locale;

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.of(2025, 1, 1);
        
        // US week fields
        WeekFields usFields = WeekFields.of(Locale.US);
        int usWeek = date.get(usFields.weekOfYear());
        
        // ISO week fields
        WeekFields isoFields = WeekFields.ISO;
        int isoWeek = date.get(isoFields.weekOfYear());
        
        System.out.println("US week of year: " + usWeek);
        System.out.println("ISO week of year: " + isoWeek);
        
        // France uses Monday as first day
        WeekFields frFields = WeekFields.of(Locale.FRANCE);
        int frWeek = date.get(frFields.weekOfYear());
        System.out.println("France week of year: " + frWeek);
    }
}

此示例比较了美国、ISO 和法国系统之间的周编号。同一日期(2025 年 1 月 1 日)根据定义落在不同的周内。ISO 周数范围从 1 到 53。

使用基于周的年份

WeekFields 支持基于周的年份计算。基于周的年份与标准日历年份不同。它对于需要基于周的报告期的应用程序很有用。

Main.java
package com.zetcode;

import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.Locale;

public class Main {

    public static void main(String[] args) {
        
        LocalDate date = LocalDate.of(2025, 1, 1);
        WeekFields weekFields = WeekFields.ISO;
        
        // Get week-based year
        int weekBasedYear = date.get(weekFields.weekBasedYear());
        int weekOfWeekBasedYear = date.get(
            weekFields.weekOfWeekBasedYear());
        
        System.out.println("Week-based year: " + weekBasedYear);
        System.out.println("Week of week-based year: " + 
            weekOfWeekBasedYear);
        
        // Edge case where dates belong to different week-based years
        LocalDate edgeDate = LocalDate.of(2024, 12, 31);
        int edgeYear = edgeDate.get(weekFields.weekBasedYear());
        System.out.println("Dec 31, 2024 week-based year: " + edgeYear);
    }
}

此示例演示了基于周的年份计算。对于 12 月底或 1 月初的日期,基于周的年份可能与日历年份不同。ISO 基于周的年份有 52 或 53 周。

自定义周定义

WeekFields 允许创建自定义周定义。这对于具有非标准周配置的业务应用程序很有用。自定义定义指定第一天和第一周的最小天数。

Main.java
package com.zetcode;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.WeekFields;

public class Main {

    public static void main(String[] args) {
        
        // Custom week starting Wednesday with 5 days in first week
        WeekFields customFields = WeekFields.of(
            DayOfWeek.WEDNESDAY, 5);
        
        LocalDate date = LocalDate.of(2025, 1, 1);
        
        System.out.println("Custom week of year: " + 
            date.get(customFields.weekOfYear()));
        System.out.println("Custom day of week: " + 
            date.get(customFields.dayOfWeek()));
        
        // First week must have at least 5 days in this year
        LocalDate firstWeekDate = LocalDate.of(2025, 1, 7);
        System.out.println("Jan 7 week of year: " + 
            firstWeekDate.get(customFields.weekOfYear()));
    }
}

此示例显示了从星期三开始的自定义周定义。最小天数参数会影响一年中第一周的开始时间。自定义周定义对于专业的业务需求很有用。

WeekFields 与 TemporalAdjusters

WeekFields 可以与时态调整器结合使用以进行高级日期操作。这允许进行操作,例如查找一周的第一天/最后一天或跳转到特定周。

Main.java
package com.zetcode;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.time.temporal.WeekFields;
import java.util.Locale;

public class Main {

    public static void main(String[] args) {
        
        WeekFields weekFields = WeekFields.of(Locale.US);
        LocalDate date = LocalDate.of(2025, 1, 15);
        
        // Adjust to first day of week (Sunday in US)
        LocalDate firstDay = date.with(
            TemporalAdjusters.previousOrSame(
                weekFields.getFirstDayOfWeek()));
        System.out.println("First day of week: " + firstDay);
        
        // Adjust to last day of week (Saturday in US)
        LocalDate lastDay = date.with(
            TemporalAdjusters.nextOrSame(
                DayOfWeek.SATURDAY));
        System.out.println("Last day of week: " + lastDay);
        
        // Jump to same week in next year
        int weekNumber = date.get(weekFields.weekOfYear());
        LocalDate nextYearSameWeek = date.plusYears(1)
            .with(weekFields.weekOfYear(), weekNumber);
        System.out.println("Same week next year: " + nextYearSameWeek);
    }
}

此示例演示了将 WeekFields 与时态调整器结合使用。操作包括查找周边界和跨年维护周数。这些技术对于日历应用程序和报告很有用。

来源

Java WeekFields 类文档

在本文中,我们介绍了 Java WeekFields 类的基本方法和特性。理解这些概念对于在国际化的 Java 应用程序中进行准确的周处理至关重要。

作者

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

列出所有Java教程