using System;using System.Collections;using System.Collections.Generic;using System.Globalization;using System.Linq;using System.Linq.Expressions;using System.Text;namespace CalendarGenerationTool{ /// <summary> /// ChinaDate /// 一日有十二时辰,一时辰有四刻,一刻有三盏茶,一盏茶有两柱香 /// 一柱香有五分,一分有六弹指,一弹指有十刹那,一刹那为一念 /// </summary> /// public static partial class ChinaDate { public static int MyYear { get; set; } #region ====== 内部常量 ==================================================================================== public static readonly ChineseLunisolarCalendar _chineseDateTime = new ChineseLunisolarCalendar(); public static readonly string[] _chineseNumber = { "〇", "一", "二", "三", "四", "五", "六", "七", "八", "九" }; public static readonly string[] _chineseMonth = { "正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "冬月", "腊月" }; public static readonly string[] _chineseDay = { "初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十", "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十", "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十" }; public static readonly string[] _chineseWeek = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" }; public static readonly string[] _celestialStem = { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" }; public static readonly string[] _terrestrialBranch = { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" }; public static readonly string[] _chineseZodiac = { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" }; public static readonly string[] _solarTerm = { "小寒", "大寒", "立春", "雨水", "惊蛰", "春分", "清明", "谷雨", "立夏", "小满", "芒种", "夏至", "小暑", "大暑", "立秋", "处暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "冬至" }; public static readonly int[] _solarTermInfo = { 0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343, 285989, 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758 }; public static Hashtable Public_Holiday = new Hashtable(), Lunar_Holiday = new Hashtable(); static ChinaDate() { //公历节日 Public_Holiday.Add("0101", "元旦"); Public_Holiday.Add("0214", "情人节"); Public_Holiday.Add("0305", "雷锋日"); Public_Holiday.Add("0308", "妇女节"); Public_Holiday.Add("0312", "植树节"); Public_Holiday.Add("0315", "消费者权益日"); Public_Holiday.Add("0501", "劳动节"); Public_Holiday.Add("0504", "青年节"); Public_Holiday.Add("0601", "儿童节"); Public_Holiday.Add("0701", "建党节"); Public_Holiday.Add("0801", "建军节"); Public_Holiday.Add("0910", "教师节"); Public_Holiday.Add("1001", "国庆节"); Public_Holiday.Add("1224", "平安夜"); Public_Holiday.Add("1225", "圣诞节"); //农历节日 Lunar_Holiday.Add("0101", "春节"); Lunar_Holiday.Add("0115", "元宵节"); Lunar_Holiday.Add("0202", "龙头节"); Lunar_Holiday.Add("0505", "端午节"); Lunar_Holiday.Add("0707", "七夕节"); Lunar_Holiday.Add("0715", "中元节"); Lunar_Holiday.Add("0815", "中秋节"); Lunar_Holiday.Add("0909", "重阳节"); Lunar_Holiday.Add("1208", "腊八节"); Lunar_Holiday.Add("1224", "小年"); } #endregion //------- 获取方法(Chinese) ------- #region ====== 获取农历年份 ==================================================================================== /// <summary> /// 获取当前日期农历年份 /// </summary> /// <returns>当前日期农历年份</returns> public static string GetYear() { return GetYear(DateTime.Now); } /// <summary> /// 获取给定日期农历年份 /// </summary> /// <param name="year">四位数字年份</param> /// <returns>给定日期农历年份</returns> public static string GetYear(int year) { return GetYear(new DateTime(year, 1, 1)); } /// <summary> /// 获取给定日期农历年份 /// </summary> /// <param name="year">四位数字年份</param> /// <param name="month">数字月份</param> /// <returns>给定日期农历年份</returns> public static string GetYear(int year, int month) { return GetYear(new DateTime(year, month, 1)); } /// <summary> /// 获取给定日期农历年份 /// </summary> /// <param name="year">四位数字年份</param> /// <param name="month">数字月份</param> /// <param name="day">数字天</param> /// <returns>给定日期农历年份</returns> public static string GetYear(int year, int month, int day) { return GetYear(new DateTime(year, month, day)); } // <summary> /// 获取农历年份 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>农历年份</returns> /// public static string GetYear(DateTime dateTime) { var yearArray = Array.ConvertAll(_chineseDateTime.GetYear(dateTime).ToString().ToCharArray(), x => int.Parse(x.ToString())); var year = new StringBuilder(); foreach (var item in yearArray) year.Append(_chineseNumber[item]); return year.ToString(); } #endregion #region ====== 获取农历月份 ==================================================================================== /// <summary> /// 获取当前日期农历月份 /// </summary> /// <returns>当前日期农历月份</returns> public static string GetMonth() { return GetMonth(DateTime.Now); } /// <summary> /// 获取给定日期农历月份 /// </summary> /// <param name="year">四位数字年份</param> /// <param name="month">数字月份</param> /// <returns>给定日期农历月份</returns> public static string GetMonth(int year, int month) { return GetMonth(new DateTime(year, month, 1)); } /// <summary> /// 获取给定日期农历月份 /// </summary> /// <param name="year">四位数字月份</param> /// <param name="month">数字月份</param> /// <param name="day">数字天</param> /// <returns>给定日期农历月份</returns> public static string GetMonth(int year, int month, int day) { return GetMonth(new DateTime(year, month, day)); } /// <summary> /// 获取农历月份 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>农历月份</returns> public static string GetMonth(DateTime dateTime) { int month = _chineseDateTime.GetMonth(dateTime); int leepMonth = _chineseDateTime.GetLeapMonth(_chineseDateTime.GetYear(dateTime));//获取闰月 if (leepMonth > 0 && leepMonth <= month) month--; return $"{GetLeap(dateTime)}{_chineseMonth[month - 1]}"; } #endregion #region ====== 获取农历日期(天) ==================================================================================== /// <summary> /// 获取当前日期农历日期(天) /// </summary> /// <returns>返回当前日期农历日期(天)</returns> public static string GetDay() { return GetDay(DateTime.Now); } /// <summary> /// 获取给定日期农历日期(天) /// </summary> /// <param name="year">四位数字月份</param> /// <param name="month">数字月份</param> /// <param name="day">数字天</param> /// <returns>返回给定日期农历日期(天)</returns> public static string GetDay(int year, int month, int day) { return GetDay(new DateTime(year, month, day)); } /// <summary> /// 获取给定日期农历日期(天) /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>返回农历给定日农历日期(天)</returns> public static string GetDay(DateTime dateTime) { string dstr = _chineseDay[_chineseDateTime.GetDayOfMonth(dateTime) - 1]; if (!string.IsNullOrEmpty(GetLunHoliday(dateTime))) { return GetLunHoliday(dateTime); } else if (!string.IsNullOrEmpty(GetPubHoliday(dateTime))) { return GetPubHoliday(dateTime); } else { return "初一".Equals(dstr) ? GetMonth(dateTime) : dstr; } } //------------------------------------------------------------------------------------------------------- /// <summary> /// 获取当前日期农历日期(天)并输出是否是节假日 /// </summary> /// <param name="IsHoliday">是否是节假日bool变量</param> /// <returns>返回当前日期农历日期(天)和输出是否是节假日,IsHoliday为true:表示当前为节假日,否则则不是!</returns> public static string GetDay(out bool IsHoliday) { return GetDay(DateTime.Now, out IsHoliday); } /// <summary> /// 获取给定日期农历日期(天) /// </summary> /// <param name="year">四位数字月份</param> /// <param name="month">数字月份</param> /// <param name="day">数字天</param> /// <param name="IsHoliday">是否是节假日bool变量</param> /// <returns>返回给定日期农历日期(天)和输出是否是节假日,IsHoliday为true:表示当前为节假日,否则则不是!</returns> public static string GetDay(int year, int month, int day, out bool IsHoliday) { return GetDay(new DateTime(year, month, day), out IsHoliday); } /// <summary> /// 获取给定日期农历日期(天)并输出是否是节假日 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <param name="IsHoliday">是否是节假日bool变量</param> /// <returns>返回农历给定日农历日期(天)和输出是否是节假日,IsHoliday为true:表示当前为节假日,否则则不是!</returns> public static string GetDay(DateTime dateTime, out bool IsHoliday) { IsHoliday = false; string dstr = _chineseDay[_chineseDateTime.GetDayOfMonth(dateTime) - 1]; if (!string.IsNullOrEmpty(GetLunHoliday(dateTime))) { IsHoliday = true; return GetLunHoliday(dateTime); } else if (!string.IsNullOrEmpty(SolarTerm(dateTime))) { IsHoliday = true; return SolarTerm(dateTime); } else if (!string.IsNullOrEmpty(GetPubHoliday(dateTime))) { IsHoliday = true; return GetPubHoliday(dateTime); } else { return "初一".Equals(dstr) ? GetMonth(dateTime) : dstr; } } //------------------------------------------------------------------------------------------------------- /// <summary> /// 获取当前日期无节日农历日期(天) /// </summary> /// <returns>返回当前日期无节日农历日期(天)</returns> public static string GetDayWithoutHoliday() { return GetDayWithoutHoliday(DateTime.Now); } /// <summary> /// 获取给定日期无节日农历日期(天) /// </summary> /// <param name="year">四位数字月份</param> /// <param name="month">数字月份</param> /// <param name="day">数字天</param> /// <returns>返回给定日期无节日农历日期(天)</returns> public static string GetDayWithoutHoliday(int year, int month, int day) { return GetDayWithoutHoliday(new DateTime(year, month, day)); } /// <summary> /// 获取给定日期无节日农历日期(天) /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>返回给定日期无节日农历日期(天);如:初九</returns> public static string GetDayWithoutHoliday(DateTime dateTime) { return _chineseDay[_chineseDateTime.GetDayOfMonth(dateTime) - 1]; } #endregion #region ====== 获取星期(数字) ==================================================================================== /// <summary> /// 获取当前日期星期(数字) /// </summary> /// <returns>以数字返回当前日期星期</returns> public static int GetWeek() { return GetWeek(DateTime.Now); } /// <summary> /// 获取给定日期星期(数字) /// </summary> /// <param name="year">四位数字月份</param> /// <param name="month">数字月份</param> /// <param name="day">数字天</param> /// <returns>以数字返回给定日期星期</returns> public static int GetWeek(int year, int month, int day) { return GetWeek(new DateTime(year, month, day)); } /// <summary> /// 获取给定日期星期(数字) /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>以数字返回返回给定日期星期</returns> public static int GetWeek(DateTime dateTime) { return (int)dateTime.DayOfWeek; } #endregion #region ====== 判断当前日期是否是农历闰月 ============================================================================= /// <summary> /// 判断当前日期是否是农历闰月 /// </summary> /// <returns>是农历闰月返回true,否则返回false</returns> public static string GetLeap() { return GetLeap(DateTime.Now); } /// <summary> /// 判断给定日期是否是农历闰月 /// </summary> /// <param name="year">四位数字年份</param> /// <param name="month">数字月份</param> /// <returns>是农历闰月返回true,否则返回false</returns> public static string GetLeap(int year, int month) { return GetLeap(new DateTime(year, month, 1)); } /// <summary> /// 判断给定日期是否是农历闰月 /// </summary> /// <param name="year">四位数字月份</param> /// <param name="month">数字月份</param> /// <param name="day">数字天</param> /// <returns>是农历闰月返回true,否则返回false</returns> public static string GetLeap(int year, int month, int day) { return GetLeap(new DateTime(year, month, day)); } /// <summary> /// 判断给定日期是否是农历闰月 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>给定日期是农历闰月返回true,否则返回false</returns> public static string GetLeap(DateTime dateTime) { int Year = _chineseDateTime.GetYear(dateTime), Month = _chineseDateTime.GetMonth(dateTime); return _chineseDateTime.IsLeapMonth(Year, Month) ? true ? "闰" : "L" : ""; } #endregion #region ====== 判断否是公历闰年 ==================================================================================== /// <summary> /// 判断当前日期年份是否为闰年 /// </summary> /// <returns>返回布尔值true为闰年,反之不是</returns> public static bool IsLeapYear() { return IsLeapYear(DateTime.Now); } /// <summary> /// 判断指定日期年份是否为闰年 /// </summary> /// <param name="year">DateTime对象</param> /// <returns>返回布尔值true为闰年,反之不是</returns> public static bool IsLeapYear(DateTime dateTime) { return IsLeapYear(dateTime.Year); } /// <summary> /// 判断指定年份是否为闰年 /// </summary> /// <param name="year">年份</param> /// <returns>返回布尔值true为闰年,反之不是</returns> public static bool IsLeapYear(int year) { return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0 && year % 3200 != 0) || year % 172800 == 0; } #endregion #region ====== 获取完整农历日期 ==================================================================================== /// <summary> /// 获取当前日期的完整农历日期 /// </summary> /// <returns>返回当前日期的完整农历日期,如:二〇一八年六月初九</returns> public static string GetChinaDate() { return GetChinaDate(DateTime.Now); } /// <summary> /// 获取按给定XXXX年【1】月【1】日的完整农历日期 /// </summary> /// <param name="year">四位数字年份</param> /// <returns>返回给定XXXX年【1】月【1】日的完整农历日期,如:二〇一八年【正月】【初一】</returns> public static string GetChinaDate(int year) { return GetChinaDate(new DateTime(year, 1, 1)); } /// <summary> /// 获取按给定XXXX年XX月【1】日的完整农历日期 /// </summary> /// <param name="year">四位数字年份</param> /// <param name="month">数字月份</param> /// <returns>返回给定XXXX年XX月1日的完整农历日期,如:二〇一八年六月【初一】</returns> public static string GetChinaDate(int year, int month) { return GetChinaDate(new DateTime(year, month, 1)); } /// <summary> /// 获取按给定日期的完整农历日期 /// </summary> /// <param name="year">四位数字年份</param> /// <param name="month">数字月份</param> /// <param name="day">数字天</param> /// <returns>返回给定日期的完整农历日期,如:二〇一八年六月初九</returns> public static string GetChinaDate(int year, int month, int day) { return GetChinaDate(new DateTime(year, month, day)); } /// <summary> /// 获取给定日期完整农历日期 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>返回给定日期农历日期,如:二〇一八年六月初九</returns> public static string GetChinaDate(DateTime dateTime) { if (dateTime < _chineseDateTime.MinSupportedDateTime || dateTime > _chineseDateTime.MaxSupportedDateTime) { throw new ArgumentOutOfRangeException( $"参数日期不在有效的范围内:只支持{_chineseDateTime.MinSupportedDateTime.ToShortTimeString()}到{_chineseDateTime.MaxSupportedDateTime}"); } return $"{GetYear(dateTime)}年{GetLeap(dateTime)}{GetMonth(dateTime)}{ _chineseDay[_chineseDateTime.GetDayOfMonth(dateTime) - 1]}"; } #endregion #region ====== 获取节日 ==================================================================================== /// <summary> /// 获取给定日期公历节日 /// </summary> /// <param name="dt">给定日期(DateTime)对象</param> /// <returns>以字符串的形式返回给定日期公历节日</returns> public static string GetPubHoliday(DateTime dt) { try { if (IsLeapYear(MyYear) || IsLeapYear(MyYear - 1)) Public_Holiday.Add("0404", "清明节"); else Public_Holiday.Add("0405", "清明节"); Public_Holiday.Add(GetMumHoliday(MyYear), "母亲节"); Public_Holiday.Add(GetDadHoliday(MyYear), "父亲节"); } catch { } string strReturn = ""; object g = Public_Holiday[dt.Month.ToString("00") + dt.Day.ToString("00")]; if (null != g) { strReturn = g.ToString(); } return strReturn; } /// <summary> /// 获取农历节日 /// </summary> /// <param name="dt"></param> /// <returns></returns> public static string GetLunHoliday(DateTime dt) { string strReturn = ""; int year = _chineseDateTime.GetYear(dt); int iMonth = _chineseDateTime.GetMonth(dt); int leapMonth = _chineseDateTime.GetLeapMonth(year); int iDay = _chineseDateTime.GetDayOfMonth(dt); if (_chineseDateTime.GetDayOfYear(dt) == _chineseDateTime.GetDaysInYear(year)) { strReturn = "除夕"; } else if (leapMonth != iMonth) { if (leapMonth != 0 && iMonth >= leapMonth) { iMonth--; } object n = Lunar_Holiday[iMonth.ToString("00") + iDay.ToString("00")]; if (null != n) { if (strReturn == "") { strReturn = n.ToString(); } else { strReturn += " " + n.ToString(); } } } return strReturn; } /// <summary> /// 获取指定年份母亲节节日 /// </summary> /// <param name="year">指定年份</param> /// <returns>母亲节字符串:"0510"</returns> public static string GetMumHoliday(int year) { int day = 14 - (GetWeek(year, 5, 1) == 0 ? 7 : GetWeek(year, 5, 1)) + 1; return $"05{day:00}"; } /// <summary> /// 获取指定年份父亲节节日 /// </summary> /// <param name="year">指定年份</param> /// <returns>父亲节字符串:"0621"</returns> public static string GetDadHoliday(int year) { int day = 21 - (GetWeek(year, 6, 1) == 0 ? 7 : GetWeek(year, 6, 1)) + 1; return $"06{day:00}"; } #endregion #region ====== 获取常规(数字)日期 ==================================================================================== /// <summary> /// 短日期(农历) /// </summary> /// <returns>返回农历数字日期</returns> public static string ToShortDateString(DateTime dateTime) { return $"{GetYear(dateTime)}-{GetLeap(dateTime)}{GetMonth(dateTime)}-{_chineseDateTime.GetDayOfMonth(dateTime)}"; } /// <summary> /// 长日期(农历) /// </summary> /// <returns>返回农历数字日期</returns> public static string ToLongDateString(DateTime dateTime) { return $"{GetYear(dateTime)}年{GetLeap(dateTime)}{GetMonth(dateTime)}月-{_chineseDateTime.GetDayOfMonth(dateTime)}日"; } /// <summary> /// 长日期时间(农历) /// </summary> /// <returns>返回农历数字日期时间</returns> public static string ToLongDateTimeString(DateTime dateTime) { return $"{GetYear(dateTime)}-{GetLeap(dateTime)}{GetMonth(dateTime)}-{_chineseDateTime.GetDayOfMonth(dateTime)} {dateTime.Hour}:{dateTime.Minute}:{dateTime.Second}"; } #endregion #region ====== 输出中文日期、中文星期、一年中的第几周、一年中的第几天、本月的第几个星期====== /// <summary> /// 获取当前日期的中文【年月日】日期 /// </summary> /// <returns>返回当前日期的中文【年月日】日期;如:二〇一八年六月初九</returns> public static string GetChineseString() { return GetChineseString(DateTime.Now, "yMd"); } /// <summary> /// 获取当前日期指定格式的中文【年月日】日期 /// </summary> /// <param name="format">日期格式化字符串,可为"yMd"、"yM"、"y"三种</param> /// <returns>返回当前日期指定格式的中文【年月日】日期;如:GetChineseString("yM"); 结果:二〇一八年六月</returns> public static string GetChineseString(string format) { return GetChineseString(DateTime.Now, format); } /// <summary> /// 获取给定日期的中文【年月日】日期 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>返回给定日期的中文【年月日】日期;如:二〇一八年六月初九</returns> public static string GetChineseString(DateTime dateTime) { return GetChineseString(dateTime, "yMd"); } /// <summary> /// 获取给定日期指定格式的中文【年月日】日期 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <param name="format">日期格式化字符串,可为"yMd"、"yM"、"y"三种</param> /// <returns>返回给定日期指定格式的中文【年月日】日期;如:GetChineseString(DateTime.Now, "yM"); 结果:二〇一八年六月</returns> public static string GetChineseString(DateTime dateTime, string format) { var year = GetYear(dateTime); var month = GetMonth(dateTime); var day = GetDayWithoutHoliday(dateTime); var date = new StringBuilder(); foreach (var item in format.ToCharArray()) { switch (item) { case 'y': date.Append($"{year}年"); break; case 'M': date.Append($"{month}月"); break; case 'd': date.Append($"{day}"); break; default: date.Append(item); break; } } var def = $"{year}年{month}月{day}"; var result = date.ToString(); return string.IsNullOrEmpty(result) ? def : result; } /// <summary> /// 获取给定日期星期 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>返回星期几,如:星期三</returns> public static string GetChineseWeek(DateTime dateTime) => _chineseWeek[(int)dateTime.DayOfWeek]; /// <summary> /// 获取给定日期是一年中第几天 /// </summary> /// <param name="date">给定日期(DateTime)对象</param> /// <returns>返回给定日期是一年中第几天</returns> public static int GetDayNumberOfYear(DateTime dateTime) { return CultureInfo.CurrentCulture.Calendar.GetDayOfYear(dateTime); } /// <summary> /// 判断给定日期是本月内的第几周 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <param name="sundayStart">默认为true:一周的第一天为周日,false:一周的第一天为周一</param> /// <returns>返回给定日期是本月内的第几周</returns> public static int GetWeekOfMonth(DateTime dateTime, bool sundayStart = true) { if (dateTime.Day == 1) return 1; else { //得到本月第一天是周几 int dayofweek = GetWeek(dateTime.Year, dateTime.Month, 1); //如果不是以周日开始,需要重新计算一下dayofweek,详细风DayOfWeek枚 //如果不是以周日开始,需要重新计算一下dayofweek,详细风DayOfWeek枚举的定义 if (!sundayStart) { dayofweek -= 1; if (dayofweek < 0) dayofweek = 7; } //得到本月的第一周一共有几天 int startWeekDays = 7 - dayofweek; //如果要判断的日期在第一周范围内,返回1 if (dateTime.Day <= startWeekDays) return 1; else { int aday = dateTime.Day + 7 - startWeekDays; return aday / 7 + (aday % 7 > 0 ? 1 : 0); } } } /// <summary> /// 获取给定日期是本年中第几个星期 /// </summary> /// <param name="date">给定日期(DateTime)对象</param> /// <returns>返回给定日期是本年中第几个星期</returns> public static int GetWeekNumberOfYear(DateTime dateTime) { return CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday); } #endregion #region ====== 输助方法(天干地支)=================================================================================== //年采用的头尾法,月采用的是节令法,主流日历基本上都这种结合,如百度的日历 /// <summary> /// 获取给定日期天干地支纪元的年 /// </summary> /// <param name="datetime">给定日期(DateTime)对象</param> /// <returns>返回给定日期天干地支纪元的年,如:庚子年</returns> public static string GetEraYear(DateTime datetime) { var sexagenaryYear = _chineseDateTime.GetSexagenaryYear(datetime); var stemIndex = _chineseDateTime.GetCelestialStem(sexagenaryYear) - 1; var branchIndex = _chineseDateTime.GetTerrestrialBranch(sexagenaryYear) - 1; return $"{_celestialStem[stemIndex]}{_terrestrialBranch[branchIndex]}"; } /// <summary> /// 获取给定年份的天干地支和生肖 /// </summary> /// <param name="year">给定的年份</param> /// <returns>返回给定年份的天干地支和生肖,如:庚子鼠</returns> public static string GetEraYearZodiac(int year) { int tg = ((year - 3) % 10) - 1 < 0 ? 9 : ((year - 3) % 10) - 1; int dz = ((year - 3) % 12) - 1 < 0 ? 11 : ((year - 3) % 12) - 1; int sx = ((year - 3) % 12) - 1 < 0 ? 11 : ((year - 3) % 12) - 1; return $"{_celestialStem[tg]}{_terrestrialBranch[dz]}{_chineseZodiac[sx]}"; } /// <summary> /// 获取给定日期天干地支纪元的月 /// </summary> /// <param name="datetime">给定日期(DateTime)对象</param> /// <returns>返回给定日期天干地支纪元的月,如:乙酉月</returns> public static string GetEraMonth(DateTime datetime) { #region ====== 节令法 ====== int Year = datetime.Year; var solarIndex = SolarTermFunc((x, y) => x <= y, datetime, out var dt); solarIndex = solarIndex == -1 ? 23 : solarIndex; var currentIndex = (int)Math.Floor(solarIndex / (decimal)2); //天干 var solarMonth = currentIndex == 0 ? 11 : currentIndex - 1; //计算天干序(月份) var sexagenaryYear = _chineseDateTime.GetSexagenaryYear(datetime); var stemYear = _chineseDateTime.GetCelestialStem(sexagenaryYear) - 1; if (solarMonth == 0) //立春时,春节前后的不同处理 { var year = _chineseDateTime.GetYear(dt); var month = _chineseDateTime.GetMonth(dt); stemYear = year == Year && month != 1 ? stemYear + 1 : stemYear; } if (solarMonth == 11) //立春在春节后,对前一节气春节前后不同处理 { var year = _chineseDateTime.GetYear(dt); stemYear = year != Year ? stemYear - 1 : stemYear; } int stemIndex; switch (stemYear) { case 0: case 5: stemIndex = 3; break; case 1: case 6: stemIndex = 5; break; case 2: case 7: stemIndex = 7; break; case 3: case 8: stemIndex = 9; break; default: stemIndex = 1; break; } //天干序 stemIndex = (stemIndex - 1 + solarMonth) % 10; //地支序 var branchIndex = currentIndex >= 11 ? currentIndex - 11 : currentIndex + 1; return $"{_celestialStem[stemIndex]}{_terrestrialBranch[branchIndex]}"; #endregion #region ====== 头尾法 ====== //这里算法要容易些,原理和节令法一样,只需取农历整年整月即可。未贴上来 #endregion } /// <summary> /// 获取给定日期天干地支纪元的日 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>返回给定日期天干地支纪元的日;如:丁丑日</returns> public static string GetEraDay(DateTime dateTime) { var ts = dateTime - new DateTime(1901, 2, 15); var offset = ts.Days; var sexagenaryDay = offset % 60; return $"{_celestialStem[sexagenaryDay % 10]}{_terrestrialBranch[sexagenaryDay % 12]}"; } /// <summary> /// 获取给定日期天干地支纪元的时 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>返回给定日期天干地支纪元的时,如:子时</returns> public static string GetEraHour(DateTime dateTime) { var hourIndex = (int)Math.Floor((dateTime.Hour + 1) / (decimal)2); hourIndex = hourIndex == 12 ? 0 : hourIndex; return _terrestrialBranch[hourIndex]; } /// <summary> /// 获取给定日期天干地支纪元的刻 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>返回给定日期天干地支纪元的刻,如:三刻</returns> public static string GetEraMinute(DateTime dateTime) { var realMinute = (dateTime.Hour % 2 == 0 ? 60 : 0) + dateTime.Minute; return $"{_chineseNumber[(int)Math.Floor(realMinute / (decimal)30) + 1]}"; } #endregion #region ====== 输出天干地支生肖 ==================================================================================== /// <summary> /// 获取当前时间天干地支纪元年月日时刻 /// </summary> /// <returns>返回指定时间天干地支纪元年月日时刻;如:戊戌年己未月甲寅日午时二刻</returns> public static string GetChineseEraString() { return GetChineseEraString(DateTime.Now); } /// <summary> /// 获取以当前时间指定格式的天干地支纪元的年月日时刻 /// </summary> /// <param name="format">支持简易参数"yMdHm",传法同中文日期</param> /// <returns>返回当前时间指定格式的天干地支纪元的年月日时刻;GetChineseEraString("yMdHm"); 结果:庚子年乙酉月丁丑日子时三刻</returns> public static string GetChineseEraString(string format) { return GetChineseEraString(DateTime.Now, format); } /// <summary> /// 获取指定时间天干地支纪元的年月日时刻 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>返回指定时间天干地支纪元的年月日时刻;如:戊戌年己未月甲寅日午时二刻</returns> public static string GetChineseEraString(DateTime dateTime) { return GetChineseEraString(dateTime, "yMdHm"); } /// <summary> /// 获取以给定时间指定格式的天干地支纪元的年月日时刻 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <param name="format">日期格式化字符串,可为"yMdHm"、"yMdH"、"yMd"、"yMd"、"yM"、"y"三种</param> /// <returns>返回给定时间指定格式的天干地支纪元的年月日时刻;GetChineseEraString(DateTime.Now, "yMdHm"); 结果:庚子年乙酉月丁丑日子时三刻</returns> public static string GetChineseEraString(DateTime dateTime, string format) { var year = GetEraYear(dateTime); var month = GetEraMonth(dateTime); var day = GetEraDay(dateTime); var hour = GetEraHour(dateTime); var minute = GetEraMinute(dateTime); var date = new StringBuilder(); foreach (var item in format.ToCharArray()) { switch (item) { case 'y': date.Append($"{year}年"); break; case 'M': date.Append($"{month}月"); break; case 'd': date.Append($"{day}日"); break; case 'H': date.Append($"{hour}时"); break; case 'm': date.Append($"{minute}刻"); break; default: date.Append(item); break; } } var def = $"{year}年{month}月{day}日{hour}时"; var result = date.ToString(); return string.IsNullOrEmpty(result) ? def : result; } /// <summary> /// 获取当前年份生肖 /// </summary> public static string GetChineseZodiac() { return GetChineseZodiac(DateTime.Now.Year); } /// <summary> /// 获取指定年份生肖 /// </summary> public static string GetChineseZodiac(int year) => _chineseZodiac[(year - 4) % 12]; #endregion #region ======(甲子年天干地支)=================================================================================== /// <summary> /// 计算与指定日期对应的一甲子(60 年)中循环中的年份。 /// </summary> /// <param name="dateTime">给定日期(DateTime)对象</param> /// <returns>甲子循环中的一个从 1 到 60 的数字,它与 date 参数对应。</returns> public static int GetSexagenaryYear(DateTime dateTime) => _chineseDateTime.GetSexagenaryYear(dateTime); /// <summary> /// 计算一甲子(60 年)循环中指定年份的天干。 /// </summary> /// <param name="sexagenaryYear">一个从 1 到 60 的整数,用于表示甲子循环中的一年。</param> /// <returns>当sexagenaryYear 小于 1 或大于 60时,返回一个从 1 到 12 的数字。否则返回 -1 。</returns> public static int GetCelestialStem(int sexagenaryYear) { if (sexagenaryYear < 1 && sexagenaryYear > 60) { return -1; } return _chineseDateTime.GetCelestialStem(sexagenaryYear); } /// <summary> /// 计算甲子 (60 年) 循环中的指定年份的地支 /// </summary> /// <param name="sexagenaryYear">一个从 1 到 60 的整数,用于表示甲子循环中的一年。</param> /// <returns>当sexagenaryYear 小于 1 或大于 60时,返回一个从 1 到 10 的数字。否则返回 -1 。</returns> public static int GetTerrestrialBranch(int sexagenaryYear) { if (sexagenaryYear < 1 && sexagenaryYear > 60) { return -1; } return _chineseDateTime.GetTerrestrialBranch(sexagenaryYear); } #endregion #region ====== 24节气 ==================================================================================== /// <summary> /// 当前节气,没有则返回空 /// </summary> public static string SolarTerm(DateTime dateTime) { var i = SolarTermFunc((x, y) => x == y, dateTime, out var dt); return i == -1 ? "" : _solarTerm[i]; } /// <summary> /// 上一个节气 /// </summary> public static string GetSolarTermPrev(DateTime dateTime) { var i = SolarTermFunc((x, y) => x < y, dateTime, out var dt); return i == -1 ? "" : _solarTerm[i]; } /// <summary> /// 下一个节气 /// </summary> public static string GetSolarTermNext(DateTime dateTime) { var i = SolarTermFunc((x, y) => x > y, dateTime, out var dt); return i == -1 ? "" : $"{_solarTerm[i]}"; } /// <summary> /// 节气计算(当前年),返回指定条件的节气序及日期(公历) /// </summary> /// <param name="func"></param> /// <param name="dateTime"></param> /// <returns>-1时即没找到</returns> public static int SolarTermFunc(Expression<Func<int, int, bool>> func, DateTime date, out DateTime dateTime) { var baseDateAndTime = new DateTime(1900, 1, 6, 2, 5, 0); //#1/6/1900 2:05:00 AM# var year = date.Year; int[] solar = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }; var expressionType = func.Body.NodeType; if (expressionType != ExpressionType.LessThan && expressionType != ExpressionType.LessThanOrEqual && expressionType != ExpressionType.GreaterThan && expressionType != ExpressionType.GreaterThanOrEqual && expressionType != ExpressionType.Equal) { throw new NotSupportedException("不受支持的操作符"); } if (expressionType == ExpressionType.LessThan || expressionType == ExpressionType.LessThanOrEqual) { solar = solar.OrderByDescending(x => x).ToArray(); } foreach (var item in solar) { var num = 525948.76 * (year - 1900) + _solarTermInfo[item - 1]; var newDate = baseDateAndTime.AddMinutes(num); //按分钟计算 if (func.Compile()(newDate.DayOfYear, date.DayOfYear)) { dateTime = newDate; return item - 1; } } dateTime = _chineseDateTime.MinSupportedDateTime; return -1; } #endregion }}