前推格里曆

前推格里曆（Proleptic Gregorian Calendar），亦稱前公曆、 Proceptic 西曆、逆推格里曆，是將現行的格里曆（公曆）的置閏規則向前推算，應用於其正式頒布年份1582年之前的日期的曆法表達。這樣做是為了方便歷史年代的連續計算和表達，特別是在歷史學、天文學和計算領域。

根據國際標準化組織 ISO 8601:2004 標準（第3.2.1節），在資訊交換的合作夥伴同意的情況下，允許使用前推格里曆來表示1582年之前的日期。

## 歷史背景

格里曆由教宗額我略十三世在1582年頒布，用以取代儒略曆。儒略曆每4年一閏，平均年長為365.25日，這比實際的回歸年（約365.2422日）長了約11分14秒。這個微小的差異導致自公元325年第一次尼西亞公會議以來，春分日逐漸向更早的日期漂移。格里曆的改革調整了置閏規則（每400年少3個閏日），並一次性刪除了1582年10月中的10天（10月4日之後直接是10月15日），使春分日恢復到3月21日左右。

前推格里曆的概念，便是將格里曆的這些置閏規則應用到1582年之前，猶像格里曆在那時就已經存在並被使用。這為研究和記錄歷史事件提供了一個統一的年代標尺。

## 應用場景

### 歷史學

歷史學家在處理1582年之前的日期時，有時會使用前推格里曆來進行年代的標準化轉換，尤其是在需要比較不同地區、不同曆法記錄的事件時。然而，最佳實踐是首先記錄歷史文獻中使用的原始日期（註明所用曆法，如儒略曆「舊式」日期），然後再提供其對應的前推格里曆日期。

例如，美國首任總統喬治·華盛頓的生日，根據當時大英帝國（包括其美洲殖民地）使用的儒略曆以及以3月25日為新年起始日的紀年方式，記錄為1731年2月11日（舊式，O.S.）。大英帝國於1752年改用格里曆，並將新年起始日改為1月1日。若將華盛頓的生日按前推格里曆規則轉換，並考慮到新年起始日的調整，則為1732年2月22日。明確註明「舊式」與「新式」（或前推格里曆）對於避免混淆至關重要。

另一個例子是日本的神武天皇即位日。根據日本古籍《日本書紀》中的干支記載「辛酉年春正月庚辰朔」，明治時代的天文學家和歷算家將其比定為前推格里曆的公元前660年2月11日，並定為紀元節（後來的建國紀念之日）。此年代和日期的史實性在學術界有廣泛討論，但仍可作為前推格里曆應用的一個實例。

### 電腦與軟體

ISO 8601標準是日期和時間表示的國際標準，它在特定條件下允許使用前推格里曆。許多程式語言和資料庫系統為了簡化日期時間的處理，內部可能採用前推格里曆來表示歷史日期。例如：

- PostgreSQL 資料庫在處理日期時，對1582年之前的日期採用前推格里曆。
- MySQL 資料庫同樣支持歷史日期，其日曆系統從公元1年開始就遵循格里曆規則。
- SQLite 的日期和時間函數也能夠處理1582年之前的日期，其行為兼容前推格里曆。
- Python 的 `datetime` 模塊，其標準日曆演算法也是基於前推格里曆，可以表示從公元1年開始的日期。
- 微軟公司的編程基礎庫ATL的類 `COleDateTime` 支持從公元100年1月1日開始的日期，其行為模式也符合前推格里曆。

在這些系統中，1582年10月沒有日期間斷。

## 計算方法與規則

前推格里曆的計算規則與標準格里曆完全相同：

- 年份能被4整除但不能被100整除的是閏年（如2024年）。

- 年份能被400整除的是閏年（如2000年）。

- 其他年份為平年。

將此規則向前無限追溯即可得到任何年份的日數和日期。

### 公元元年及公元前年份

在歷史紀年中，通常沒有「公元0年」。公元1年之前是公元前1年。

然而，在天文學年份編號和ISO 8601標準中，為了方便計算，引入了公元0年，它對應於歷史上的公元前1年。更早的年份則用負數表示（例如，公元前2年對應天文學年份-1年）。

在這種編號系統中：

- 天文學的 0 年 (對應歷史上的公元前1年) 是閏年 (因為它相當於可以被4整除的年份，且適用格里曆規則)。
- 歷史上的公元前1年 (天文學0年)、公元前5年 (天文學-4年)、公元前9年 (天文學-8年) 等，如果按照格里曆規則判斷，都是閏年。

例如，要判斷歷史上的公元前 $y$ 年是否為前推格里曆閏年：

- 若使用天文學年份編號，則年份為 $-(y-1)$。若 $-(y-1)$ 符合格里曆閏年規則，則為閏年。

- 若直接使用公元前 $y$ 年，可以判斷 $y$ 是否符合「能被4整除但非整百年份，或能被400整除的整百年份」這一規律的反推（需注意BC年號越大，年份越早）。更簡便的是將其轉換為對應的天文學年份判斷。

### 儒略日

在實際計算中，尤其是需要跨越很長時間範圍或在不同曆法間轉換時，天文學家和程式設計師常使用儒略日（Julian Day Number, JDN）作為中間參照。JDN是一個自前推儒略曆公元前4713年1月1日世界時12:00起算的連續日數。任何日期都可以轉換為JDN，反之亦然。進行這種轉換時，必須明確指定所用的曆法是儒略曆還是（前推）格里曆。

例如，可以通過Fliegel與 Van Flandern 在1968年提出的演算法將格里曆日期（包括前推格里曆日期）轉換為JDN。(請注意：某些從JDN轉換回非常早期的前推格里曆日期的簡化演算法可能存在問題，特別是在公元400年之前，因此需要使用經過驗證的完整演算法。)

另一個概念是Rata Die系統，它將公元1年1月1日（前推格里曆）定義為第1天，並以此計算連續日數。一些編程系統使用此方法。

## 與儒略曆的差異

由於儒略曆和格里曆的置閏規則不同（儒略曆每4年一閏，格里曆每400年少3閏），隨著時間向前推移，兩者累積的日數差異會逐漸變化。

- 在公元4年至公元100年2月28日（儒略曆）期間，前推格里曆比儒略曆 慢2天。
- 從公元100年3月1日（儒略曆）至200年2月28日（儒略曆），前推格里曆比儒略曆 慢1天。
- 從公元200年3月1日（儒略曆）至300年2月28日（儒略曆），兩者日期 相同。
- 此後，每經過一個儒略曆的世紀年但非格里曆閏年的世紀年（如500年、600年、700年、900年、1000年、1100年、1300年、1400年、1500年），前推格里曆會比儒略曆快一天。
- 到1582年10月格里曆改革前夕，格里曆日期已比儒略曆日期快10天。

下表顯示了在首次正式引入公曆之前，儒略曆和前推公曆日期的區別：

儒略曆範圍｜公曆範圍｜公曆領先日數

4年3月3日（預期儒略曆的開始） 100年3月1日｜4年3月1日 100年2月28日｜-2日

100年3月2日 200年2月29日｜100年3月1日 200年2月28日｜-1日

200年3月1日 300年2月28日｜200年3月1日 300年2月28日｜0日

300年2月29日 500年2月27日｜300年3月1日 500年2月28日｜1日

500年2月28日 600年2月26日｜500年3月1日 600年2月28日｜2日

600年2月27日 700年2月25日｜600年3月1日 700年2月28日｜3日

700年2月26日 900年2月24日｜700年3月1日 900年2月28日｜4日

900年2月25日 1000年2月23日｜900年3月1日 1000年2月28日｜5日

1000年2月24日 1100年2月22日｜1000年3月1日 1100年2月28日｜6日

1100年2月23日 1300年2月21日｜1100年3月1日 1300年2月28日｜7日

1300年2月22日 1400年2月20日｜1300年3月1日 1400年2月28日｜8日

1400年2月21日 1500年2月19日｜1400年3月1日 1500年2月28日｜9日

1500年2月20日 1582年10月4日｜1500年3月1日 1582年10月14日｜10日

注意：上表假設儒略閏日為2月29日。然而，歷史上儒略曆的閏日（拉丁語：ante diem bis sextum Kalendas Martias）是通過重複2月24日來實現的（稱為「雙崗日」，bissextile day）。這意味著在儒略曆的閏年中，嚴格來說有兩個2月24日，這會影響2月24日至2月28日之間的日期計數。此外，儒略曆在公元前45年至公元4年之間的置閏並非規律的每四年一閏，存在「閏年錯誤」時期，直到公元4年（或有說公元8年）之後才穩定下來。

## 使用中的混淆點與注意事項

- 舊式與新式日期 (Old Style and New Style dates)：在格里曆被各國逐漸採用的過渡時期（1582年至20世紀初，如俄國到1918年，土耳其到1927年），同一歷史事件可能因地區不同而有不同的日期記錄。一些國家在改歷的同時，還將新年從3月25日（或其他日期）移至1月1日。這會導致年份和日期都發生變化，如前述喬治·華盛頓的生日例子，其儒略曆日期1731年2月11日不僅月份和日數不同于格里歷的2月22日，年份也因舊式以3月25日為新年起點而記為1731年，但在以1月1日為新年的格里曆中則屬於1732年。
- 公元0年的問題：如前所述，歷史紀年無公元0年，而天文學和ISO 8601有。使用時需明確是哪種體系。
- 史料的原始日期：研究歷史時，應首先採用史料中記載的原始日期和曆法，然後根據需要換算為前推格里曆日期，並加以註明。
- 軟體實現的差異：雖然許多系統聲稱支持前推格里曆，但其對非常早期日期（如公元前）的處理細節，特別是閏年規則和公元0年的處理，可能存在細微差別，需查閱具體文檔。一些簡單的日期計算代碼可能未完全實現格里曆的所有複雜規則（如整百年份的判斷），導致錯誤。