陽曆轉農曆及四柱八字程式更新
09/27/2010, 10:36 - Open Source
上次的轉換程式,轉換出來的四柱八字,和黃曆上所記的不同,經過研究之後,發現農曆的年干支轉換,是發生在立春,而非農曆正月初一。而每月的干支轉換是發生在該月份的第一個節氣,而非每月的第一日。造成這個問題,是因為在四柱八字轉參考了紫微斗數的四柱轉換方式,紫微斗數的轉換方式出較簡單直接,而農曆則需要考慮節氣轉換。而節氣是和太陽運行照射的角度有關。感謝JamDing的指正,並提供測試方法。

LunarCalendar.h

//
// LunarCalendar.h
// LunarCal
//
// Created by Tasuka Hsu on 09/07/2010.
// Copyleft 2010 http://Tasuka.IDV.TW.
//

#import <Foundation/Foundation.h>

@interface LunarCalendar : NSObject {
NSNumber *SolarYear; //陽曆年 1900-2100
NSNumber *SolarMonth; //陽曆月 1-12
NSNumber *SolarDay; //陽曆日 1-31
NSNumber *SolarHour; //陽曆時 0-23
}

-(void)setSolarYear:(int) year month:(int)month day:(int)day hour:(int)hour;
-(void)setSolarYear:(int) year month:(int)month day:(int)day;
-(void)setSolarYear:(int) year;
-(void)setSolarMonth:(int) month;
-(void)setSolarDay:(int) day;
-(void)setSolarHour:(int) hour;

-(int)solarYear; //陽曆年 1900-2100
-(int)solarMonth; //陽曆月 1-12
-(int)solarDay; //陽曆日 1-31
-(int)solarHour; //陽曆時 0-23
-(int)weekDay; //星期 0-6

-(int)lunarYear; //農曆年 1900-2100
-(int)lunarMonth; //農曆月 1-12
-(int)lunarDay; //農曆日 1-30
-(int)lunarHour; //農曆時 0-11

-(NSString *)lunarHourChinese; //農曆時
-(NSDate *)spring:(int)year; //春分
-(NSDate *)spring:(int)year index:(int)idx;
-(NSDate *)springStart:(int)year; //立春

-(BOOL)isLeap; //閏年

-(NSString *)chineseYear; //農曆干支年
-(NSString *)chineseMonth; //農曆干支月
-(NSString *)chineseDay; //農曆干支日
-(NSString *)chineseHour; //農曆干支時
-(NSString *)chineseYearTitle; //紀元
-(NSString *)chineseYearAnimal; //生肖

-(NSArray *)Gan; //天干表
-(NSArray *)Zhi; //地支表
-(NSArray *)Animals; //生肖表
-(NSArray *)solarTerms; //二十四節氣表

-(int)solarTerm:(int)year index:(int)idx; //節氣
-(void)lunarCalendar; //計算陽曆轉換農曆

@end



LunarCalendar.m

//
// LunarCalendar.m
// LunarCal
//
// Created by Tasuka Hsu on 09/07/2010.
// Copyleft 2010 http://Tasuka.IDV.TW.
// This class is based on http://s.o4u.com/host/blog/calendar/calendar.htm Java Script code

#import "LunarCalendar.h"

@interface LunarCalendar (Private)
NSArray *lunarInfo;
NSArray *solarMonths;
NSArray *Gan;
NSArray *Zhi;
NSArray *Animals;
NSArray *solarTerms;
NSArray *solarTermsSunAngle;
NSArray *solarTermsRate;
NSArray *solarTermsDayIdx;

NSNumber *week;
NSNumber *LunarYear;
NSNumber *LunarMonth;
NSNumber *LunarDay;
NSNumber *LunarHour;

NSString *ChineseYear;
NSString *ChineseMonth;
NSString *ChineseDay;
NSString *ChineseHour;
NSString *ChineseYearTitle;
NSString *ChineseYearAnimal;

int dayCyclical;
BOOL NightHour;
BOOL Leap;

-(int)lunarYearDays:(int)year;
-(int)leapDays:(int)year;
-(int)leapMonth:(int)year;
-(int)monthDays:(int)year: month:(int)month;
-(int)solarDays:(int)year: month:(int)month;

-(NSString *)cyclical:(int)number;
-(NSDate *)lunarCalc;

#define MoonCycle 29.53059
#define EarthCycle 365.2422

@end

@implementation LunarCalendar
-(id)init
{
//農曆資料表
lunarInfo=[NSArray arrayWithObjects:
[NSNumber numberWithInt:0x4bd8],[NSNumber numberWithInt:0x4ae0],[NSNumber numberWithInt:0xa570],
[NSNumber numberWithInt:0x54d5],[NSNumber numberWithInt:0xd260],[NSNumber numberWithInt:0xd950],
[NSNumber numberWithInt:0x5554],[NSNumber numberWithInt:0x56af],[NSNumber numberWithInt:0x9ad0],
[NSNumber numberWithInt:0x55d2],[NSNumber numberWithInt:0x4ae0],[NSNumber numberWithInt:0xa5b6],
[NSNumber numberWithInt:0xa4d0],[NSNumber numberWithInt:0xd250],[NSNumber numberWithInt:0xd295],
[NSNumber numberWithInt:0xb54f],[NSNumber numberWithInt:0xd6a0],[NSNumber numberWithInt:0xada2],
[NSNumber numberWithInt:0x95b0],[NSNumber numberWithInt:0x4977],[NSNumber numberWithInt:0x497f],
[NSNumber numberWithInt:0xa4b0],[NSNumber numberWithInt:0xb4b5],[NSNumber numberWithInt:0x6a50],
[NSNumber numberWithInt:0x6d40],[NSNumber numberWithInt:0xab54],[NSNumber numberWithInt:0x2b6f],
[NSNumber numberWithInt:0x9570],[NSNumber numberWithInt:0x52f2],[NSNumber numberWithInt:0x4970],
[NSNumber numberWithInt:0x6566],[NSNumber numberWithInt:0xd4a0],[NSNumber numberWithInt:0xea50],
[NSNumber numberWithInt:0x6a95],[NSNumber numberWithInt:0x5adf],[NSNumber numberWithInt:0x2b60],
[NSNumber numberWithInt:0x86e3],[NSNumber numberWithInt:0x92ef],[NSNumber numberWithInt:0xc8d7],
[NSNumber numberWithInt:0xc95f],[NSNumber numberWithInt:0xd4a0],[NSNumber numberWithInt:0xd8a6],
[NSNumber numberWithInt:0xb55f],[NSNumber numberWithInt:0x56a0],[NSNumber numberWithInt:0xa5b4],
[NSNumber numberWithInt:0x25df],[NSNumber numberWithInt:0x92d0],[NSNumber numberWithInt:0xd2b2],
[NSNumber numberWithInt:0xa950],[NSNumber numberWithInt:0xb557],[NSNumber numberWithInt:0x6ca0],
[NSNumber numberWithInt:0xb550],[NSNumber numberWithInt:0x5355],[NSNumber numberWithInt:0x4daf],
[NSNumber numberWithInt:0xa5b0],[NSNumber numberWithInt:0x4573],[NSNumber numberWithInt:0x52bf],
[NSNumber numberWithInt:0xa9a8],[NSNumber numberWithInt:0xe950],[NSNumber numberWithInt:0x6aa0],
[NSNumber numberWithInt:0xaea6],[NSNumber numberWithInt:0xab50],[NSNumber numberWithInt:0x4b60],
[NSNumber numberWithInt:0xaae4],[NSNumber numberWithInt:0xa570],[NSNumber numberWithInt:0x5260],
[NSNumber numberWithInt:0xf263],[NSNumber numberWithInt:0xd950],[NSNumber numberWithInt:0x5b57],
[NSNumber numberWithInt:0x56a0],[NSNumber numberWithInt:0x96d0],[NSNumber numberWithInt:0x4dd5],
[NSNumber numberWithInt:0x4ad0],[NSNumber numberWithInt:0xa4d0],[NSNumber numberWithInt:0xd4d4],
[NSNumber numberWithInt:0xd250],[NSNumber numberWithInt:0xd558],[NSNumber numberWithInt:0xb540],
[NSNumber numberWithInt:0xb6a0],[NSNumber numberWithInt:0x95a6],[NSNumber numberWithInt:0x95bf],
[NSNumber numberWithInt:0x49b0],[NSNumber numberWithInt:0xa974],[NSNumber numberWithInt:0xa4b0],
[NSNumber numberWithInt:0xb27a],[NSNumber numberWithInt:0x6a50],[NSNumber numberWithInt:0x6d40],
[NSNumber numberWithInt:0xaf46],[NSNumber numberWithInt:0xab60],[NSNumber numberWithInt:0x9570],
[NSNumber numberWithInt:0x4af5],[NSNumber numberWithInt:0x4970],[NSNumber numberWithInt:0x64b0],
[NSNumber numberWithInt:0x74a3],[NSNumber numberWithInt:0xea50],[NSNumber numberWithInt:0x6b58],
[NSNumber numberWithInt:0x5ac0],[NSNumber numberWithInt:0xab60],[NSNumber numberWithInt:0x96d5],
[NSNumber numberWithInt:0x92e0],[NSNumber numberWithInt:0xc960],[NSNumber numberWithInt:0xd954],
[NSNumber numberWithInt:0xd4a0],[NSNumber numberWithInt:0xda50],[NSNumber numberWithInt:0x7552],
[NSNumber numberWithInt:0x56a0],[NSNumber numberWithInt:0xabb7],[NSNumber numberWithInt:0x25d0],
[NSNumber numberWithInt:0x92d0],[NSNumber numberWithInt:0xcab5],[NSNumber numberWithInt:0xa950],
[NSNumber numberWithInt:0xb4a0],[NSNumber numberWithInt:0xbaa4],[NSNumber numberWithInt:0xad50],
[NSNumber numberWithInt:0x55d9],[NSNumber numberWithInt:0x4ba0],[NSNumber numberWithInt:0xa5b0],
[NSNumber numberWithInt:0x5176],[NSNumber numberWithInt:0x52bf],[NSNumber numberWithInt:0xa930],
[NSNumber numberWithInt:0x7954],[NSNumber numberWithInt:0x6aa0],[NSNumber numberWithInt:0xad50],
[NSNumber numberWithInt:0x5b52],[NSNumber numberWithInt:0x4b60],[NSNumber numberWithInt:0xa6e6],
[NSNumber numberWithInt:0xa4e0],[NSNumber numberWithInt:0xd260],[NSNumber numberWithInt:0xea65],
[NSNumber numberWithInt:0xd530],[NSNumber numberWithInt:0x5aa0],[NSNumber numberWithInt:0x76a3],
[NSNumber numberWithInt:0x96d0],[NSNumber numberWithInt:0x4afb],[NSNumber numberWithInt:0x4ad0],
[NSNumber numberWithInt:0xa4d0],[NSNumber numberWithInt:0xd0b6],[NSNumber numberWithInt:0xd25f],
[NSNumber numberWithInt:0xd520],[NSNumber numberWithInt:0xdd45],[NSNumber numberWithInt:0xb5a0],
[NSNumber numberWithInt:0x56d0],[NSNumber numberWithInt:0x55b2],[NSNumber numberWithInt:0x49b0],
[NSNumber numberWithInt:0xa577],[NSNumber numberWithInt:0xa4b0],[NSNumber numberWithInt:0xaa50],
[NSNumber numberWithInt:0xb255],[NSNumber numberWithInt:0x6d2f],[NSNumber numberWithInt:0xada0],
[NSNumber numberWithInt:0x4b63],[NSNumber numberWithInt:0x937f],[NSNumber numberWithInt:0x49f8],
[NSNumber numberWithInt:0x4970],[NSNumber numberWithInt:0x64b0],[NSNumber numberWithInt:0x68a6],
[NSNumber numberWithInt:0xea5f],[NSNumber numberWithInt:0x6b20],[NSNumber numberWithInt:0xa6c4],
[NSNumber numberWithInt:0xaaef],[NSNumber numberWithInt:0x92e0],[NSNumber numberWithInt:0xd2e3],
[NSNumber numberWithInt:0xc960],[NSNumber numberWithInt:0xd557],[NSNumber numberWithInt:0xd4a0],
[NSNumber numberWithInt:0xda50],[NSNumber numberWithInt:0x5d55],[NSNumber numberWithInt:0x56a0],
[NSNumber numberWithInt:0xa6d0],[NSNumber numberWithInt:0x55d4],[NSNumber numberWithInt:0x52d0],
[NSNumber numberWithInt:0xa9b8],[NSNumber numberWithInt:0xa950],[NSNumber numberWithInt:0xb4a0],
[NSNumber numberWithInt:0xb6a6],[NSNumber numberWithInt:0xad50],[NSNumber numberWithInt:0x55a0],
[NSNumber numberWithInt:0xaba4],[NSNumber numberWithInt:0xa5b0],[NSNumber numberWithInt:0x52b0],
[NSNumber numberWithInt:0xb273],[NSNumber numberWithInt:0x6930],[NSNumber numberWithInt:0x7337],
[NSNumber numberWithInt:0x6aa0],[NSNumber numberWithInt:0xad50],[NSNumber numberWithInt:0x4b55],
[NSNumber numberWithInt:0x4b6f],[NSNumber numberWithInt:0xa570],[NSNumber numberWithInt:0x54e4],
[NSNumber numberWithInt:0xd260],[NSNumber numberWithInt:0xe968],[NSNumber numberWithInt:0xd520],
[NSNumber numberWithInt:0xdaa0],[NSNumber numberWithInt:0x6aa6],[NSNumber numberWithInt:0x56df],
[NSNumber numberWithInt:0x4ae0],[NSNumber numberWithInt:0xa9d4],[NSNumber numberWithInt:0xa4d0],
[NSNumber numberWithInt:0xd150],[NSNumber numberWithInt:0xf252],[NSNumber numberWithInt:0xd520],nil];

//陽曆月天數表
solarMonths=[NSArray arrayWithObjects:[NSNumber numberWithInt:31],[NSNumber numberWithInt:28],
[NSNumber numberWithInt:31],[NSNumber numberWithInt:30],[NSNumber numberWithInt:31],
[NSNumber numberWithInt:30],[NSNumber numberWithInt:31],[NSNumber numberWithInt:31],
[NSNumber numberWithInt:30],[NSNumber numberWithInt:31],[NSNumber numberWithInt:30],
[NSNumber numberWithInt:31],nil];

//天干表
Gan=[NSArray arrayWithObjects:@"甲",@"乙",@"丙",@"丁",@"戊",@"己",@"庚",@"辛",@"壬",@"癸",nil];

//地支表
Zhi=[NSArray arrayWithObjects:@"子",@"丑",@"寅",@"卯",@"辰",@"巳",@"午",@"未",@"申",@"酉",@"戌",@"亥",nil];

//生肖表
Animals=[NSArray arrayWithObjects:@"鼠",@"牛",@"虎",@"兔",@"龍",@"蛇",@"馬",@"羊",@"猴",@"雞",@"狗",@"豬",nil];

//節氣表
solarTerms=[NSArray arrayWithObjects:
@"小寒",@"大寒",@"立春",@"雨水",@"驚蟄",@"春分",
@"清明",@"穀雨",@"立夏",@"小滿",@"芒種",@"夏至",
@"小暑",@"大暑",@"立秋",@"處暑",@"白露",@"秋分",
@"寒露",@"霜降",@"立冬",@"小雪",@"大雪",@"冬至",nil];

//節氣計算值表
solarTermsRate=[NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.242778],[NSNumber numberWithFloat:0.242765],
[NSNumber numberWithFloat:0.242713],[NSNumber numberWithFloat:0.242627],
[NSNumber numberWithFloat:0.242512],[NSNumber numberWithFloat:0.242377],
[NSNumber numberWithFloat:0.242231],[NSNumber numberWithFloat:0.242083],
[NSNumber numberWithFloat:0.241945],[NSNumber numberWithFloat:0.241825],
[NSNumber numberWithFloat:0.241731],[NSNumber numberWithFloat:0.241669],
[NSNumber numberWithFloat:0.241642],[NSNumber numberWithFloat:0.241654],
[NSNumber numberWithFloat:0.241703],[NSNumber numberWithFloat:0.241786],
[NSNumber numberWithFloat:0.241898],[NSNumber numberWithFloat:0.242032],
[NSNumber numberWithFloat:0.242179],[NSNumber numberWithFloat:0.242328],
[NSNumber numberWithFloat:0.242469],[NSNumber numberWithFloat:0.242592],
[NSNumber numberWithFloat:0.242689],[NSNumber numberWithFloat:0.242752],nil];

//節氣計算index值表
solarTermsDayIdx=[NSArray arrayWithObjects:
[NSNumber numberWithFloat:6.3811],[NSNumber numberWithFloat:21.1046],
[NSNumber numberWithFloat:4.8693],[NSNumber numberWithFloat:19.7062],
[NSNumber numberWithFloat:6.3968],[NSNumber numberWithFloat:21.4471],
[NSNumber numberWithFloat:5.6280],[NSNumber numberWithFloat:20.9375],
[NSNumber numberWithFloat:6.3771],[NSNumber numberWithFloat:21.9300],
[NSNumber numberWithFloat:6.5733],[NSNumber numberWithFloat:22.2747],
[NSNumber numberWithFloat:8.0091],[NSNumber numberWithFloat:23.7317],
[NSNumber numberWithFloat:8.4102],[NSNumber numberWithFloat:24.0125],
[NSNumber numberWithFloat:8.5186],[NSNumber numberWithFloat:23.8896],
[NSNumber numberWithFloat:9.1414],[NSNumber numberWithFloat:24.2487],
[NSNumber numberWithFloat:8.2396],[NSNumber numberWithFloat:23.1189],
[NSNumber numberWithFloat:7.9152],[NSNumber numberWithFloat:22.6587],nil];

solarTermsSunAngle=[NSArray arrayWithObjects:
[NSNumber numberWithInt:285],[NSNumber numberWithInt:300],
[NSNumber numberWithInt:315],[NSNumber numberWithInt:330],
[NSNumber numberWithInt:345],[NSNumber numberWithInt:0],
[NSNumber numberWithInt:15],[NSNumber numberWithInt:30],
[NSNumber numberWithInt:45],[NSNumber numberWithInt:60],
[NSNumber numberWithInt:75],[NSNumber numberWithInt:90],
[NSNumber numberWithInt:105],[NSNumber numberWithInt:120],
[NSNumber numberWithInt:135],[NSNumber numberWithInt:150],
[NSNumber numberWithInt:165],[NSNumber numberWithInt:180],
[NSNumber numberWithInt:195],[NSNumber numberWithInt:210],
[NSNumber numberWithInt:225],[NSNumber numberWithInt:240],
[NSNumber numberWithInt:255],[NSNumber numberWithInt:270],nil];

return self;
}

-(void)dealloc
{
[super dealloc];
}

-(int)lunarYearDays:(int)year //農曆年天數
{
int i,sum=348;

for(i=0x8000;i>0x8;i>>=1){
sum+=(([[lunarInfo objectAtIndex:(year-1900)] intValue]&i)?1:0);
}

return (sum+[self leapDays:year]);
}

-(int)leapDays:(int)year //農曆閏年天數
{
if([self leapMonth:year]){
return ((([[lunarInfo objectAtIndex:(year-1899)] intValue]&0xf)==0xf)?30:29);
}else{
return 0;
}
}

-(int)leapMonth:(int)year //農曆閏月
{
int lm=([[lunarInfo objectAtIndex:(year-1900)] intValue]&0xf);
return ((lm==0xf)?0:lm);
}

-(int)monthDays:(int)year month:(int)month //農曆每月天數
{
return ([[lunarInfo objectAtIndex:(year-1900)] intValue]&(0x10000>>(month))?30:29);
}

-(int)solarDays:(int)year month:(int)month //陽曆月天數
{
if(month==2){
return ((((year%4)==0)&&((year%100)!=0)||((year%400)==0))?29:28);
}else{
return [[solarMonths objectAtIndex:month-1] intValue];
}
}

-(NSString *)cyclical:(int)number //干支轉換
{
return [[Gan objectAtIndex:(number%10)] stringByAppendingString:[Zhi objectAtIndex:(number%12)]];
}

-(NSDate *)spring:(int)year //春分日期
{
return [self spring:year index:0];
}

-(NSDate *)springStart:(int)year //立春日期
{
return [self spring:year index:1];
}

-(NSDate *)spring:(int)year index:(int)idx
{
NSDateComponents *dayTerm2Comps=[[NSDateComponents alloc] init];

if(index==0){ //春分
[dayTerm2Comps setDay:[self solarTerm:year index:5]];
[dayTerm2Comps setMonth:3];
}else{ //立春
[dayTerm2Comps setDay:[self solarTerm:year index:2]];
[dayTerm2Comps setMonth:2];
}

[dayTerm2Comps setYear:year];

NSCalendar *gregorian=[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *dayTerm2=[gregorian dateFromComponents:dayTerm2Comps];

[dayTerm2Comps release];
[gregorian release];

return dayTerm2;
}

-(NSDate *)lunarCalc //農曆轉換計算
{
int i,leap,temp=0,year=0;
long offset=0;

NSDateComponents *baseDayComps=[[NSDateComponents alloc] init]; //農曆基準年
NSDateComponents *solarDayComps=[[NSDateComponents alloc] init];
NSDateComponents *chineseDayBaseComps=[[NSDateComponents alloc] init]; //干支轉換基準年

[baseDayComps setDay:31];
[baseDayComps setMonth:1];
[baseDayComps setYear:1900];

[chineseDayBaseComps setDay:1];
[chineseDayBaseComps setMonth:1];
[chineseDayBaseComps setYear:1900];

if(SolarYear!=nil && SolarMonth!=nil && SolarDay!=nil){
[solarDayComps setYear:[SolarYear intValue]];
[solarDayComps setMonth:[SolarMonth intValue]];
[solarDayComps setDay:[SolarDay intValue]];
}

NSCalendar *gregorian=[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];

NSDate *baseDay=[gregorian dateFromComponents:baseDayComps];
NSDate *solarDayTemp=[gregorian dateFromComponents:solarDayComps];
NSDate *chineseDayTemp=[gregorian dateFromComponents:chineseDayBaseComps];

week=[NSNumber numberWithInt:[[solarDayTemp descriptionWithCalendarFormat:@"%w" timeZone:nil locale:nil] intValue]];

NSTimeInterval timeDifference=[solarDayTemp timeIntervalSinceDate:baseDay]; //和基準年的日差
offset=timeDifference/86400;

NSTimeInterval chineseTimeDifference=[solarDayTemp timeIntervalSinceDate:chineseDayTemp];
dayCyclical=(chineseTimeDifference/86400)+10;

for(i=1900;(i<2100 && offset>0);i++){
temp=[self lunarYearDays:i];
offset-=temp;
}
if(offset<0){
offset+=temp;
i--;
}
year=i;

leap=[self leapMonth:i];
Leap=NO;

for(i=1;(i<13 && offset>0);i++){
if(leap>0 && i==(leap+1) && Leap==NO){
i--;
Leap=YES;
temp=[self leapDays:year];
}else{
temp=[self monthDays:year month:i];
}
if(Leap==YES && i==(leap+1)){
Leap=NO;
}
offset-=temp;
}

if(offset==0 && leap>0 && i==leap+1){
if(Leap){
Leap=NO;
}else{
Leap=YES;
i--;
}
}

if(offset<0){
offset+=temp;
i--;
}

NSDateComponents *lunarComps=[[NSDateComponents alloc] init];
[lunarComps setYear:year];
[lunarComps setMonth:i];
[lunarComps setDay:offset+1];
[lunarComps setHour:[SolarHour intValue]];

NSDate *lunarDate=[gregorian dateFromComponents:lunarComps];

[chineseDayBaseComps release];
[baseDayComps release];
[solarDayComps release];
[gregorian release];
[lunarComps release];

return lunarDate;
}

-(void)lunarCalendar //農曆轉換格式
{
int year,month,hour,sYear,sMonth,sDay;

//若沒輸入完整陽曆年月日,則取現在時間
if(SolarYear==nil || SolarMonth==nil || SolarDay==nil){
NSDate *nowDate=[NSDate date];
[self setSolarYear:[[nowDate descriptionWithCalendarFormat:@"%Y" timeZone:nil locale:nil] intValue]];
[self setSolarMonth:[[nowDate descriptionWithCalendarFormat:@"%m" timeZone:nil locale:nil] intValue]];
[self setSolarDay:[[nowDate descriptionWithCalendarFormat:@"%d" timeZone:nil locale:nil] intValue]];
[self setSolarHour:[[nowDate descriptionWithCalendarFormat:@"%H" timeZone:nil locale:nil] intValue]];
}

NSDate *lunarDate=[self lunarCalc];

LunarYear=[NSNumber numberWithInt:[[lunarDate descriptionWithCalendarFormat:@"%Y" timeZone:nil locale:nil] intValue]];
LunarMonth=[NSNumber numberWithInt:[[lunarDate descriptionWithCalendarFormat:@"%m" timeZone:nil locale:nil] intValue]];
LunarDay=[NSNumber numberWithInt:[[lunarDate descriptionWithCalendarFormat:@"%d" timeZone:nil locale:nil] intValue]];

hour=([[lunarDate descriptionWithCalendarFormat:@"%H" timeZone:nil locale:nil] intValue]+1);

//農曆子時 23-1 所以一天會有兩個子時
NightHour=(hour>23)?YES:NO;
hour=(hour>23)?0:hour/2;
LunarHour=[NSNumber numberWithInt:hour];

year=[self lunarYear];
month=[self lunarMonth];

sYear=[self solarYear];
sMonth=[self solarMonth];
sDay=[self solarDay];

if(year>1911){
ChineseYearTitle=[NSString stringWithString:@"民國"];
if(year-1911==1){
ChineseYearTitle=[ChineseYearTitle stringByAppendingString:@"元年"];
}else{
ChineseYearTitle=[ChineseYearTitle stringByAppendingString:[NSString stringWithFormat:@"%d年",year-1911]];
}
}else{
if(year>1874 && year<1909){
ChineseYearTitle=[NSString stringWithString:@"光緒"];
if(year-1874==1){
ChineseYearTitle=[ChineseYearTitle stringByAppendingString:@"元年"];
}else{
ChineseYearTitle=[ChineseYearTitle stringByAppendingString:[NSString stringWithFormat:@"%d年",year-1874]];
}
}else{
if(year>1908 && year<1912){
ChineseYearTitle=[NSString stringWithString:@"宣統"];
if(year-1908==1){
ChineseYearTitle=[ChineseYearTitle stringByAppendingString:@"元年"];
}else{
ChineseYearTitle=[ChineseYearTitle stringByAppendingString:[NSString stringWithFormat:@"%d年",year-1908]];
}
}
}
}

//農曆在立春就換干支年並在每月第一個節氣就轉換干支月,而紫微斗數則是直接由農曆轉換。兩者轉換出來的年柱和月柱會有不同
int springTerm=[self solarTerm:sYear index:2];
int firstTerm=[self solarTerm:sYear index:(sMonth-1)*2]; //每月第一個節氣

if(sMonth<2){
ChineseYear=[NSString stringWithString:[self cyclical:year-1900+36]];
ChineseMonth=[NSString stringWithString:[self cyclical:((year-1900)*12+month+12)]];
ChineseYearAnimal=[NSString stringWithString:[Animals objectAtIndex:((year-4)%12)]];
}else{
if(sMonth==2 && sDay==springTerm){
if(sYear==year){
ChineseYear=[NSString stringWithString:[self cyclical:year-1900+36]];
ChineseMonth=[NSString stringWithString:[self cyclical:((year-1900)*12+month+12+1)]];
ChineseYearAnimal=[NSString stringWithString:[Animals objectAtIndex:((year-4)%12)]];
}else{
ChineseYear=[NSString stringWithString:[self cyclical:year-1900+36+1]];
ChineseMonth=[NSString stringWithString:[self cyclical:((year-1900)*12+month+12+2)]];
ChineseYearAnimal=[NSString stringWithString:[Animals objectAtIndex:((year-4)%12)+1]];
}
}else{
if(sMonth==2 && sDay<springTerm){
ChineseYear=[NSString stringWithString:[self cyclical:year-1900+36]];
ChineseMonth=[NSString stringWithString:[self cyclical:((year-1900)*12+month+12+1)]];
ChineseYearAnimal=[NSString stringWithString:[Animals objectAtIndex:((year-4)%12)]];
}else{
if(sYear>year){
ChineseYear=[NSString stringWithString:[self cyclical:year-1900+36+1]];
ChineseMonth=[NSString stringWithString:[self cyclical:((year-1900)*12+month+12+2)]];
ChineseYearAnimal=[NSString stringWithString:[Animals objectAtIndex:((year-4)%12)+1]];
}else{
if(sMonth==month){
ChineseYear=[NSString stringWithString:[self cyclical:year-1900+36]];
ChineseMonth=[NSString stringWithString:[self cyclical:((year-1900)*12+month+12)]];
ChineseYearAnimal=[NSString stringWithString:[Animals objectAtIndex:((year-4)%12)]];
}else{
ChineseYear=[NSString stringWithString:[self cyclical:year-1900+36]];
ChineseMonth=[NSString stringWithString:[self cyclical:((year-1900)*12+month+12+1)]];
ChineseYearAnimal=[NSString stringWithString:[Animals objectAtIndex:((year-4)%12)]];
}
}
}
}
}

ChineseDay=[NSString stringWithString:[self cyclical:dayCyclical]];

hour=(((((dayCyclical%10)%5)*2)+[self lunarHour])%10);
hour=NightHour?((hour+12)%10):hour;
ChineseHour=[NSString stringWithString:[Gan objectAtIndex:hour]];

ChineseHour=[ChineseHour stringByAppendingString:[Zhi objectAtIndex:[self lunarHour]]];

if([self isLeap]){
ChineseMonth=[ChineseMonth stringByAppendingString:@"(閏)"];
}
}

-(void)setSolarYear:(int) year month:(int)month day:(int)day hour:(int)hour
{
[self setSolarYear:year];
[self setSolarMonth:month];
[self setSolarDay:day];
[self setSolarHour:hour];
}

-(void)setSolarYear:(int) year month:(int)month day:(int)day
{
[self setSolarYear:year];
[self setSolarMonth:month];
[self setSolarDay:day];
}

-(void)setSolarYear:(int) year
{
if(year>1873||year<2100){
SolarYear=[NSNumber numberWithInt:year];
}
}

-(void)setSolarMonth:(int) month
{
if(month>0||month<=12){
SolarMonth=[NSNumber numberWithInt:month];
}
}

-(void)setSolarDay:(int) day
{
if(day>0||day<=31){
SolarDay=[NSNumber numberWithInt:day];
}
}

-(void)setSolarHour:(int) hour
{
if(hour>=0||hour<=23){
SolarHour=[NSNumber numberWithInt:hour];
}
}

-(int)solarYear
{
return [SolarYear intValue];
}

-(int)solarMonth
{
return [SolarMonth intValue];
}

-(int)solarDay
{
return [SolarDay intValue];
}

-(int)solarHour
{
return [SolarHour intValue];
}

-(int)weekDay
{
return [week intValue];
}

-(int)lunarYear
{
return [LunarYear intValue];
}

-(int)lunarMonth
{
return [LunarMonth intValue];
}

-(int)lunarDay
{
return [LunarDay intValue];
}

-(int)lunarHour
{
return [LunarHour intValue];
}

-(NSString *)lunarHourChinese
{
return [NSString stringWithString:[Zhi objectAtIndex:[self lunarHour]]];
}

-(BOOL)isLeap
{
return(Leap?YES:NO);
}

-(int)solarTerm:(int)year index:(int)idx //節氣,從小寒開始算起
{
// D+A*Y-L Y西元年份後兩位,L閏年數。
return floor([[solarTermsDayIdx objectAtIndex:idx] floatValue]+ \
[[solarTermsRate objectAtIndex:idx] floatValue]* \
(year-1900)-((year-1900)/4));
}

-(NSString *)chineseYear
{
return ChineseYear;
}

-(NSString *)chineseMonth
{
return ChineseMonth;
}

-(NSString *)chineseDay
{
return ChineseDay;
}

-(NSString *)chineseHour
{
return ChineseHour;
}

-(NSString *)chineseYearTitle
{
return ChineseYearTitle;
}

-(NSString *)chineseYearAnimal
{
return ChineseYearAnimal;
}

-(NSArray *)Gan
{
return Gan;
}

-(NSArray *)Zhi
{
return Zhi;
}

-(NSArray *)Animals
{
return Animals;
}
-(NSArray *)solarTerms
{
return solarTerms;
}
@end



LunarCal.m

//#define TEST0
//#define TEST1
//#define TEST2
//#define TEST21
//#define TEST22
//#define TEST3
//#define TEST4
//#define TEST41
//#define TEST5

#import <Foundation/Foundation.h>
#import "LunarCalendar.h"

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

LunarCalendar *lunarCal=[[LunarCalendar alloc] init];

#ifdef TEST0
NSLog(@"辛卯年庚子月辛酉日");
[lunarCal setSolarYear:2012 month:1 day:1 hour:23];
#endif

#ifdef TEST1
NSLog(@"壬辰年己酉月丙戌日");
[lunarCal setSolarYear:2012 month:9 day:22 hour:23];
#endif

#ifdef TEST2
NSLog(@"己丑年丁丑月甲申日");
[lunarCal setSolarYear:2010 month:2 day:3];
#endif

#ifdef TEST21
NSLog(@"庚寅年戊寅月乙酉日");
[lunarCal setSolarYear:2010 month:2 day:4];
#endif

#ifdef TEST22
NSLog(@"庚寅年戊寅月丙戌日");
[lunarCal setSolarYear:2010 month:2 day:5 hour:10];
#endif

#ifdef TEST3
NSLog(@"乙卯年己卯月癸酉日");
[lunarCal setSolarYear:1975 month:3 day:28 hour:2];
#endif

#ifdef TEST4
NSLog(@"辛亥年庚寅月庚申日");
[lunarCal setSolarYear:1971 month:2 day:4 hour:2];
#endif

#ifdef TEST41
NSLog(@"辛亥年庚寅月辛酉日");
[lunarCal setSolarYear:1971 month:2 day:5 hour:2];
#endif

#ifdef TEST5
NSLog(@"辛亥年壬辰月辛巳日");
[lunarCal setSolarYear:1971 month:4 day:26 hour:2];
#endif

[lunarCal lunarCalendar];
NSLog(@"陽曆:%d-%d-%d 星期%d %d時",[lunarCal solarYear],[lunarCal solarMonth],[lunarCal solarDay], \
[lunarCal weekDay],[lunarCal solarHour]);
NSLog(@"農曆:%d-%d-%d",[lunarCal lunarYear],[lunarCal lunarMonth],[lunarCal lunarDay]);
NSLog(@"農曆:%@%d月%d日 %@時 %@年%@月%@日%@時",[lunarCal chineseYearTitle],[lunarCal lunarMonth], \
[lunarCal lunarDay],[lunarCal lunarHourChinese], \
[lunarCal chineseYear],[lunarCal chineseMonth],[lunarCal chineseDay],[lunarCal chineseHour]);
NSLog(@"生肖屬%@",[lunarCal chineseYearAnimal]);

[lunarCal release];
[pool drain];
return 0;
}



註:修正生肖也需要在立春同步改變問題。

lam
11/18/2010, 09:28
四柱轉換不對,只修改氣節交換都不對,是不是很繁複的問題?
經測試多是欠一天。

tasuka
11/18/2010, 09:38
這個程式還有問題,因為月柱和節氣轉換的時間沒辦法完全掌握.
己經在用NASA的JPL星曆的太陽軌道資料修改,節氣轉換可以正確算到秒.
這樣就可以判斷真正的節氣到底要在當天或下一天轉換,因為時辰在子時會有跨日的問題.不過因為拿JPL星曆從1900-2099每一天的太陽軌道資料量太大,還在想辦縮小.(事實上是最近有點懶...)

Bule
10/27/2011, 20:10
RUN出來有問題
請問板大是程式哪裡出狀況了

回應

發表回應

填寫下面來發表回應。









插入項目:


遊覽已上傳的圖片








回應需經過管理人員認可後才會出現在網頁上.