ZetCode

Java YearMonth 类

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

java.time.YearMonth 类表示年和月的组合,没有日或时间信息。它是 Java 8 中引入的 Java 现代日期时间 API 的一部分。YearMonth 是不可变的,并且是线程安全的。

YearMonth 适用于表示信用卡到期日、订阅期限,或任何需要年-月精度的场景。它会自动处理月份长度和闰年。该类遵循 ISO-8601 标准。

YearMonth 类概述

YearMonth 提供了创建、解析和操作年-月值的方法。关键操作包括获取月份长度、比较值和格式化输出。该类支持对月份和年份的算术运算。

public final class YearMonth implements Temporal, TemporalAdjuster, 
    Comparable<YearMonth>, Serializable {
    public static YearMonth now();
    public static YearMonth of(int year, Month month);
    public static YearMonth of(int year, int month);
    public static YearMonth parse(CharSequence text);
    public int getYear();
    public Month getMonth();
    public int lengthOfMonth();
    public boolean isLeapYear();
    public boolean isAfter(YearMonth other);
    public boolean isBefore(YearMonth other);
    public YearMonth plus(long amountToAdd, TemporalUnit unit);
    public YearMonth minus(long amountToSubtract, TemporalUnit unit);
}

上面的代码显示了 YearMonth 提供的关键方法。这些方法允许创建、比较和操作年-月值。该类处理特定于月份的计算,例如确定月份长度。

创建 YearMonth 对象

YearMonth 对象可以通过多种方式创建。最常用的方法是 now 获取当前年-月,以及用于特定值的工厂方法。也支持从字符串解析。

Main.java
package com.zetcode; 

import java.time.Month;
import java.time.YearMonth;

public class Main {

    public static void main(String[] args) {
        
        // Current year-month
        YearMonth current = YearMonth.now();
        System.out.println("Current year-month: " + current);
        
        // From year and month enum
        YearMonth ym1 = YearMonth.of(2025, Month.JANUARY);
        System.out.println("From enum: " + ym1);
        
        // From year and month number
        YearMonth ym2 = YearMonth.of(2025, 2);
        System.out.println("From numbers: " + ym2);
        
        // From string
        YearMonth parsed = YearMonth.parse("2025-03");
        System.out.println("Parsed from string: " + parsed);
    }
}

此示例演示了创建 YearMonth 对象的不同方法。输出显示 ISO-8601 格式的值 (yyyy-MM)。now 方法使用系统时钟和默认时区。

获取 YearMonth 组件

一个 YearMonth 可以分解成它的年和月组件。这些值可以作为数字或 Month 枚举值检索。该类还提供了检查月份长度和闰年的方法。

Main.java
package com.zetcode; 

import java.time.YearMonth;

public class Main {

    public static void main(String[] args) {

        YearMonth ym = YearMonth.of(2025, 2);
        
        // Get year
        int year = ym.getYear();
        System.out.println("Year: " + year);
        
        // Get month as enum
        System.out.println("Month: " + ym.getMonth());
        
        // Get month as number
        System.out.println("Month value: " + ym.getMonthValue());
        
        // Get month length
        System.out.println("Days in month: " + ym.lengthOfMonth());
        
        // Check leap year
        System.out.println("Is leap year: " + ym.isLeapYear());
    }
}

此示例显示了如何从 YearMonth 提取组件。请注意,lengthOfMonth 考虑了二月的闰年。月份可以作为枚举或数值检索。

比较 YearMonth 值

可以比较 YearMonth 值以确定时间顺序。该类提供了 isBeforeisAftercompareTo 方法。这些比较对于日期范围验证很有用。

Main.java
package com.zetcode; 

import java.time.YearMonth;

public class Main {

    public static void main(String[] args) {

        YearMonth current = YearMonth.now();
        YearMonth future = current.plusMonths(3);
        YearMonth past = current.minusYears(1);
        
        System.out.println("Current is before future: " + current.isBefore(future));
        System.out.println("Current is after past: " + current.isAfter(past));
        System.out.println("Comparison result: " + current.compareTo(future));
        
        // Equality check
        YearMonth copy = YearMonth.of(current.getYear(), current.getMonthValue());
        System.out.println("Current equals copy: " + current.equals(copy));
    }
}

此示例演示了比较 YearMonth 对象的各种方法。比较方法同时考虑了年和月组件。请注意,相等需要两个组件完全匹配。

添加和减去时间

YearMonth 通过 plusminus 方法支持时间算术。这些操作对于计算未来或过去的年-月值很有用。该类正确处理年和月的边界。

Main.java
package com.zetcode; 

import java.time.YearMonth;
import java.time.temporal.ChronoUnit;

public class Main {

    public static void main(String[] args) {

        YearMonth ym = YearMonth.of(2025, 1);
        
        // Add months
        YearMonth nextMonth = ym.plusMonths(1);
        System.out.println("Next month: " + nextMonth);
        
        // Subtract years
        YearMonth lastYear = ym.minusYears(1);
        System.out.println("Last year: " + lastYear);
        
        // Add using ChronoUnit
        YearMonth inTwoMonths = ym.plus(2, ChronoUnit.MONTHS);
        System.out.println("In two months: " + inTwoMonths);
        
        // Complex operation
        YearMonth result = ym.plusYears(2).minusMonths(3);
        System.out.println("Complex operation result: " + result);
    }
}

此示例显示了使用 YearMonth 执行时间算术的各种方法。操作可以使用便捷方法或 ChronoUnit 常量。所有计算都会自动处理年和月的进位。

转换为其他日期类型

YearMonth 可以转换为其他时间类型,如 LocalDate。当您需要处理该月中的特定日期或与其他日期组件组合时,这些转换至关重要。

Main.java
package com.zetcode; 

import java.time.LocalDate;
import java.time.YearMonth;

public class Main {

    public static void main(String[] args) {

        YearMonth ym = YearMonth.of(2025, 2);
        
        // Convert to LocalDate (first day of month)
        LocalDate firstDay = ym.atDay(1);
        System.out.println("First day: " + firstDay);
        
        // Convert to LocalDate (last day of month)
        LocalDate lastDay = ym.atEndOfMonth();
        System.out.println("Last day: " + lastDay);
        
        // Convert from LocalDate
        YearMonth fromDate = YearMonth.from(LocalDate.of(2025, 3, 15));
        System.out.println("From LocalDate: " + fromDate);
    }
}

此示例演示了 YearMonth 和 LocalDate 之间的转换。atDayatEndOfMonth 方法特别有用。从 LocalDate 转换仅提取年和月组件。

格式化和解析

YearMonth 通过 DateTimeFormatter 类支持格式化和解析。这允许根据各种模式和语言环境进行灵活的输入/输出格式化。

Main.java
package com.zetcode; 

import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {

    public static void main(String[] args) {

        YearMonth ym = YearMonth.of(2025, 4);
        
        // Default format (ISO)
        System.out.println("ISO format: " + ym);
        
        // Custom format
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/yyyy");
        System.out.println("Custom format: " + ym.format(formatter));
        
        // Localized format
        DateTimeFormatter frenchFormatter = 
            DateTimeFormatter.ofPattern("MMMM yyyy", Locale.FRENCH);
        System.out.println("French format: " + ym.format(frenchFormatter));
        
        // Parse custom format
        YearMonth parsed = YearMonth.parse("05-2025", 
            DateTimeFormatter.ofPattern("MM-yyyy"));
        System.out.println("Parsed custom format: " + parsed);
    }
}

此示例显示了如何使用不同的模式和语言环境格式化和解析 YearMonth 值。DateTimeFormatter 提供了广泛的格式化选项。解析处理标准和自定义格式。

来源

Java YearMonth 类文档

在本文中,我们介绍了 Java YearMonth 类的基本方法和特性。理解这些概念对于在现代 Java 应用程序中进行准确的年-月处理至关重要。

作者

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

列出所有Java教程