1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using System.Globalization;
    5. using System.Linq;
    6. using System.Linq.Expressions;
    7. using System.Text;
    8. namespace CalendarGenerationTool
    9. {
    10. /// <summary>
    11. /// ChinaDate
    12. /// 一日有十二时辰,一时辰有四刻,一刻有三盏茶,一盏茶有两柱香
    13. /// 一柱香有五分,一分有六弹指,一弹指有十刹那,一刹那为一念
    14. /// </summary>
    15. ///
    16. public static partial class ChinaDate
    17. {
    18. public static int MyYear { get; set; }
    19. #region ====== 内部常量 ====================================================================================
    20. public static readonly ChineseLunisolarCalendar _chineseDateTime = new ChineseLunisolarCalendar();
    21. public static readonly string[] _chineseNumber = { "〇", "一", "二", "三", "四", "五", "六", "七", "八", "九" };
    22. public static readonly string[] _chineseMonth =
    23. {
    24. "正月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "冬月", "腊月"
    25. };
    26. public static readonly string[] _chineseDay =
    27. {
    28. "初一", "初二", "初三", "初四", "初五", "初六", "初七", "初八", "初九", "初十",
    29. "十一", "十二", "十三", "十四", "十五", "十六", "十七", "十八", "十九", "二十",
    30. "廿一", "廿二", "廿三", "廿四", "廿五", "廿六", "廿七", "廿八", "廿九", "三十"
    31. };
    32. public static readonly string[] _chineseWeek =
    33. {
    34. "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"
    35. };
    36. public static readonly string[] _celestialStem = { "甲", "乙", "丙", "丁", "戊", "己", "庚", "辛", "壬", "癸" };
    37. public static readonly string[] _terrestrialBranch = { "子", "丑", "寅", "卯", "辰", "巳", "午", "未", "申", "酉", "戌", "亥" };
    38. public static readonly string[] _chineseZodiac = { "鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪" };
    39. public static readonly string[] _solarTerm =
    40. {
    41. "小寒", "大寒", "立春", "雨水", "惊蛰", "春分",
    42. "清明", "谷雨", "立夏", "小满", "芒种", "夏至",
    43. "小暑", "大暑", "立秋", "处暑", "白露", "秋分",
    44. "寒露", "霜降", "立冬", "小雪", "大雪", "冬至"
    45. };
    46. public static readonly int[] _solarTermInfo = {
    47. 0, 21208, 42467, 63836, 85337, 107014, 128867, 150921, 173149, 195551, 218072, 240693, 263343, 285989,
    48. 308563, 331033, 353350, 375494, 397447, 419210, 440795, 462224, 483532, 504758
    49. };
    50. public static Hashtable Public_Holiday = new Hashtable(), Lunar_Holiday = new Hashtable();
    51. static ChinaDate()
    52. {
    53. //公历节日
    54. Public_Holiday.Add("0101", "元旦");
    55. Public_Holiday.Add("0214", "情人节");
    56. Public_Holiday.Add("0305", "雷锋日");
    57. Public_Holiday.Add("0308", "妇女节");
    58. Public_Holiday.Add("0312", "植树节");
    59. Public_Holiday.Add("0315", "消费者权益日");
    60. Public_Holiday.Add("0501", "劳动节");
    61. Public_Holiday.Add("0504", "青年节");
    62. Public_Holiday.Add("0601", "儿童节");
    63. Public_Holiday.Add("0701", "建党节");
    64. Public_Holiday.Add("0801", "建军节");
    65. Public_Holiday.Add("0910", "教师节");
    66. Public_Holiday.Add("1001", "国庆节");
    67. Public_Holiday.Add("1224", "平安夜");
    68. Public_Holiday.Add("1225", "圣诞节");
    69. //农历节日
    70. Lunar_Holiday.Add("0101", "春节");
    71. Lunar_Holiday.Add("0115", "元宵节");
    72. Lunar_Holiday.Add("0202", "龙头节");
    73. Lunar_Holiday.Add("0505", "端午节");
    74. Lunar_Holiday.Add("0707", "七夕节");
    75. Lunar_Holiday.Add("0715", "中元节");
    76. Lunar_Holiday.Add("0815", "中秋节");
    77. Lunar_Holiday.Add("0909", "重阳节");
    78. Lunar_Holiday.Add("1208", "腊八节");
    79. Lunar_Holiday.Add("1224", "小年");
    80. }
    81. #endregion
    82. //------- 获取方法(Chinese) -------
    83. #region ====== 获取农历年份 ====================================================================================
    84. /// <summary>
    85. /// 获取当前日期农历年份
    86. /// </summary>
    87. /// <returns>当前日期农历年份</returns>
    88. public static string GetYear()
    89. {
    90. return GetYear(DateTime.Now);
    91. }
    92. /// <summary>
    93. /// 获取给定日期农历年份
    94. /// </summary>
    95. /// <param name="year">四位数字年份</param>
    96. /// <returns>给定日期农历年份</returns>
    97. public static string GetYear(int year)
    98. {
    99. return GetYear(new DateTime(year, 1, 1));
    100. }
    101. /// <summary>
    102. /// 获取给定日期农历年份
    103. /// </summary>
    104. /// <param name="year">四位数字年份</param>
    105. /// <param name="month">数字月份</param>
    106. /// <returns>给定日期农历年份</returns>
    107. public static string GetYear(int year, int month)
    108. {
    109. return GetYear(new DateTime(year, month, 1));
    110. }
    111. /// <summary>
    112. /// 获取给定日期农历年份
    113. /// </summary>
    114. /// <param name="year">四位数字年份</param>
    115. /// <param name="month">数字月份</param>
    116. /// <param name="day">数字天</param>
    117. /// <returns>给定日期农历年份</returns>
    118. public static string GetYear(int year, int month, int day)
    119. {
    120. return GetYear(new DateTime(year, month, day));
    121. }
    122. // <summary>
    123. /// 获取农历年份
    124. /// </summary>
    125. /// <param name="dateTime">给定日期(DateTime)对象</param>
    126. /// <returns>农历年份</returns>
    127. ///
    128. public static string GetYear(DateTime dateTime)
    129. {
    130. var yearArray = Array.ConvertAll(_chineseDateTime.GetYear(dateTime).ToString().ToCharArray(), x => int.Parse(x.ToString()));
    131. var year = new StringBuilder();
    132. foreach (var item in yearArray)
    133. year.Append(_chineseNumber[item]);
    134. return year.ToString();
    135. }
    136. #endregion
    137. #region ====== 获取农历月份 ====================================================================================
    138. /// <summary>
    139. /// 获取当前日期农历月份
    140. /// </summary>
    141. /// <returns>当前日期农历月份</returns>
    142. public static string GetMonth()
    143. {
    144. return GetMonth(DateTime.Now);
    145. }
    146. /// <summary>
    147. /// 获取给定日期农历月份
    148. /// </summary>
    149. /// <param name="year">四位数字年份</param>
    150. /// <param name="month">数字月份</param>
    151. /// <returns>给定日期农历月份</returns>
    152. public static string GetMonth(int year, int month)
    153. {
    154. return GetMonth(new DateTime(year, month, 1));
    155. }
    156. /// <summary>
    157. /// 获取给定日期农历月份
    158. /// </summary>
    159. /// <param name="year">四位数字月份</param>
    160. /// <param name="month">数字月份</param>
    161. /// <param name="day">数字天</param>
    162. /// <returns>给定日期农历月份</returns>
    163. public static string GetMonth(int year, int month, int day)
    164. {
    165. return GetMonth(new DateTime(year, month, day));
    166. }
    167. /// <summary>
    168. /// 获取农历月份
    169. /// </summary>
    170. /// <param name="dateTime">给定日期(DateTime)对象</param>
    171. /// <returns>农历月份</returns>
    172. public static string GetMonth(DateTime dateTime)
    173. {
    174. int month = _chineseDateTime.GetMonth(dateTime);
    175. int leepMonth = _chineseDateTime.GetLeapMonth(_chineseDateTime.GetYear(dateTime));//获取闰月
    176. if (leepMonth > 0 && leepMonth <= month) month--;
    177. return $"{GetLeap(dateTime)}{_chineseMonth[month - 1]}";
    178. }
    179. #endregion
    180. #region ====== 获取农历日期(天) ====================================================================================
    181. /// <summary>
    182. /// 获取当前日期农历日期(天)
    183. /// </summary>
    184. /// <returns>返回当前日期农历日期(天)</returns>
    185. public static string GetDay()
    186. {
    187. return GetDay(DateTime.Now);
    188. }
    189. /// <summary>
    190. /// 获取给定日期农历日期(天)
    191. /// </summary>
    192. /// <param name="year">四位数字月份</param>
    193. /// <param name="month">数字月份</param>
    194. /// <param name="day">数字天</param>
    195. /// <returns>返回给定日期农历日期(天)</returns>
    196. public static string GetDay(int year, int month, int day)
    197. {
    198. return GetDay(new DateTime(year, month, day));
    199. }
    200. /// <summary>
    201. /// 获取给定日期农历日期(天)
    202. /// </summary>
    203. /// <param name="dateTime">给定日期(DateTime)对象</param>
    204. /// <returns>返回农历给定日农历日期(天)</returns>
    205. public static string GetDay(DateTime dateTime)
    206. {
    207. string dstr = _chineseDay[_chineseDateTime.GetDayOfMonth(dateTime) - 1];
    208. if (!string.IsNullOrEmpty(GetLunHoliday(dateTime)))
    209. {
    210. return GetLunHoliday(dateTime);
    211. }
    212. else if (!string.IsNullOrEmpty(GetPubHoliday(dateTime)))
    213. {
    214. return GetPubHoliday(dateTime);
    215. }
    216. else
    217. {
    218. return "初一".Equals(dstr) ? GetMonth(dateTime) : dstr;
    219. }
    220. }
    221. //-------------------------------------------------------------------------------------------------------
    222. /// <summary>
    223. /// 获取当前日期农历日期(天)并输出是否是节假日
    224. /// </summary>
    225. /// <param name="IsHoliday">是否是节假日bool变量</param>
    226. /// <returns>返回当前日期农历日期(天)和输出是否是节假日,IsHoliday为true:表示当前为节假日,否则则不是!</returns>
    227. public static string GetDay(out bool IsHoliday)
    228. {
    229. return GetDay(DateTime.Now, out IsHoliday);
    230. }
    231. /// <summary>
    232. /// 获取给定日期农历日期(天)
    233. /// </summary>
    234. /// <param name="year">四位数字月份</param>
    235. /// <param name="month">数字月份</param>
    236. /// <param name="day">数字天</param>
    237. /// <param name="IsHoliday">是否是节假日bool变量</param>
    238. /// <returns>返回给定日期农历日期(天)和输出是否是节假日,IsHoliday为true:表示当前为节假日,否则则不是!</returns>
    239. public static string GetDay(int year, int month, int day, out bool IsHoliday)
    240. {
    241. return GetDay(new DateTime(year, month, day), out IsHoliday);
    242. }
    243. /// <summary>
    244. /// 获取给定日期农历日期(天)并输出是否是节假日
    245. /// </summary>
    246. /// <param name="dateTime">给定日期(DateTime)对象</param>
    247. /// <param name="IsHoliday">是否是节假日bool变量</param>
    248. /// <returns>返回农历给定日农历日期(天)和输出是否是节假日,IsHoliday为true:表示当前为节假日,否则则不是!</returns>
    249. public static string GetDay(DateTime dateTime, out bool IsHoliday)
    250. {
    251. IsHoliday = false;
    252. string dstr = _chineseDay[_chineseDateTime.GetDayOfMonth(dateTime) - 1];
    253. if (!string.IsNullOrEmpty(GetLunHoliday(dateTime)))
    254. {
    255. IsHoliday = true;
    256. return GetLunHoliday(dateTime);
    257. }
    258. else if (!string.IsNullOrEmpty(SolarTerm(dateTime)))
    259. {
    260. IsHoliday = true;
    261. return SolarTerm(dateTime);
    262. }
    263. else if (!string.IsNullOrEmpty(GetPubHoliday(dateTime)))
    264. {
    265. IsHoliday = true;
    266. return GetPubHoliday(dateTime);
    267. }
    268. else
    269. {
    270. return "初一".Equals(dstr) ? GetMonth(dateTime) : dstr;
    271. }
    272. }
    273. //-------------------------------------------------------------------------------------------------------
    274. /// <summary>
    275. /// 获取当前日期无节日农历日期(天)
    276. /// </summary>
    277. /// <returns>返回当前日期无节日农历日期(天)</returns>
    278. public static string GetDayWithoutHoliday()
    279. {
    280. return GetDayWithoutHoliday(DateTime.Now);
    281. }
    282. /// <summary>
    283. /// 获取给定日期无节日农历日期(天)
    284. /// </summary>
    285. /// <param name="year">四位数字月份</param>
    286. /// <param name="month">数字月份</param>
    287. /// <param name="day">数字天</param>
    288. /// <returns>返回给定日期无节日农历日期(天)</returns>
    289. public static string GetDayWithoutHoliday(int year, int month, int day)
    290. {
    291. return GetDayWithoutHoliday(new DateTime(year, month, day));
    292. }
    293. /// <summary>
    294. /// 获取给定日期无节日农历日期(天)
    295. /// </summary>
    296. /// <param name="dateTime">给定日期(DateTime)对象</param>
    297. /// <returns>返回给定日期无节日农历日期(天);如:初九</returns>
    298. public static string GetDayWithoutHoliday(DateTime dateTime)
    299. {
    300. return _chineseDay[_chineseDateTime.GetDayOfMonth(dateTime) - 1];
    301. }
    302. #endregion
    303. #region ====== 获取星期(数字) ====================================================================================
    304. /// <summary>
    305. /// 获取当前日期星期(数字)
    306. /// </summary>
    307. /// <returns>以数字返回当前日期星期</returns>
    308. public static int GetWeek()
    309. {
    310. return GetWeek(DateTime.Now);
    311. }
    312. /// <summary>
    313. /// 获取给定日期星期(数字)
    314. /// </summary>
    315. /// <param name="year">四位数字月份</param>
    316. /// <param name="month">数字月份</param>
    317. /// <param name="day">数字天</param>
    318. /// <returns>以数字返回给定日期星期</returns>
    319. public static int GetWeek(int year, int month, int day)
    320. {
    321. return GetWeek(new DateTime(year, month, day));
    322. }
    323. /// <summary>
    324. /// 获取给定日期星期(数字)
    325. /// </summary>
    326. /// <param name="dateTime">给定日期(DateTime)对象</param>
    327. /// <returns>以数字返回返回给定日期星期</returns>
    328. public static int GetWeek(DateTime dateTime)
    329. {
    330. return (int)dateTime.DayOfWeek;
    331. }
    332. #endregion
    333. #region ====== 判断当前日期是否是农历闰月 =============================================================================
    334. /// <summary>
    335. /// 判断当前日期是否是农历闰月
    336. /// </summary>
    337. /// <returns>是农历闰月返回true,否则返回false</returns>
    338. public static string GetLeap()
    339. {
    340. return GetLeap(DateTime.Now);
    341. }
    342. /// <summary>
    343. /// 判断给定日期是否是农历闰月
    344. /// </summary>
    345. /// <param name="year">四位数字年份</param>
    346. /// <param name="month">数字月份</param>
    347. /// <returns>是农历闰月返回true,否则返回false</returns>
    348. public static string GetLeap(int year, int month)
    349. {
    350. return GetLeap(new DateTime(year, month, 1));
    351. }
    352. /// <summary>
    353. /// 判断给定日期是否是农历闰月
    354. /// </summary>
    355. /// <param name="year">四位数字月份</param>
    356. /// <param name="month">数字月份</param>
    357. /// <param name="day">数字天</param>
    358. /// <returns>是农历闰月返回true,否则返回false</returns>
    359. public static string GetLeap(int year, int month, int day)
    360. {
    361. return GetLeap(new DateTime(year, month, day));
    362. }
    363. /// <summary>
    364. /// 判断给定日期是否是农历闰月
    365. /// </summary>
    366. /// <param name="dateTime">给定日期(DateTime)对象</param>
    367. /// <returns>给定日期是农历闰月返回true,否则返回false</returns>
    368. public static string GetLeap(DateTime dateTime)
    369. {
    370. int Year = _chineseDateTime.GetYear(dateTime), Month = _chineseDateTime.GetMonth(dateTime);
    371. return _chineseDateTime.IsLeapMonth(Year, Month) ? true ? "闰" : "L" : "";
    372. }
    373. #endregion
    374. #region ====== 判断否是公历闰年 ====================================================================================
    375. /// <summary>
    376. /// 判断当前日期年份是否为闰年
    377. /// </summary>
    378. /// <returns>返回布尔值true为闰年,反之不是</returns>
    379. public static bool IsLeapYear()
    380. {
    381. return IsLeapYear(DateTime.Now);
    382. }
    383. /// <summary>
    384. /// 判断指定日期年份是否为闰年
    385. /// </summary>
    386. /// <param name="year">DateTime对象</param>
    387. /// <returns>返回布尔值true为闰年,反之不是</returns>
    388. public static bool IsLeapYear(DateTime dateTime)
    389. {
    390. return IsLeapYear(dateTime.Year);
    391. }
    392. /// <summary>
    393. /// 判断指定年份是否为闰年
    394. /// </summary>
    395. /// <param name="year">年份</param>
    396. /// <returns>返回布尔值true为闰年,反之不是</returns>
    397. public static bool IsLeapYear(int year)
    398. {
    399. return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0 && year % 3200 != 0) || year % 172800 == 0;
    400. }
    401. #endregion
    402. #region ====== 获取完整农历日期 ====================================================================================
    403. /// <summary>
    404. /// 获取当前日期的完整农历日期
    405. /// </summary>
    406. /// <returns>返回当前日期的完整农历日期,如:二〇一八年六月初九</returns>
    407. public static string GetChinaDate()
    408. {
    409. return GetChinaDate(DateTime.Now);
    410. }
    411. /// <summary>
    412. /// 获取按给定XXXX年【1】月【1】日的完整农历日期
    413. /// </summary>
    414. /// <param name="year">四位数字年份</param>
    415. /// <returns>返回给定XXXX年【1】月【1】日的完整农历日期,如:二〇一八年【正月】【初一】</returns>
    416. public static string GetChinaDate(int year)
    417. {
    418. return GetChinaDate(new DateTime(year, 1, 1));
    419. }
    420. /// <summary>
    421. /// 获取按给定XXXX年XX月【1】日的完整农历日期
    422. /// </summary>
    423. /// <param name="year">四位数字年份</param>
    424. /// <param name="month">数字月份</param>
    425. /// <returns>返回给定XXXX年XX月1日的完整农历日期,如:二〇一八年六月【初一】</returns>
    426. public static string GetChinaDate(int year, int month)
    427. {
    428. return GetChinaDate(new DateTime(year, month, 1));
    429. }
    430. /// <summary>
    431. /// 获取按给定日期的完整农历日期
    432. /// </summary>
    433. /// <param name="year">四位数字年份</param>
    434. /// <param name="month">数字月份</param>
    435. /// <param name="day">数字天</param>
    436. /// <returns>返回给定日期的完整农历日期,如:二〇一八年六月初九</returns>
    437. public static string GetChinaDate(int year, int month, int day)
    438. {
    439. return GetChinaDate(new DateTime(year, month, day));
    440. }
    441. /// <summary>
    442. /// 获取给定日期完整农历日期
    443. /// </summary>
    444. /// <param name="dateTime">给定日期(DateTime)对象</param>
    445. /// <returns>返回给定日期农历日期,如:二〇一八年六月初九</returns>
    446. public static string GetChinaDate(DateTime dateTime)
    447. {
    448. if (dateTime < _chineseDateTime.MinSupportedDateTime || dateTime > _chineseDateTime.MaxSupportedDateTime)
    449. {
    450. throw new ArgumentOutOfRangeException(
    451. $"参数日期不在有效的范围内:只支持{_chineseDateTime.MinSupportedDateTime.ToShortTimeString()}到{_chineseDateTime.MaxSupportedDateTime}");
    452. }
    453. return $"{GetYear(dateTime)}年{GetLeap(dateTime)}{GetMonth(dateTime)}{ _chineseDay[_chineseDateTime.GetDayOfMonth(dateTime) - 1]}";
    454. }
    455. #endregion
    456. #region ====== 获取节日 ====================================================================================
    457. /// <summary>
    458. /// 获取给定日期公历节日
    459. /// </summary>
    460. /// <param name="dt">给定日期(DateTime)对象</param>
    461. /// <returns>以字符串的形式返回给定日期公历节日</returns>
    462. public static string GetPubHoliday(DateTime dt)
    463. {
    464. try
    465. {
    466. if (IsLeapYear(MyYear) || IsLeapYear(MyYear - 1))
    467. Public_Holiday.Add("0404", "清明节");
    468. else
    469. Public_Holiday.Add("0405", "清明节");
    470. Public_Holiday.Add(GetMumHoliday(MyYear), "母亲节");
    471. Public_Holiday.Add(GetDadHoliday(MyYear), "父亲节");
    472. }
    473. catch { }
    474. string strReturn = "";
    475. object g = Public_Holiday[dt.Month.ToString("00") + dt.Day.ToString("00")];
    476. if (null != g)
    477. {
    478. strReturn = g.ToString();
    479. }
    480. return strReturn;
    481. }
    482. /// <summary>
    483. /// 获取农历节日
    484. /// </summary>
    485. /// <param name="dt"></param>
    486. /// <returns></returns>
    487. public static string GetLunHoliday(DateTime dt)
    488. {
    489. string strReturn = "";
    490. int year = _chineseDateTime.GetYear(dt);
    491. int iMonth = _chineseDateTime.GetMonth(dt);
    492. int leapMonth = _chineseDateTime.GetLeapMonth(year);
    493. int iDay = _chineseDateTime.GetDayOfMonth(dt);
    494. if (_chineseDateTime.GetDayOfYear(dt) == _chineseDateTime.GetDaysInYear(year))
    495. {
    496. strReturn = "除夕";
    497. }
    498. else if (leapMonth != iMonth)
    499. {
    500. if (leapMonth != 0 && iMonth >= leapMonth)
    501. {
    502. iMonth--;
    503. }
    504. object n = Lunar_Holiday[iMonth.ToString("00") + iDay.ToString("00")];
    505. if (null != n)
    506. {
    507. if (strReturn == "")
    508. {
    509. strReturn = n.ToString();
    510. }
    511. else
    512. {
    513. strReturn += " " + n.ToString();
    514. }
    515. }
    516. }
    517. return strReturn;
    518. }
    519. /// <summary>
    520. /// 获取指定年份母亲节节日
    521. /// </summary>
    522. /// <param name="year">指定年份</param>
    523. /// <returns>母亲节字符串:"0510"</returns>
    524. public static string GetMumHoliday(int year)
    525. {
    526. int day = 14 - (GetWeek(year, 5, 1) == 0 ? 7 : GetWeek(year, 5, 1)) + 1;
    527. return $"05{day:00}";
    528. }
    529. /// <summary>
    530. /// 获取指定年份父亲节节日
    531. /// </summary>
    532. /// <param name="year">指定年份</param>
    533. /// <returns>父亲节字符串:"0621"</returns>
    534. public static string GetDadHoliday(int year)
    535. {
    536. int day = 21 - (GetWeek(year, 6, 1) == 0 ? 7 : GetWeek(year, 6, 1)) + 1;
    537. return $"06{day:00}";
    538. }
    539. #endregion
    540. #region ====== 获取常规(数字)日期 ====================================================================================
    541. /// <summary>
    542. /// 短日期(农历)
    543. /// </summary>
    544. /// <returns>返回农历数字日期</returns>
    545. public static string ToShortDateString(DateTime dateTime)
    546. {
    547. return $"{GetYear(dateTime)}-{GetLeap(dateTime)}{GetMonth(dateTime)}-{_chineseDateTime.GetDayOfMonth(dateTime)}";
    548. }
    549. /// <summary>
    550. /// 长日期(农历)
    551. /// </summary>
    552. /// <returns>返回农历数字日期</returns>
    553. public static string ToLongDateString(DateTime dateTime)
    554. {
    555. return $"{GetYear(dateTime)}年{GetLeap(dateTime)}{GetMonth(dateTime)}月-{_chineseDateTime.GetDayOfMonth(dateTime)}日";
    556. }
    557. /// <summary>
    558. /// 长日期时间(农历)
    559. /// </summary>
    560. /// <returns>返回农历数字日期时间</returns>
    561. public static string ToLongDateTimeString(DateTime dateTime)
    562. {
    563. return $"{GetYear(dateTime)}-{GetLeap(dateTime)}{GetMonth(dateTime)}-{_chineseDateTime.GetDayOfMonth(dateTime)} {dateTime.Hour}:{dateTime.Minute}:{dateTime.Second}";
    564. }
    565. #endregion
    566. #region ====== 输出中文日期、中文星期、一年中的第几周、一年中的第几天、本月的第几个星期======
    567. /// <summary>
    568. /// 获取当前日期的中文【年月日】日期
    569. /// </summary>
    570. /// <returns>返回当前日期的中文【年月日】日期;如:二〇一八年六月初九</returns>
    571. public static string GetChineseString()
    572. {
    573. return GetChineseString(DateTime.Now, "yMd");
    574. }
    575. /// <summary>
    576. /// 获取当前日期指定格式的中文【年月日】日期
    577. /// </summary>
    578. /// <param name="format">日期格式化字符串,可为"yMd"、"yM"、"y"三种</param>
    579. /// <returns>返回当前日期指定格式的中文【年月日】日期;如:GetChineseString("yM"); 结果:二〇一八年六月</returns>
    580. public static string GetChineseString(string format)
    581. {
    582. return GetChineseString(DateTime.Now, format);
    583. }
    584. /// <summary>
    585. /// 获取给定日期的中文【年月日】日期
    586. /// </summary>
    587. /// <param name="dateTime">给定日期(DateTime)对象</param>
    588. /// <returns>返回给定日期的中文【年月日】日期;如:二〇一八年六月初九</returns>
    589. public static string GetChineseString(DateTime dateTime)
    590. {
    591. return GetChineseString(dateTime, "yMd");
    592. }
    593. /// <summary>
    594. /// 获取给定日期指定格式的中文【年月日】日期
    595. /// </summary>
    596. /// <param name="dateTime">给定日期(DateTime)对象</param>
    597. /// <param name="format">日期格式化字符串,可为"yMd"、"yM"、"y"三种</param>
    598. /// <returns>返回给定日期指定格式的中文【年月日】日期;如:GetChineseString(DateTime.Now, "yM"); 结果:二〇一八年六月</returns>
    599. public static string GetChineseString(DateTime dateTime, string format)
    600. {
    601. var year = GetYear(dateTime);
    602. var month = GetMonth(dateTime);
    603. var day = GetDayWithoutHoliday(dateTime);
    604. var date = new StringBuilder();
    605. foreach (var item in format.ToCharArray())
    606. {
    607. switch (item)
    608. {
    609. case 'y':
    610. date.Append($"{year}年");
    611. break;
    612. case 'M':
    613. date.Append($"{month}月");
    614. break;
    615. case 'd':
    616. date.Append($"{day}");
    617. break;
    618. default:
    619. date.Append(item);
    620. break;
    621. }
    622. }
    623. var def = $"{year}年{month}月{day}";
    624. var result = date.ToString();
    625. return string.IsNullOrEmpty(result) ? def : result;
    626. }
    627. /// <summary>
    628. /// 获取给定日期星期
    629. /// </summary>
    630. /// <param name="dateTime">给定日期(DateTime)对象</param>
    631. /// <returns>返回星期几,如:星期三</returns>
    632. public static string GetChineseWeek(DateTime dateTime) => _chineseWeek[(int)dateTime.DayOfWeek];
    633. /// <summary>
    634. /// 获取给定日期是一年中第几天
    635. /// </summary>
    636. /// <param name="date">给定日期(DateTime)对象</param>
    637. /// <returns>返回给定日期是一年中第几天</returns>
    638. public static int GetDayNumberOfYear(DateTime dateTime)
    639. {
    640. return CultureInfo.CurrentCulture.Calendar.GetDayOfYear(dateTime);
    641. }
    642. /// <summary>
    643. /// 判断给定日期是本月内的第几周
    644. /// </summary>
    645. /// <param name="dateTime">给定日期(DateTime)对象</param>
    646. /// <param name="sundayStart">默认为true:一周的第一天为周日,false:一周的第一天为周一</param>
    647. /// <returns>返回给定日期是本月内的第几周</returns>
    648. public static int GetWeekOfMonth(DateTime dateTime, bool sundayStart = true)
    649. {
    650. if (dateTime.Day == 1) return 1;
    651. else
    652. {
    653. //得到本月第一天是周几
    654. int dayofweek = GetWeek(dateTime.Year, dateTime.Month, 1);
    655. //如果不是以周日开始,需要重新计算一下dayofweek,详细风DayOfWeek枚
    656. //如果不是以周日开始,需要重新计算一下dayofweek,详细风DayOfWeek枚举的定义
    657. if (!sundayStart)
    658. {
    659. dayofweek -= 1;
    660. if (dayofweek < 0)
    661. dayofweek = 7;
    662. }
    663. //得到本月的第一周一共有几天
    664. int startWeekDays = 7 - dayofweek;
    665. //如果要判断的日期在第一周范围内,返回1
    666. if (dateTime.Day <= startWeekDays)
    667. return 1;
    668. else
    669. {
    670. int aday = dateTime.Day + 7 - startWeekDays;
    671. return aday / 7 + (aday % 7 > 0 ? 1 : 0);
    672. }
    673. }
    674. }
    675. /// <summary>
    676. /// 获取给定日期是本年中第几个星期
    677. /// </summary>
    678. /// <param name="date">给定日期(DateTime)对象</param>
    679. /// <returns>返回给定日期是本年中第几个星期</returns>
    680. public static int GetWeekNumberOfYear(DateTime dateTime)
    681. {
    682. return CultureInfo.CurrentCulture.Calendar.GetWeekOfYear(dateTime, CalendarWeekRule.FirstDay, DayOfWeek.Sunday);
    683. }
    684. #endregion
    685. #region ====== 输助方法(天干地支)===================================================================================
    686. //年采用的头尾法,月采用的是节令法,主流日历基本上都这种结合,如百度的日历
    687. /// <summary>
    688. /// 获取给定日期天干地支纪元的年
    689. /// </summary>
    690. /// <param name="datetime">给定日期(DateTime)对象</param>
    691. /// <returns>返回给定日期天干地支纪元的年,如:庚子年</returns>
    692. public static string GetEraYear(DateTime datetime)
    693. {
    694. var sexagenaryYear = _chineseDateTime.GetSexagenaryYear(datetime);
    695. var stemIndex = _chineseDateTime.GetCelestialStem(sexagenaryYear) - 1;
    696. var branchIndex = _chineseDateTime.GetTerrestrialBranch(sexagenaryYear) - 1;
    697. return $"{_celestialStem[stemIndex]}{_terrestrialBranch[branchIndex]}";
    698. }
    699. /// <summary>
    700. /// 获取给定年份的天干地支和生肖
    701. /// </summary>
    702. /// <param name="year">给定的年份</param>
    703. /// <returns>返回给定年份的天干地支和生肖,如:庚子鼠</returns>
    704. public static string GetEraYearZodiac(int year)
    705. {
    706. int tg = ((year - 3) % 10) - 1 < 0 ? 9 : ((year - 3) % 10) - 1;
    707. int dz = ((year - 3) % 12) - 1 < 0 ? 11 : ((year - 3) % 12) - 1;
    708. int sx = ((year - 3) % 12) - 1 < 0 ? 11 : ((year - 3) % 12) - 1;
    709. return $"{_celestialStem[tg]}{_terrestrialBranch[dz]}{_chineseZodiac[sx]}";
    710. }
    711. /// <summary>
    712. /// 获取给定日期天干地支纪元的月
    713. /// </summary>
    714. /// <param name="datetime">给定日期(DateTime)对象</param>
    715. /// <returns>返回给定日期天干地支纪元的月,如:乙酉月</returns>
    716. public static string GetEraMonth(DateTime datetime)
    717. {
    718. #region ====== 节令法 ======
    719. int Year = datetime.Year;
    720. var solarIndex = SolarTermFunc((x, y) => x <= y, datetime, out var dt);
    721. solarIndex = solarIndex == -1 ? 23 : solarIndex;
    722. var currentIndex = (int)Math.Floor(solarIndex / (decimal)2);
    723. //天干
    724. var solarMonth = currentIndex == 0 ? 11 : currentIndex - 1; //计算天干序(月份)
    725. var sexagenaryYear = _chineseDateTime.GetSexagenaryYear(datetime);
    726. var stemYear = _chineseDateTime.GetCelestialStem(sexagenaryYear) - 1;
    727. if (solarMonth == 0) //立春时,春节前后的不同处理
    728. {
    729. var year = _chineseDateTime.GetYear(dt);
    730. var month = _chineseDateTime.GetMonth(dt);
    731. stemYear = year == Year && month != 1 ? stemYear + 1 : stemYear;
    732. }
    733. if (solarMonth == 11) //立春在春节后,对前一节气春节前后不同处理
    734. {
    735. var year = _chineseDateTime.GetYear(dt);
    736. stemYear = year != Year ? stemYear - 1 : stemYear;
    737. }
    738. int stemIndex;
    739. switch (stemYear)
    740. {
    741. case 0:
    742. case 5:
    743. stemIndex = 3;
    744. break;
    745. case 1:
    746. case 6:
    747. stemIndex = 5;
    748. break;
    749. case 2:
    750. case 7:
    751. stemIndex = 7;
    752. break;
    753. case 3:
    754. case 8:
    755. stemIndex = 9;
    756. break;
    757. default:
    758. stemIndex = 1;
    759. break;
    760. }
    761. //天干序
    762. stemIndex = (stemIndex - 1 + solarMonth) % 10;
    763. //地支序
    764. var branchIndex = currentIndex >= 11 ? currentIndex - 11 : currentIndex + 1;
    765. return $"{_celestialStem[stemIndex]}{_terrestrialBranch[branchIndex]}";
    766. #endregion
    767. #region ====== 头尾法 ======
    768. //这里算法要容易些,原理和节令法一样,只需取农历整年整月即可。未贴上来
    769. #endregion
    770. }
    771. /// <summary>
    772. /// 获取给定日期天干地支纪元的日
    773. /// </summary>
    774. /// <param name="dateTime">给定日期(DateTime)对象</param>
    775. /// <returns>返回给定日期天干地支纪元的日;如:丁丑日</returns>
    776. public static string GetEraDay(DateTime dateTime)
    777. {
    778. var ts = dateTime - new DateTime(1901, 2, 15);
    779. var offset = ts.Days;
    780. var sexagenaryDay = offset % 60;
    781. return $"{_celestialStem[sexagenaryDay % 10]}{_terrestrialBranch[sexagenaryDay % 12]}";
    782. }
    783. /// <summary>
    784. /// 获取给定日期天干地支纪元的时
    785. /// </summary>
    786. /// <param name="dateTime">给定日期(DateTime)对象</param>
    787. /// <returns>返回给定日期天干地支纪元的时,如:子时</returns>
    788. public static string GetEraHour(DateTime dateTime)
    789. {
    790. var hourIndex = (int)Math.Floor((dateTime.Hour + 1) / (decimal)2);
    791. hourIndex = hourIndex == 12 ? 0 : hourIndex;
    792. return _terrestrialBranch[hourIndex];
    793. }
    794. /// <summary>
    795. /// 获取给定日期天干地支纪元的刻
    796. /// </summary>
    797. /// <param name="dateTime">给定日期(DateTime)对象</param>
    798. /// <returns>返回给定日期天干地支纪元的刻,如:三刻</returns>
    799. public static string GetEraMinute(DateTime dateTime)
    800. {
    801. var realMinute = (dateTime.Hour % 2 == 0 ? 60 : 0) + dateTime.Minute;
    802. return $"{_chineseNumber[(int)Math.Floor(realMinute / (decimal)30) + 1]}";
    803. }
    804. #endregion
    805. #region ====== 输出天干地支生肖 ====================================================================================
    806. /// <summary>
    807. /// 获取当前时间天干地支纪元年月日时刻
    808. /// </summary>
    809. /// <returns>返回指定时间天干地支纪元年月日时刻;如:戊戌年己未月甲寅日午时二刻</returns>
    810. public static string GetChineseEraString()
    811. {
    812. return GetChineseEraString(DateTime.Now);
    813. }
    814. /// <summary>
    815. /// 获取以当前时间指定格式的天干地支纪元的年月日时刻
    816. /// </summary>
    817. /// <param name="format">支持简易参数"yMdHm",传法同中文日期</param>
    818. /// <returns>返回当前时间指定格式的天干地支纪元的年月日时刻;GetChineseEraString("yMdHm"); 结果:庚子年乙酉月丁丑日子时三刻</returns>
    819. public static string GetChineseEraString(string format)
    820. {
    821. return GetChineseEraString(DateTime.Now, format);
    822. }
    823. /// <summary>
    824. /// 获取指定时间天干地支纪元的年月日时刻
    825. /// </summary>
    826. /// <param name="dateTime">给定日期(DateTime)对象</param>
    827. /// <returns>返回指定时间天干地支纪元的年月日时刻;如:戊戌年己未月甲寅日午时二刻</returns>
    828. public static string GetChineseEraString(DateTime dateTime)
    829. {
    830. return GetChineseEraString(dateTime, "yMdHm");
    831. }
    832. /// <summary>
    833. /// 获取以给定时间指定格式的天干地支纪元的年月日时刻
    834. /// </summary>
    835. /// <param name="dateTime">给定日期(DateTime)对象</param>
    836. /// <param name="format">日期格式化字符串,可为"yMdHm"、"yMdH"、"yMd"、"yMd"、"yM"、"y"三种</param>
    837. /// <returns>返回给定时间指定格式的天干地支纪元的年月日时刻;GetChineseEraString(DateTime.Now, "yMdHm"); 结果:庚子年乙酉月丁丑日子时三刻</returns>
    838. public static string GetChineseEraString(DateTime dateTime, string format)
    839. {
    840. var year = GetEraYear(dateTime);
    841. var month = GetEraMonth(dateTime);
    842. var day = GetEraDay(dateTime);
    843. var hour = GetEraHour(dateTime);
    844. var minute = GetEraMinute(dateTime);
    845. var date = new StringBuilder();
    846. foreach (var item in format.ToCharArray())
    847. {
    848. switch (item)
    849. {
    850. case 'y':
    851. date.Append($"{year}年");
    852. break;
    853. case 'M':
    854. date.Append($"{month}月");
    855. break;
    856. case 'd':
    857. date.Append($"{day}日");
    858. break;
    859. case 'H':
    860. date.Append($"{hour}时");
    861. break;
    862. case 'm':
    863. date.Append($"{minute}刻");
    864. break;
    865. default:
    866. date.Append(item);
    867. break;
    868. }
    869. }
    870. var def = $"{year}年{month}月{day}日{hour}时";
    871. var result = date.ToString();
    872. return string.IsNullOrEmpty(result) ? def : result;
    873. }
    874. /// <summary>
    875. /// 获取当前年份生肖
    876. /// </summary>
    877. public static string GetChineseZodiac()
    878. {
    879. return GetChineseZodiac(DateTime.Now.Year);
    880. }
    881. /// <summary>
    882. /// 获取指定年份生肖
    883. /// </summary>
    884. public static string GetChineseZodiac(int year) => _chineseZodiac[(year - 4) % 12];
    885. #endregion
    886. #region ======(甲子年天干地支)===================================================================================
    887. /// <summary>
    888. /// 计算与指定日期对应的一甲子(60 年)中循环中的年份。
    889. /// </summary>
    890. /// <param name="dateTime">给定日期(DateTime)对象</param>
    891. /// <returns>甲子循环中的一个从 1 到 60 的数字,它与 date 参数对应。</returns>
    892. public static int GetSexagenaryYear(DateTime dateTime) => _chineseDateTime.GetSexagenaryYear(dateTime);
    893. /// <summary>
    894. /// 计算一甲子(60 年)循环中指定年份的天干。
    895. /// </summary>
    896. /// <param name="sexagenaryYear">一个从 1 到 60 的整数,用于表示甲子循环中的一年。</param>
    897. /// <returns>当sexagenaryYear 小于 1 或大于 60时,返回一个从 1 到 12 的数字。否则返回 -1 。</returns>
    898. public static int GetCelestialStem(int sexagenaryYear)
    899. {
    900. if (sexagenaryYear < 1 && sexagenaryYear > 60)
    901. {
    902. return -1;
    903. }
    904. return _chineseDateTime.GetCelestialStem(sexagenaryYear);
    905. }
    906. /// <summary>
    907. /// 计算甲子 (60 年) 循环中的指定年份的地支
    908. /// </summary>
    909. /// <param name="sexagenaryYear">一个从 1 到 60 的整数,用于表示甲子循环中的一年。</param>
    910. /// <returns>当sexagenaryYear 小于 1 或大于 60时,返回一个从 1 到 10 的数字。否则返回 -1 。</returns>
    911. public static int GetTerrestrialBranch(int sexagenaryYear)
    912. {
    913. if (sexagenaryYear < 1 && sexagenaryYear > 60)
    914. {
    915. return -1;
    916. }
    917. return _chineseDateTime.GetTerrestrialBranch(sexagenaryYear);
    918. }
    919. #endregion
    920. #region ====== 24节气 ====================================================================================
    921. /// <summary>
    922. /// 当前节气,没有则返回空
    923. /// </summary>
    924. public static string SolarTerm(DateTime dateTime)
    925. {
    926. var i = SolarTermFunc((x, y) => x == y, dateTime, out var dt);
    927. return i == -1 ? "" : _solarTerm[i];
    928. }
    929. /// <summary>
    930. /// 上一个节气
    931. /// </summary>
    932. public static string GetSolarTermPrev(DateTime dateTime)
    933. {
    934. var i = SolarTermFunc((x, y) => x < y, dateTime, out var dt);
    935. return i == -1 ? "" : _solarTerm[i];
    936. }
    937. /// <summary>
    938. /// 下一个节气
    939. /// </summary>
    940. public static string GetSolarTermNext(DateTime dateTime)
    941. {
    942. var i = SolarTermFunc((x, y) => x > y, dateTime, out var dt);
    943. return i == -1 ? "" : $"{_solarTerm[i]}";
    944. }
    945. /// <summary>
    946. /// 节气计算(当前年),返回指定条件的节气序及日期(公历)
    947. /// </summary>
    948. /// <param name="func"></param>
    949. /// <param name="dateTime"></param>
    950. /// <returns>-1时即没找到</returns>
    951. public static int SolarTermFunc(Expression<Func<int, int, bool>> func, DateTime date, out DateTime dateTime)
    952. {
    953. var baseDateAndTime = new DateTime(1900, 1, 6, 2, 5, 0); //#1/6/1900 2:05:00 AM#
    954. var year = date.Year;
    955. 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 };
    956. var expressionType = func.Body.NodeType;
    957. if (expressionType != ExpressionType.LessThan && expressionType != ExpressionType.LessThanOrEqual &&
    958. expressionType != ExpressionType.GreaterThan && expressionType != ExpressionType.GreaterThanOrEqual &&
    959. expressionType != ExpressionType.Equal)
    960. {
    961. throw new NotSupportedException("不受支持的操作符");
    962. }
    963. if (expressionType == ExpressionType.LessThan || expressionType == ExpressionType.LessThanOrEqual)
    964. {
    965. solar = solar.OrderByDescending(x => x).ToArray();
    966. }
    967. foreach (var item in solar)
    968. {
    969. var num = 525948.76 * (year - 1900) + _solarTermInfo[item - 1];
    970. var newDate = baseDateAndTime.AddMinutes(num); //按分钟计算
    971. if (func.Compile()(newDate.DayOfYear, date.DayOfYear))
    972. {
    973. dateTime = newDate;
    974. return item - 1;
    975. }
    976. }
    977. dateTime = _chineseDateTime.MinSupportedDateTime;
    978. return -1;
    979. }
    980. #endregion
    981. }
    982. }