天文算法--复活节日期

复活节日期的计算

package cn.ancony.chinese_calendar;

/**
 * 计算指定年基督教复活节星期日(Easter Sunday)日期的方法
 */
public class EasterSunday {
    /**
     * 复活节星期日的推算规则:春分后(含春分)的第一次满月后的第一个星期日。
     * <p>
     * 在 1900 至 2100 年间,使用纯粹天文规则推算出了一些不同于教会规则的复活节星期日,这些年份是:
     * <p>
     * 1900,1903,1923,1924,1927,1943,1954,1962,1967,
     * 1974,1981,2038,2049,2069,2076,2089,2095,2096.
     *
     * @param year 年份,1582年(不含)后使用格里高利历,之前使用儒略历
     * @return 复活节日期
     */
    public static YearMonthDay easterSunday(int year) {
        return year > 1582 ? gregorian(year) : julian(year);
    }

    /**
     * 格里高利复活节
     * 适用于格里高利历中始自 1583 年的所有年份.
     * 格里高利历的复活节日期要 5700000 年才循环一次。有人发现格复活节最常见的日期是 4 月 19 日
     *
     * @param year 格里高利历年份
     * @return 日期
     */
    private static YearMonthDay gregorian(int year) {
        int
                a = year % 19, b = year / 100, c = year % 100, d = b / 4,
                e = b % 4, f = (b + 8) / 25, g = (b - f + 1) / 3,
                h = (19 * a + b - d - g + 15) % 30, i = c / 4, k = c % 4,
                l = (32 + 2 * e + 2 * i - h - k) % 7, m = (a + 11 * h + 22 * l) / 451,
                tmp = (h + l - 7 * m + 114), n = tmp / 31, p = tmp % 31;
        return YearMonthDay.of(year, n, p + 1);
    }

    /**
     * 儒略历复活节
     * 儒略历的复活节日期有为期 532 年的循环。比如,179 年,711 年和 1243 年的复活节都在 4 月 12 日
     *
     * @param year 儒略历年份
     * @return 日期
     */
    private static YearMonthDay julian(int year) {
        int a = year % 4, b = year % 7, c = year % 19, d = (19 * c + 15) % 30,
                e = (2 * a + 4 * b - d + 34) % 7,
                temp = d + e + 114, f = temp / 31, g = temp % 31;
        return YearMonthDay.of(year, f, g + 1);
    }
}

以下是测试类:

package cn.ancony.javafx.chinese_calendar;

import cn.ancony.chinese_calendar.EasterSunday;
import cn.ancony.chinese_calendar.YearMonthDay;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class TestEasterSunday {
    @ParameterizedTest
    @CsvSource({
            "3, 31, 1991",
            "4, 19, 1992",
            "4, 11, 1993",
            "4, 18, 1954",
            "4, 23, 2000",
            "3, 22, 1818",
            "3, 22, 2285",
            "4, 25, 1886",
            "4, 25, 1943",
            "4, 25, 2038",
            "4, 12,  179",
            "4, 12,  711",
            "4, 12, 1243"})
    public void test1(int month, int day, int year) {
        assertEquals(YearMonthDay.of(year, month, day), EasterSunday.easterSunday(year));
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值