/// <summary>
/// 中国阴历及节假日计算
/// </summary>
public class ChineseCalendar
{
private static ChineseLunisolarCalendar clc = new ChineseLunisolarCalendar();
//中国节日汇总
private static List<ChineseHoliday> HOLIDAYS = new List<ChineseHoliday>()
{
//公历节日
new ChineseHoliday(1,1,"元旦节",false),
new ChineseHoliday(5,1,"劳动节",false),
new ChineseHoliday(10,1,"国庆节",false),
new ChineseHoliday(10,2,"国庆节",false),
new ChineseHoliday(10,3,"国庆节",false),
new ChineseHoliday(10,4,"国庆节",false),
new ChineseHoliday(10,5,"国庆节",false),
new ChineseHoliday(10,6,"国庆节",false),
new ChineseHoliday(10,7,"国庆节",false),
//阴历节日
new ChineseHoliday(12,30,"春节",true),
new ChineseHoliday(1,1,"春节",true),
new ChineseHoliday(1,2,"春节",true),
new ChineseHoliday(1,3,"春节",true),
new ChineseHoliday(1,4,"春节",true),
new ChineseHoliday(1,5,"春节",true),
new ChineseHoliday(1,6,"春节",true),
new ChineseHoliday(5,5,"端午节",true),
new ChineseHoliday(8,15,"中秋节",true),
};
/// <summary>
/// 把公历日期转换为阴历日期
/// 这里不直接返回Datetime的原因是阴历有时候2月有30号转换Datetime会出错
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
public static Tuple<int, int, int> ToChineseDate(DateTime date)
{
/** GetLeapMonth(int year)方法返回一个1到13之间的数字,
* 比如:1、该年阴历2月有闰月,则返回3
* 如果:2、该年阴历8月有闰月,则返回9
* GetMonth(DateTime dateTime)返回是当前月份,忽略是否闰月
* 比如:1、该年阴历2月有闰月,2月返回2,闰2月返回3
* 如果:2、该年阴历8月有闰月,8月返回8,闰8月返回9
*/
int lyear = clc.GetYear(date);
int lmonth = clc.GetMonth(date);
int lday = clc.GetDayOfMonth(date);
//获取第几个月是闰月,等于0表示本年无闰月
int leapMonth = clc.GetLeapMonth(lyear);
if (leapMonth > 0)
{
if (leapMonth == lmonth)
{
lmonth--;
}
else if (lmonth > leapMonth)
{
lmonth--;
}
}
return new Tuple<int, int, int>(lyear, lmonth, lday);
}
/// <summary>
/// 根据日期获取节日名称,有可能有的时候一天有2个节日
/// item1=阴历节日,item2=阳历节日
/// </summary>
/// <param name="date">公历日期</param>
/// <returns></returns>
public static Tuple<string, string> GetTupleHoliday(DateTime date)
{
string choliday = ""; //阴历、公历节日
string holiday = ""; //公历节日
Tuple<int, int, int> cdate = ToChineseDate(date);
//找公历节日
foreach (var item in HOLIDAYS.FindAll(p => p.IsLunar == false))
{
//月份和日相同则认为是假期
if (item.Month == date.Month && item.Day == date.Day)
{
holiday = item.Name;
break;
}
}
//找阴历节日
foreach (var item in HOLIDAYS.FindAll(p => p.IsLunar == true))
{
if (item.Month == cdate.Item2 && item.Day == cdate.Item3)
{
choliday = item.Name;
break;
}
}
return new Tuple<string, string>(choliday, holiday);
}
/// <summary>
/// 根据日期获取节日名称,有可能有的时候一天有2个节日
/// item1=阴历节日,item3=阳历假日
/// </summary>
/// <param name="date">公历日期</param>
/// <returns></returns>
public static string GetHoliday(DateTime date)
{
string holiday = ""; //节日名称
try
{
//加这个条件是因为阴历不在这个范围内转换会报错
if (date.Year >= 1902 && date.Year <= 2100)
{
Tuple<int, int, int> cdate = ToChineseDate(date);
//找公历节日
foreach (var item in HOLIDAYS)
{
if (item.IsLunar == false)
{
//月份和日相同则认为是假期
if (item.Month == date.Month && item.Day == date.Day)
{
holiday = item.Name;
break;
}
}
else
{
//阴历
if (item.Month == cdate.Item2 && item.Day == cdate.Item3)
{
holiday = item.Name;
break;
}
}
}
}
}
catch (Exception ex)
{
}
return holiday;
}
}
/// <summary>
/// 关于中国公历、阴历的节假日汇总
/// </summary>
internal class ChineseHoliday
{
/// <summary>
/// 是否是阴历
/// </summary>
public bool IsLunar { get; set; }
/// <summary>
/// 节日月份
/// </summary>
public int Month { set; get; }
/// <summary>
/// 节日
/// </summary>
public int Day { set; get; }
/// <summary>
/// 节日名称
/// </summary>
public string Name { set; get; }
/// <summary>
/// 节日的构造函数
/// </summary>
/// <param name="month">月份</param>
/// <param name="day">日</param>
/// <param name="name">节日名称</param>
/// <param name="isLunar">是否阴历,默认值false=公历</param>
public ChineseHoliday(int month, int day, string name, bool isLunar = false)
{
this.IsLunar = isLunar;
this.Month = month;
this.Day = day;
this.Name = name;
}
}