181 lines
4.7 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright 2024 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package xyz.zhouxy.plusone.commons.time;
import java.time.Month;
import java.time.MonthDay;
import java.time.temporal.ChronoField;
import com.google.common.collect.Range;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
/**
* 季度
*
* @author <a href="http://zhouxy.xyz:3000/ZhouXY108">ZhouXY</a>
*/
public enum Quarter {
/** 第一季度 */
Q1(1),
/** 第二季度 */
Q2(2),
/** 第三季度 */
Q3(3),
/** 第四季度 */
Q4(4),
;
/** 季度值 (1/2/3/4) */
private final int value;
private final Range<Integer> monthRange;
/** 常量值 */
private static final Quarter[] ENUMS = Quarter.values();
/**
* @param value 季度值 (1/2/3/4)
*/
Quarter(int value) {
this.value = value;
final int lastMonth = value * 3;
final int firstMonth = lastMonth - 2;
this.monthRange = Range.closed(firstMonth, lastMonth);
}
// StaticFactoryMethods
/**
* 根据给定的月份值返回对应的季度
*
* @param monthValue 月份值取值范围为1到12
* @return 对应的季度
* @throws IllegalArgumentException 如果月份值不在有效范围内1到12将抛出异常
*/
@StaticFactoryMethod(Quarter.class)
public static Quarter fromMonth(int monthValue) {
ChronoField.MONTH_OF_YEAR.checkValidValue(monthValue);
return of(computeQuarterValueInternal(monthValue));
}
/**
* 根据给定的月份返回对应的季度
*
* @param month 月份
* @return 对应的季度
*/
@StaticFactoryMethod(Quarter.class)
public static Quarter fromMonth(Month month) {
final int monthValue = month.getValue();
return of(computeQuarterValueInternal(monthValue));
}
/**
* 根据指定的年份,获取一个新的 YearQuarter 实例
* 此方法允许在保持当前季度信息不变的情况下,更改年份
*
* @param year 指定的年份
* @return 返回一个新的 YearQuarter 实例,年份更新为指定的年份
*/
public final YearQuarter atYear(int year) {
return YearQuarter.of(year, this);
}
/**
* 根据给定的季度值返回对应的季度
*
* @param value 季度值 (1/2/3/4)
* @return 对应的季度
* @throws IllegalArgumentException 如果季度值不在有效范围内1到4将抛出异常
*/
@StaticFactoryMethod(Quarter.class)
public static Quarter of(int value) {
if (value < 1 || value > 4) {
throw new IllegalArgumentException("Invalid value for Quarter: " + value);
}
return ENUMS[value - 1];
}
// StaticFactoryMethods end
// computes
public Quarter plus(long quarters) { // TODO 单元测试
final int amount = (int) ((quarters % 4) + 4);
return ENUMS[(ordinal() + amount) % 4];
}
public Quarter minus(long quarters) { // TODO 单元测试
return plus(-(quarters % 4));
}
// computes end
// Getters
public int getValue() {
return value;
}
public Month firstMonth() {
return Month.of(firstMonthValue());
}
public int firstMonthValue() {
return this.monthRange.lowerEndpoint();
}
public Month lastMonth() {
return Month.of(lastMonthValue());
}
public int lastMonthValue() {
return this.monthRange.upperEndpoint();
}
public MonthDay firstMonthDay() {
return MonthDay.of(firstMonth(), 1);
}
public MonthDay lastMonthDay() {
// 季度的最后一个月不可能是 2 月
final Month month = lastMonth();
return MonthDay.of(month, month.maxLength());
}
public int firstDayOfYear(boolean leapYear) {
return firstMonth().firstDayOfYear(leapYear);
}
// Getters end
// Internal
/**
* 计算给定月份对应的季度值
*
* @param monthValue 月份值取值范围为1到12
* @return 对应的季度值
*/
private static int computeQuarterValueInternal(int monthValue) {
return (monthValue - 1) / 3 + 1;
}
}