[TOC]
來源
二十四節(jié)氣采用的是“定氣法”劃分,即每一個(gè)節(jié)氣分別相應(yīng)于地球在黃道上每運(yùn)行15°所到達(dá)的一定位置.
把太陽周年運(yùn)動(dòng)軌跡劃分為24等份.太陽從黃經(jīng)零度起,沿黃經(jīng)每運(yùn)行15度所經(jīng)歷的時(shí)日稱為“一個(gè)節(jié)氣”沐鼠。每年運(yùn)行360度,共經(jīng)歷24個(gè)節(jié)氣,每月2個(gè)谴轮。
二十四節(jié)氣表達(dá)了人與自然宇宙之間獨(dú)特的時(shí)間觀念奉呛,蘊(yùn)含著中華民族悠久的文化內(nèi)涵和歷史積淀。
二十四節(jié)氣既是歷代官府頒布的時(shí)間準(zhǔn)繩,也是指導(dǎo)農(nóng)業(yè)生產(chǎn)的指南針另凌,日常生活中人們預(yù)知冷暖雪雨的指南針询张。
二十四節(jié)氣歌
春雨驚春清谷天孙乖,
夏滿芒夏暑相連,
秋處露秋寒霜降份氧,
冬雪雪冬小大寒唯袄。
每月兩節(jié)不變更,
最多相差一兩天蜗帜。
上半年是六廿一越妈,
下半年逢八廿三。
節(jié)氣歌的妙處就在于首字是春夏秋冬,第四字也是春夏秋冬.
節(jié)氣日期計(jì)算
通用公式——[Y×D+C]-L
Y=年代數(shù)后2位钮糖、
D=0.2422梅掠、
L=閏年數(shù)(凡閏年3月1日前閏年數(shù)要減一,即:L=[(Y-1)/4],因?yàn)樾『旯椤⒋蠛质恪⒘⒋骸⒂晁@兩個(gè)節(jié)氣都小于3月1日,所以 y = y-1)消痛、
C取決于節(jié)氣和年份
例:求2017年的立春日期
[17×0.2422+3.87]-[(17-1)/4]=7.9874-4=3
所以2017年的立春日期是2月3日
編程計(jì)算
import java.util.HashMap;
import java.util.Map;
/**
*describe:24節(jié)氣
*程序的運(yùn)行得出的節(jié)氣結(jié)果絕大多數(shù)是正確的且叁,有少數(shù)部份是有誤差的
*/
public class _24SolarTerms {
//常數(shù)D
private static final double D = 0.2422;
private final static Map<String,Integer[]> INCREASE_OFFSETMAP = new HashMap<String, Integer[]>();//+1偏移
private final static Map<String,Integer[]> DECREASE_OFFSETMAP = new HashMap<String, Integer[]>();//-1偏移
/**枚舉24節(jié)氣**/
private static enum SolarTermsEnum {
LICHUN,//--立春
YUSHUI,//--雨水
JINGZHE,//--驚蟄
CHUNFEN,//春分
QINGMING,//清明
GUYU,//谷雨
LIXIA,//立夏
XIAOMAN,//小滿
MANGZHONG,//芒種
XIAZHI,//夏至
XIAOSHU,//小暑
DASHU,//大暑
LIQIU,//立秋
CHUSHU,//處暑
BAILU,//白露
QIUFEN,//秋分
HANLU,//寒露
SHUANGJIANG,//霜降
LIDONG,//立冬
XIAOXUE,//小雪
DAXUE,//大雪
DONGZHI,//冬至
XIAOHAN,//小寒
DAHAN;//大寒
}
static {
DECREASE_OFFSETMAP.put(SolarTermsEnum.YUSHUI.name(), new Integer[]{2026});//雨水
INCREASE_OFFSETMAP.put(SolarTermsEnum.CHUNFEN.name(), new Integer[]{2084});//春分
INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAOMAN.name(), new Integer[]{2008});//小滿
INCREASE_OFFSETMAP.put(SolarTermsEnum.MANGZHONG.name(), new Integer[]{1902});//芒種
INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAZHI.name(), new Integer[]{1928});//夏至
INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAOSHU.name(), new Integer[]{1925,2016});//小暑
INCREASE_OFFSETMAP.put(SolarTermsEnum.DASHU.name(), new Integer[]{1922});//大暑
INCREASE_OFFSETMAP.put(SolarTermsEnum.LIQIU.name(), new Integer[]{2002});//立秋
INCREASE_OFFSETMAP.put(SolarTermsEnum.BAILU.name(), new Integer[]{1927});//白露
INCREASE_OFFSETMAP.put(SolarTermsEnum.QIUFEN.name(), new Integer[]{1942});//秋分
INCREASE_OFFSETMAP.put(SolarTermsEnum.SHUANGJIANG.name(), new Integer[]{2089});//霜降
INCREASE_OFFSETMAP.put(SolarTermsEnum.LIDONG.name(), new Integer[]{2089});//立冬
INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAOXUE.name(), new Integer[]{1978});//小雪
INCREASE_OFFSETMAP.put(SolarTermsEnum.DAXUE.name(), new Integer[]{1954});//大雪
DECREASE_OFFSETMAP.put(SolarTermsEnum.DONGZHI.name(), new Integer[]{1918,2021});//冬至
INCREASE_OFFSETMAP.put(SolarTermsEnum.XIAOHAN.name(), new Integer[]{1982});//小寒
DECREASE_OFFSETMAP.put(SolarTermsEnum.XIAOHAN.name(), new Integer[]{2019});//小寒
INCREASE_OFFSETMAP.put(SolarTermsEnum.DAHAN.name(), new Integer[]{2082});//大寒
}
//定義一個(gè)二維數(shù)組,第一維數(shù)組存儲(chǔ)的是20世紀(jì)的節(jié)氣C值秩伞,第二維數(shù)組存儲(chǔ)的是21世紀(jì)的節(jié)氣C值,0到23個(gè)逞带,依次代表立春欺矫、雨水...大寒節(jié)氣的C值
private static final double[][] CENTURY_ARRAY =
{{4.6295,19.4599,6.3826,21.4155,5.59,20.888,6.318,21.86,6.5,22.2,7.928,23.65,8.35,
23.95,8.44,23.822,9.098,24.218,8.218,23.08,7.9,22.6,6.11,20.84}
,{3.87,18.73,5.63,20.646,4.81,20.1,5.52,21.04,5.678,21.37,7.108,22.83,
7.5,23.13,7.646,23.042,8.318,23.438,7.438,22.36,7.18,21.94,5.4055,20.12}};
/**
*
* @param year 年份
* @param name 節(jié)氣的名稱
* @return 返回節(jié)氣是相應(yīng)月份的第幾天
*/
public static int getSolarTermNum(int year,String name){
double centuryValue = 0;//節(jié)氣的世紀(jì)值,每個(gè)節(jié)氣的每個(gè)世紀(jì)值都不同
name = name.trim().toUpperCase();
int ordinal = SolarTermsEnum.valueOf(name).ordinal();
int centuryIndex = -1;
if(year>=1901 && year<=2000){//20世紀(jì)
centuryIndex = 0;
} else if(year>=2001 && year <= 2100){//21世紀(jì)
centuryIndex = 1;
} else {
throw new RuntimeException("不支持此年份:"+year+"展氓,目前只支持1901年到2100年的時(shí)間范圍");
}
centuryValue = CENTURY_ARRAY[centuryIndex][ordinal];
int dateNum = 0;
/**
* 計(jì)算 num =[Y*D+C]-L這是傳說中的壽星通用公式
* 公式解讀:年數(shù)的后2位乘0.2422加C(即:centuryValue)取整數(shù)后穆趴,減閏年數(shù)
*/
int y = year%100;
//步驟1:取年分的后兩位數(shù)
if(year%4 == 0 && year%100 !=0 || year%400 ==0){//閏年
if(ordinal == SolarTermsEnum.XIAOHAN.ordinal() || ordinal == SolarTermsEnum.DAHAN.ordinal()
|| ordinal == SolarTermsEnum.LICHUN.ordinal() || ordinal == SolarTermsEnum.YUSHUI.ordinal()){
//注意:凡閏年3月1日前閏年數(shù)要減一,即:L=[(Y-1)/4],因?yàn)樾『龉⒋蠛疵谩⒘⒋骸⒂晁@兩個(gè)節(jié)氣都小于3月1日,所以 y = y-1
y = y-1;//步驟2
}
}
dateNum = (int)(y*D+centuryValue)-(int)(y/4);//步驟3空入,使用公式[Y*D+C]-L計(jì)算
dateNum += specialYearOffset(year,name);//步驟4络它,加上特殊的年分的節(jié)氣偏移量
return dateNum;
}
/**
* 特例,特殊的年分的節(jié)氣偏移量,由于公式并不完善,所以算出的個(gè)別節(jié)氣的第幾天數(shù)并不準(zhǔn)確歪赢,在此返回其偏移量
* @param year 年份
* @param name 節(jié)氣名稱
* @return 返回其偏移量
*/
public static int specialYearOffset(int year,String name) {
int offset = 0;
offset += getOffset(DECREASE_OFFSETMAP,year,name,-1);
offset += getOffset(INCREASE_OFFSETMAP,year,name,1);
return offset;
}
public static int getOffset(Map<String,Integer[]> map,int year,String name,int offset){
int off = 0;
Integer[] years = map.get(name);
if(null != years){
for(int i:years){
if(i == year){
off = offset;
break;
}
}
}
return off;
}
public static String solarTermToString(int year) {
StringBuffer sb = new StringBuffer();
sb.append("---").append(year);
if(year%4 == 0 && year%100 !=0 || year%400 ==0){//閏年
sb.append(" 閏年");
} else {
sb.append(" 平年");
}
sb.append("\n")
.append("立春:2月").append(getSolarTermNum(year,SolarTermsEnum.LICHUN.name()))
.append("日,雨水:2月").append(getSolarTermNum(year,SolarTermsEnum.YUSHUI.name()))
.append("日,驚蟄:3月").append(getSolarTermNum(year,SolarTermsEnum.JINGZHE.name()))
.append("日,春分:3月").append(getSolarTermNum(year,SolarTermsEnum.CHUNFEN.name()))
.append("日,清明:4月").append(getSolarTermNum(year,SolarTermsEnum.QINGMING.name()))
.append("日,谷雨:4月").append(getSolarTermNum(year,SolarTermsEnum.GUYU.name()))
.append("日,立夏:5月").append(getSolarTermNum(year,SolarTermsEnum.LIXIA.name()))
.append("日,小滿:5月").append(getSolarTermNum(year,SolarTermsEnum.XIAOMAN.name()))
.append("日,芒種:6月").append(getSolarTermNum(year,SolarTermsEnum.MANGZHONG.name()))
.append("日,夏至:6月").append(getSolarTermNum(year,SolarTermsEnum.XIAZHI.name()))
.append("日,小暑:7月").append(getSolarTermNum(year,SolarTermsEnum.XIAOSHU.name()))
.append("日,大暑:7月").append(getSolarTermNum(year,SolarTermsEnum.DASHU.name()))
.append("日,立秋:8月").append(getSolarTermNum(year,SolarTermsEnum.LIQIU.name()))
.append("日,處暑:8月").append(getSolarTermNum(year,SolarTermsEnum.CHUSHU.name()))
.append("日,白露:9月").append(getSolarTermNum(year,SolarTermsEnum.BAILU.name()))
.append("日,秋分:9月").append(getSolarTermNum(year,SolarTermsEnum.QIUFEN.name()))
.append("日,寒露:10月").append(getSolarTermNum(year,SolarTermsEnum.HANLU.name()))
.append("日,霜降:10月").append(getSolarTermNum(year,SolarTermsEnum.SHUANGJIANG.name()))
.append("日,立冬:11月").append(getSolarTermNum(year,SolarTermsEnum.LIDONG.name()))
.append("日,小雪:11月").append(getSolarTermNum(year,SolarTermsEnum.XIAOXUE.name()))
.append("日,大雪:12月").append(getSolarTermNum(year,SolarTermsEnum.DAXUE.name()))
.append("日,冬至:12月").append(getSolarTermNum(year,SolarTermsEnum.DONGZHI.name()))
.append("日,小寒:1月").append(getSolarTermNum(year,SolarTermsEnum.XIAOHAN.name()))
.append("日,大寒:1月").append(getSolarTermNum(year,SolarTermsEnum.DAHAN.name()));
return sb.toString();
}
}