NSDate,NSCalendar的农历支持

五年前我们团队制作第一版倒数日时,并不支持农历,那个时候iOS系统也没有农历的相关接口。14年制作第二版倒数日(iDays)的时候,为了实现农历和公历的双向转换,使用sql数据库存储了前后100年内每日的农历信息,数据容量8Mb左右,增加了软件大小,且限制了年限为 1900年-2100年间。

直到iOS 8.0,iOS系统框架开始才开始支持中国农历的相关计算,我们将系统的相关类进行扩充,以满足我们新产品对农历的需求。

Cocospods

1
pod 'gerinn-dev-kit'

Github

Github

使用方法

NSDate+Lunar

NSDate+Lunar 部分包含了NSDateNSCalendar两个部分的扩充。

NSDate

获取当前日期是否为农历闰月。

1
- (BOOL)lunar_isLeapMonth;

获取农历月份,和中文描述。

1
2
- (NSInteger)lunar_month;
- (NSInteger)lunar_month_chinese;

获取农历年份的干支描述,农历以公元前2697年为第一个甲子年,60年一个周期,lunar_year的值为1-60。

1
2
- (NSInteger)lunar_year;
- (NSString*)lunar_year_chinese;

获取农历日期,以及中文描述。

1
2
- (NSInteger)lunar_day;
- (NSString*)lunar_day_chinese;

NSCalendar

所有NSCalendar关于农历的分类方法,要求NSCalendar使用NSCalendarIdentifierChinese初始化,所以提供一个实例方法:

1
+ (instancetype)lunarCalendar;

在做农历日期选择器的时候,因为农历年和公历年数量上是一一对应的,所以接口中的年份参数均设计成公历年,省去了中间的换算过程,月份和日期则为农历月,农历日。

通过公历年获取农历年干支
1
- (NSString*)lunar_yearChineseWithGregorianYear:(NSInteger)year;
1
NSLog(@"%@",[[NSCalendar lunarCalendar] lunar_yearChineseWithGregorianYear:2018]);

戊戌

通过公历年获取月份数组
1
- (NSArray <NSNumber*>*)lunar_monthWithGregorianYear:(NSInteger)year;
1
NSLog(@"%@",[[NSCalendar lunarCalendar] lunar_monthWithGregorianYear:2017]);

(
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13
)

获取农历月份描述

因为2017年有闰月,所以月份返回了13个。通过月份序号,调用下面的方法获取中文名称:

1
- (NSString *)lunar_monthChineseWithLunarMonth:(NSInteger)month gregorianYear:(NSInteger)year;
1
NSLog(@"%@",[[NSCalendar lunarCalendar] lunar_monthChineseWithLunarMonth:7 gregorianYear:2017]);

闰六月

获取天数数组

接着我们根据公历年和农历月获取天数数组

1
NSLog(@"%@",[[NSCalendar lunarCalendar] lunar_daysWithGregorianYear:2017 lunarMonth:6]);

同样可以获取到天数的中文描述

1
- (NSString*)lunar_dayChineseWithLunarDay:(NSInteger)day shortDes:(BOOL)useShort;

当useShort为真时,会将二十四中的二十缩写成廿

通过农历年月日获取公历NSDate
1
- (NSDate*)lunar_getDayWithGregorianYear:(NSInteger)year lunarMonth:(NSInteger)month lunarDay:(NSInteger)day;

这里的year为公历年,month为前面接口返回的序号。

1
NSLog(@"%@",[[NSCalendar lunarCalendar] lunar_getDayWithGregorianYear:1989 lunarMonth:8 lunarDay:8]);

Thu Sep 7 00:00:00 1989

NSDate+Calculation

天数计算目前有三个接口,区分公历和农历

一周后
1
[[NSDate date] calculate:NSCalendarUnitWeekOfYear value:1];
一个月后
1
[[NSDate date] lunar_calculate:NSCalendarUnitMonth value:1];

公历计算两个日期间的差值

1
NSLog(@"%@",@([[f dateFromString:@"2018-05-31"] calculateFromDate:[f dateFromString:@"2018-11-12"] unit:NSCalendarUnitWeekday]));

-165