中國的農曆同時考慮到月球繞行地球與地球繞行太陽的情形,不像西曆那樣有著明顯的規律,雖然農曆本身的干支年是60年循環一次,但是每個年份在每次循環中,所含的各個月份之天數有可能是不一樣的,甚至連該年有沒有閏月,有閏月的話是閏幾月也都不能固定,單講哪個干支年也無法確定究竟是第幾次循環的,因此通常還會搭配其它曆法或是紀年法來使用,現在的話當然就是搭配西曆來用啦!



Chinese Lunisolar Calendar

「Chinese Lunisolar Calendar」是筆者開發的套件,以不同的結構體分別抽象化了西曆的年、月、日和農曆的西曆年和農曆的月和日。農曆的部份仰賴三個資料集合,也就是農曆每年的大月、閏月、以及農曆新年與該年所屬西曆年新年的天數差距,因此能夠支援的農曆日期範圍是有限的。目前有西元1901年到2100年的資料,可以支援的農曆日期範圍為西曆的西元1901年2月19日至西元2101年1月28日。

這個套件實現了西曆和農曆的轉換,以及用農曆日期和時間來計算八字重量的功能。除此之外,也可以將西曆或是農曆日期與中文字串互轉,同時支援繁體中文和簡體中文。

Crates.io

Cargo.toml

chinese-lunisolar-calendar = "*"

使用方法

產生SolarDate結構實體的例子如下:

use chinese_lunisolar_calendar::chrono::prelude::*;

use chinese_lunisolar_calendar::SolarDate;

let solar_date = SolarDate::from_naive_date(NaiveDate::from_ymd(2019, 1, 15)).unwrap();

assert_eq!("二零一九年一月十五日", solar_date.to_chinese_string());
assert_eq!("二〇一九年一月十五日", solar_date.to_chinese_string_2());

產生LunisolarDate結構實體的例子如下:

use chinese_lunisolar_calendar::chrono::prelude::*;

use chinese_lunisolar_calendar::{ChineseVariant, LunisolarDate};

let lunisolar_date = LunisolarDate::from_naive_date(NaiveDate::from_ymd(2019, 1, 15)).unwrap();

assert_eq!(2019, lunisolar_date.get_solar_year().to_u16());
assert_eq!("二零一八 戊戌、狗年 臘月 初十", lunisolar_date.to_chinese_string(ChineseVariant::Traditional));
assert_eq!("二零一八 戊戌、狗年 腊月 初十", lunisolar_date.to_chinese_string(ChineseVariant::Simple));
assert_eq!("二〇一八 戊戌、狗年 臘月 初十", lunisolar_date.to_chinese_string_2(ChineseVariant::Traditional));
assert_eq!("二〇一八 戊戌、狗年 腊月 初十", lunisolar_date.to_chinese_string_2(ChineseVariant::Simple));

assert_eq!(4.3, lunisolar_date.get_ba_zi_weight_by_time(NaiveTime::from_hms(15, 30, 0)));

當然,除了from_naive_date關聯函數之外,還有更多方便的以from_開頭的關聯函數可以產生SolarDate或是LunisolarDate的結構實體。

SolarDate結構實體和LunisolarDate結構實體也可以輕易互轉。程式如下:

let lunisolar_date = solar_date.to_lunisolar_date().unwrap();
let solar_date = lunisolar_date.to_solar_date();

LunisolarDate結構實體可以透過其get_ba_zi_weight方法再加上表示時辰的地支,或是get_ba_zi_weight_by_time方法再加上時間資料,來計算出八字重量。程式如下:

let weight = lunisolar_date.get_ba_zi_weight(EarthlyBranch::Ninth);
let weight = lunisolar_date.get_ba_zi_weight_by_time(NaiveTime::from_hms(15, 30, 0));