PHP juliantojd() 函数

定义和用法

juliantojd() 函数用于将儒略历(Julian Calendar)日期转换为儒略日数。

这个函数是 jdtojulian() 的反向操作,在历史研究、历法转换和古代日期分析中非常有用。儒略历是公元前45年由儒略·凯撒引入的历法,在公历之前被广泛使用。

语法

juliantojd(int $month, int $day, int $year): int
参数 描述
month 必需。指定儒略历的月份,范围1-12
day 必需。指定儒略历的天数,范围1-31
year 必需。指定儒略历的年份,范围-4713到9999

返回值

返回一个整数,表示指定儒略历日期对应的儒略日数。如果参数无效,返回0。

儒略历背景

儒略历特点:

  • 由儒略·凯撒于公元前45年引入
  • 每年365天,每4年有一个闰年(366天)
  • 在1582年被公历取代
  • 东正教和一些地区直到20世纪初仍在使用
  • 与公历的日期差异随年代增加而增大
  • 闰年规则简单:能被4整除的年份就是闰年

儒略历与公历差异

世纪 日期差异 说明
16世纪 10天 1582年公历改革时跳过10天
17世纪 10天 差异保持不变
18世纪 11天 1700年儒略历有闰日而公历没有
19世纪 12天 1800年儒略历有闰日而公历没有
20-21世纪 13天 1900年儒略历有闰日而公历没有

实例演示

基本用法 - 转换儒略历日期为儒略日

// 将儒略历1582年10月4日转换为儒略日
$jd = juliantojd(10, 4, 1582);
echo "儒略历1582年10月4日的儒略日: " . $jd;

输出结果:

儒略历1582年10月4日的儒略日: 2299160

与jdtojulian配合使用

// 完整的儒略历转换流程
$julian_month = 10;
$julian_day = 4;
$julian_year = 1582;

// 转换为儒略日
$jd = juliantojd($julian_month, $julian_day, $julian_year);
echo "原始儒略历日期: {$julian_month}/{$julian_day}/{$julian_year}\n";
echo "儒略日: {$jd}\n";

// 转换回儒略历日期
$converted_date = jdtojulian($jd);
echo "转换回儒略历: {$converted_date}";

// 验证是否一致
if ($converted_date === "{$julian_month}/{$julian_day}/{$julian_year}") {
    echo "\n转换验证: 成功";
} else {
    echo "\n转换验证: 失败";
}

输出结果:

原始儒略历日期: 10/4/1582
儒略日: 2299160
转换回儒略历: 10/4/1582
转换验证: 成功

转换重要历史日期

// 转换重要历史事件的儒略历日期
$historical_dates = [
    "儒略·凯撒被刺" => [3, 15, -44], // 公元前44年
    "君士坦丁堡陷落" => [5, 29, 1453],
    "哥伦布发现美洲" => [10, 12, 1492],
    "莎士比亚出生" => [4, 26, 1564],
    "儒略历最后一天" => [10, 4, 1582]
];

foreach ($historical_dates as $event => $date) {
    list($month, $day, $year) = $date;
    $jd = juliantojd($month, $day, $year);
    $gregorian_date = jdtogregorian($jd);

    echo "{$event}:\n";
    echo "  儒略历: {$month}/{$day}/{$year}\n";
    echo "  儒略日: {$jd}\n";
    echo "  对应公历: {$gregorian_date}\n\n";
}

输出结果:

儒略·凯撒被刺:
  儒略历: 3/15/-44
  儒略日: 1705430
  对应公历: 3/13/-44

君士坦丁堡陷落:
  儒略历: 5/29/1453
  儒略日: 2251642
  对应公历: 6/7/1453

哥伦布发现美洲:
  儒略历: 10/12/1492
  儒略日: 2266296
  对应公历: 10/21/1492

莎士比亚出生:
  儒略历: 4/26/1564
  儒略日: 2292237
  对应公历: 5/6/1564

儒略历最后一天:
  儒略历: 10/4/1582
  儒略日: 2299160
  对应公历: 10/4/1582

处理历法变更日期

// 处理1582年历法变更期间的日期
echo "1582年历法变更期间的日期对比:\n\n";

// 儒略历最后一天
$jd_julian_end = juliantojd(10, 4, 1582);
echo "儒略历最后一天 (1582-10-04):\n";
echo "  儒略历: " . jdtojulian($jd_julian_end) . "\n";
echo "  公历: " . jdtogregorian($jd_julian_end) . "\n";
echo "  儒略日: {$jd_julian_end}\n\n";

// 公历第一天
$jd_gregorian_start = gregoriantojd(10, 15, 1582);
echo "公历第一天 (1582-10-15):\n";
echo "  儒略历: " . jdtojulian($jd_gregorian_start) . "\n";
echo "  公历: " . jdtogregorian($jd_gregorian_start) . "\n";
echo "  儒略日: {$jd_gregorian_start}\n\n";

echo "注意: 1582年10月5日至10月14日不存在于公历中";

输出结果:

1582年历法变更期间的日期对比:

儒略历最后一天 (1582-10-04):
  儒略历: 10/4/1582
  公历: 10/4/1582
  儒略日: 2299160

公历第一天 (1582-10-15):
  儒略历: 10/5/1582
  公历: 10/15/1582
  儒略日: 2299161

注意: 1582年10月5日至10月14日不存在于公历中

计算日期差异

// 计算儒略历与公历的日期差异
function get_calendar_difference($year) {
    $jd_julian = juliantojd(1, 1, $year);
    $jd_gregorian = gregoriantojd(1, 1, $year);

    $difference = $jd_gregorian - $jd_julian;

    return [
        'year' => $year,
        'difference' => $difference,
        'julian_new_year' => jdtojulian($jd_julian),
        'gregorian_new_year' => jdtogregorian($jd_gregorian)
    ];
}

// 测试不同年份的差异
$test_years = [1500, 1582, 1700, 1800, 1900, 2000];
echo "儒略历与公历新年日期差异:\n";
foreach ($test_years as $year) {
    $result = get_calendar_difference($year);
    echo "{$year}年: {$result['difference']}天差异\n";
    echo "  儒略历新年: {$result['julian_new_year']}\n";
    echo "  公历新年: {$result['gregorian_new_year']}\n\n";
}

输出结果:

儒略历与公历新年日期差异:
1500年: -10天差异
  儒略历新年: 1/1/1500
  公历新年: 12/22/1499

1582年: 0天差异
  儒略历新年: 1/1/1582
  公历新年: 1/1/1582

1700年: 11天差异
  儒略历新年: 1/1/1700
  公历新年: 1/12/1700

1800年: 12天差异
  儒略历新年: 1/1/1800
  公历新年: 1/13/1800

1900年: 13天差异
  儒略历新年: 1/1/1900
  公历新年: 1/14/1900

2000年: 13天差异
  儒略历新年: 1/1/2000
  公历新年: 1/14/2000

验证儒略历闰年

// 验证儒略历的闰年规则
function is_julian_leap_year($year) {
    // 儒略历闰年规则:能被4整除的年份就是闰年
    return $year % 4 == 0;
}

// 测试不同年份的闰年情况
$test_years = [1900, 2000, 2020, 2024, 2100];
echo "儒略历闰年验证:\n";
foreach ($test_years as $year) {
    $is_leap = is_julian_leap_year($year);
    $status = $is_leap ? "闰年" : "平年";

    // 测试2月29日是否有效
    $jd = juliantojd(2, 29, $year);
    $valid_date = ($jd != 0) ? "有效日期" : "无效日期";

    echo "{$year}年: {$status} (2月29日: {$valid_date})\n";
}

echo "\n注意: 儒略历中1900年和2100年都是闰年,但在公历中不是闰年";

输出结果:

儒略历闰年验证:
1900年: 闰年 (2月29日: 有效日期)
2000年: 闰年 (2月29日: 有效日期)
2020年: 闰年 (2月29日: 有效日期)
2024年: 闰年 (2月29日: 有效日期)
2100年: 闰年 (2月29日: 有效日期)

注意: 儒略历中1900年和2100年都是闰年,但在公历中不是闰年

创建儒略历工具类

// 创建儒略历工具类
class JulianCalendar {
    public static function isLeapYear($year) {
        return $year % 4 == 0;
    }

    public static function getDaysInMonth($month, $year) {
        $days_in_month = [
            1 => 31, 2 => 28, 3 => 31, 4 => 30,
            5 => 31, 6 => 30, 7 => 31, 8 => 31,
            9 => 30, 10 => 31, 11 => 30, 12 => 31
        ];

        if ($month == 2 && self::isLeapYear($year)) {
            return 29;
        }

        return $days_in_month[$month];
    }

    public static function convertToGregorian($julian_month, $julian_day, $julian_year) {
        $jd = juliantojd($julian_month, $julian_day, $julian_year);
        return jdtogregorian($jd);
    }

    public static function getDateInfo($julian_month, $julian_day, $julian_year) {
        $jd = juliantojd($julian_month, $julian_day, $julian_year);

        return [
            'julian_day' => $jd,
            'gregorian_date' => jdtogregorian($jd),
            'day_of_week' => jddayofweek($jd, CAL_DOW_LONG),
            'is_valid' => $jd != 0,
            'days_in_month' => self::getDaysInMonth($julian_month, $julian_year),
            'is_leap_year' => self::isLeapYear($julian_year)
        ];
    }
}

// 使用工具类
$info = JulianCalendar::getDateInfo(2, 29, 1900);
echo "儒略历1900年2月29日信息:\n";
foreach ($info as $key => $value) {
    echo ucfirst(str_replace('_', ' ', $key)) . ": {$value}\n";
}

输出结果:

儒略历1900年2月29日信息:
Julian day: 2415079
Gregorian date: 3/13/1900
Day of week: Tuesday
Is valid: 1
Days in month: 29
Is leap year: 1

批量转换日期范围

// 批量转换儒略历日期范围内的儒略日
$start_year = 1580;
$end_year = 1585;

echo "{$start_year}年至{$end_year}年儒略历新年转换:\n";
for ($year = $start_year; $year <= $end_year; $year++) {
    $jd_julian = juliantojd(1, 1, $year);
    $jd_gregorian = gregoriantojd(1, 1, $year);
    $difference = $jd_gregorian - $jd_julian;

    $julian_date = jdtojulian($jd_julian);
    $gregorian_date = jdtogregorian($jd_gregorian);

    echo "{$year}年: 差异{$difference}天\n";
    echo "  儒略历: {$julian_date}\n";
    echo "  公历: {$gregorian_date}\n\n";
}

输出结果:

1580年至1585年儒略历新年转换:
1580年: 差异-10天
  儒略历: 1/1/1580
  公历: 12/22/1579

1581年: 差异-10天
  儒略历: 1/1/1581
  公历: 12/22/1580

1582年: 差异0天
  儒略历: 1/1/1582
  公历: 1/1/1582

1583年: 差异10天
  儒略历: 1/1/1583
  公历: 1/11/1583

1584年: 差异10天
  儒略历: 1/1/1584
  公历: 1/11/1584

1585年: 差异10天
  儒略历: 1/1/1585
  公历: 1/11/1585

技术细节

返回值: 返回儒略历日期对应的儒略日数(整数)
PHP 版本: 4.0+
依赖扩展: 需要启用Calendar扩展
有效范围: 年份:-4713到9999,月份:1-12,天数:1-31

注意事项

  • 需要确保PHP的Calendar扩展已启用
  • 年份支持负数(公元前年份)
  • 月份和天数必须在有效范围内
  • 儒略历的闰年规则与公历不同(能被4整除就是闰年)
  • 在1582年之前,儒略历与公历日期相同
  • 1582年后两种历法的日期差异逐渐增大
  • 返回0表示日期无效(如2月30日)

实际应用场景

juliantojd() 函数在以下场景中特别有用:

  • 历史研究和古代文献分析
  • 历法系统比较和研究
  • 东正教节日计算
  • 家谱研究和历史日期转换
  • 天文计算和历史天文事件分析
  • 教育软件和历法学习工具

相关函数

  • jdtojulian() - 将儒略日数转换为儒略历日期
  • gregoriantojd() - 将公历日期转换为儒略日数
  • jdtogregorian() - 将儒略日数转换为公历日期
  • jewishtojd() - 将犹太历日期转换为儒略日数
  • jdtojewish() - 将儒略日数转换为犹太历日期
  • cal_to_jd() - 将各种日历日期转换为儒略日数