Ingen beskrivning
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Lunar.cs 75KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Lunar.Util;
  6. // ReSharper disable InconsistentNaming
  7. // ReSharper disable IdentifierTypo
  8. // ReSharper disable StringLiteralTypo
  9. // ReSharper disable MemberCanBePrivate.Global
  10. namespace Lunar
  11. {
  12. /// <summary>
  13. /// 农历日期
  14. /// </summary>
  15. public class Lunar
  16. {
  17. /// <summary>
  18. /// 节气表,国标以冬至为首个节气
  19. /// </summary>
  20. public static readonly string[] JIE_QI = { "冬至", "小寒", "大寒", "立春", "雨水", "驚蟄", "春分", "清明", "穀雨", "立夏", "小满", "芒種", "夏至", "小暑", "大暑", "立秋", "處暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪" };
  21. /// <summary>
  22. /// 实际的节气表
  23. /// </summary>
  24. public static readonly string[] JIE_QI_IN_USE = { "DA_XUE", "冬至", "小寒", "大寒", "立春", "雨水", "驚蟄", "春分", "清明", "穀雨", "立夏", "小满", "芒種", "夏至", "小暑", "大暑", "立秋", "處暑", "白露", "秋分", "寒露", "霜降", "立冬", "小雪", "大雪", "DONG_ZHI", "XIAO_HAN", "DA_HAN", "LI_CHUN", "YU_SHUI", "JING_ZHE" };
  25. /// <summary>
  26. /// 农历年
  27. /// </summary>
  28. public int Year { get; }
  29. /// <summary>
  30. /// 农历月,闰月为负,即闰2月=-2
  31. /// </summary>
  32. public int Month { get; }
  33. /// <summary>
  34. /// 农历日
  35. /// </summary>
  36. public int Day { get; }
  37. /// <summary>
  38. /// 对应阳历
  39. /// </summary>
  40. public Solar Solar { get; }
  41. /// <summary>
  42. /// 时对应的天干下标,0-9
  43. /// </summary>
  44. public int TimeGanIndex { get; set; }
  45. /// <summary>
  46. /// 时对应的地支下标,0-11
  47. /// </summary>
  48. public int TimeZhiIndex { get; set; }
  49. /// <summary>
  50. /// 日对应的天干下标,0-9
  51. /// </summary>
  52. public int DayGanIndex { get; set; }
  53. /// <summary>
  54. /// 日对应的地支下标,0-11
  55. /// </summary>
  56. public int DayZhiIndex { get; set; }
  57. /// <summary>
  58. /// 日对应的天干下标(八字流派1,晚子时日柱算明天),0-9
  59. /// </summary>
  60. public int DayGanIndexExact { get; set; }
  61. /// <summary>
  62. /// 日对应的地支下标(八字流派1,晚子时日柱算明天),0-11
  63. /// </summary>
  64. public int DayZhiIndexExact { get; set; }
  65. /// <summary>
  66. /// 日对应的天干下标(八字流派2,晚子时日柱算当天),0-9
  67. /// </summary>
  68. public int DayGanIndexExact2 { get; set; }
  69. /// <summary>
  70. /// 日对应的地支下标(八字流派2,晚子时日柱算当天),0-11
  71. /// </summary>
  72. public int DayZhiIndexExact2 { get; set; }
  73. /// <summary>
  74. /// 月对应的天干下标(以节交接当天起算),0-9
  75. /// </summary>
  76. public int MonthGanIndex { get; set; }
  77. /// <summary>
  78. /// 月对应的地支下标(以节交接当天起算),0-11
  79. /// </summary>
  80. public int MonthZhiIndex { get; set; }
  81. /// <summary>
  82. /// 月对应的天干下标(八字流派1,晚子时日柱算明天),0-9
  83. /// </summary>
  84. public int MonthGanIndexExact { get; set; }
  85. /// <summary>
  86. /// 月对应的地支下标(八字流派1,晚子时日柱算明天),0-11
  87. /// </summary>
  88. public int MonthZhiIndexExact { get; set; }
  89. /// <summary>
  90. /// 年对应的天干下标(国标,以正月初一为起点),0-9
  91. /// </summary>
  92. public int YearGanIndex { get; set; }
  93. /// <summary>
  94. /// 年对应的地支下标(国标,以正月初一为起点),0-11
  95. /// </summary>
  96. public int YearZhiIndex { get; set; }
  97. /// <summary>
  98. /// 年对应的天干下标(月干计算用,以立春为起点),0-9
  99. /// </summary>
  100. public int YearGanIndexByLiChun { get; set; }
  101. /// <summary>
  102. /// 年对应的地支下标(月支计算用,以立春为起点),0-11
  103. /// </summary>
  104. public int YearZhiIndexByLiChun { get; set; }
  105. /// <summary>
  106. /// 年对应的天干下标(最精确的,供八字用,以立春交接时刻为起点),0-9
  107. /// </summary>
  108. public int YearGanIndexExact { get; set; }
  109. /// <summary>
  110. /// 年对应的地支下标(最精确的,供八字用,以立春交接时刻为起点),0-11
  111. /// </summary>
  112. public int YearZhiIndexExact { get; set; }
  113. /// <summary>
  114. /// 周下标,0-6
  115. /// </summary>
  116. public int WeekIndex { get; set; }
  117. /// <summary>
  118. /// 阳历小时
  119. /// </summary>
  120. public int Hour { get; }
  121. /// <summary>
  122. /// 阳历分钟
  123. /// </summary>
  124. public int Minute { get; }
  125. /// <summary>
  126. /// 阳历秒钟
  127. /// </summary>
  128. public int Second { get; }
  129. /// <summary>
  130. /// 节气表
  131. /// </summary>
  132. public Dictionary<string, Solar> JieQiTable { get; } = new Dictionary<string, Solar>();
  133. private EightChar.EightChar _eightChar;
  134. /// <summary>
  135. /// 八字
  136. /// </summary>
  137. public EightChar.EightChar EightChar => _eightChar ?? (_eightChar = new EightChar.EightChar(this));
  138. private Foto _foto;
  139. /// <summary>
  140. /// 佛历
  141. /// </summary>
  142. public Foto Foto => _foto ?? (_foto = Foto.FromLunar(this));
  143. private Tao _tao;
  144. /// <summary>
  145. /// 道历
  146. /// </summary>
  147. public Tao Tao => _tao ?? (_tao = Tao.FromLunar(this));
  148. /// <summary>
  149. /// 默认使用当前日期初始化
  150. /// </summary>
  151. public Lunar(): this(DateTime.Now)
  152. {
  153. }
  154. /// <summary>
  155. /// 通过农历年月日时分秒初始化
  156. /// </summary>
  157. /// <param name="lunarYear">年(农历)</param>
  158. /// <param name="lunarMonth">月(农历),1到12,闰月为负,即闰2月=-2</param>
  159. /// <param name="lunarDay">日(农历),1到31</param>
  160. /// <param name="hour">小时(阳历)</param>
  161. /// <param name="minute">分钟(阳历)</param>
  162. /// <param name="second">秒钟(阳历)</param>
  163. public Lunar(int lunarYear, int lunarMonth, int lunarDay, int hour = 0, int minute = 0, int second = 0)
  164. {
  165. var y = LunarYear.FromYear(lunarYear);
  166. var m = y.GetMonth(lunarMonth);
  167. if (null == m)
  168. {
  169. throw new ArgumentException($"wrong lunar year {lunarYear} month {lunarMonth}");
  170. }
  171. if (lunarDay < 1)
  172. {
  173. throw new ArgumentException("lunar day must bigger than 0");
  174. }
  175. var days = m.DayCount;
  176. if (lunarDay > days)
  177. {
  178. throw new ArgumentException($"only {days} days in lunar year {lunarYear} month {lunarMonth}");
  179. }
  180. Year = lunarYear;
  181. Month = lunarMonth;
  182. Day = lunarDay;
  183. Hour = hour;
  184. Minute = minute;
  185. Second = second;
  186. var noon = Solar.FromJulianDay(m.FirstJulianDay + lunarDay - 1);
  187. Solar = Solar.FromYmdHms(noon.Year, noon.Month, noon.Day, hour, minute, second);
  188. if (noon.Year != lunarYear) {
  189. y = LunarYear.FromYear(noon.Year);
  190. }
  191. Compute(y);
  192. }
  193. /// <summary>
  194. /// 通过阳历初始化
  195. /// </summary>
  196. /// <param name="solar">阳历</param>
  197. public Lunar(Solar solar)
  198. {
  199. var ly = LunarYear.FromYear(solar.Year);
  200. foreach (var m in ly.Months)
  201. {
  202. var days = solar.Subtract(Solar.FromJulianDay(m.FirstJulianDay));
  203. if (days < m.DayCount)
  204. {
  205. Year = m.Year;
  206. Month = m.Month;
  207. Day = days + 1;
  208. break;
  209. }
  210. }
  211. Hour = solar.Hour;
  212. Minute = solar.Minute;
  213. Second = solar.Second;
  214. Solar = solar;
  215. Compute(ly);
  216. }
  217. /// <summary>
  218. /// 通过阳历日期初始化
  219. /// </summary>
  220. /// <param name="date">阳历日期</param>
  221. public Lunar(DateTime date): this(Solar.FromDate(date))
  222. {
  223. }
  224. /// <summary>
  225. /// 计算节气表
  226. /// </summary>
  227. private void ComputeJieQi(LunarYear lunarYear)
  228. {
  229. var julianDays = lunarYear.JieQiJulianDays;
  230. for (int i = 0, j = JIE_QI_IN_USE.Length; i < j; i++)
  231. {
  232. JieQiTable.Add(JIE_QI_IN_USE[i], Solar.FromJulianDay(julianDays[i]));
  233. }
  234. }
  235. /// <summary>
  236. /// 计算干支纪年
  237. /// </summary>
  238. private void ComputeYear()
  239. {
  240. // 以正月初一开始
  241. var offset = Year - 4;
  242. YearGanIndex = offset % 10;
  243. YearZhiIndex = offset % 12;
  244. if (YearGanIndex < 0)
  245. {
  246. YearGanIndex += 10;
  247. }
  248. if (YearZhiIndex < 0)
  249. {
  250. YearZhiIndex += 12;
  251. }
  252. // 以立春作为新一年的开始的干支纪年
  253. var g = YearGanIndex;
  254. var z = YearZhiIndex;
  255. // 精确的干支纪年,以立春交接时刻为准
  256. var gExact = YearGanIndex;
  257. var zExact = YearZhiIndex;
  258. var solarYear = Solar.Year;
  259. var solarYmd = Solar.Ymd;
  260. var solarYmdHms = Solar.YmdHms;
  261. // 获取立春的阳历时刻
  262. var liChun = JieQiTable["立春"];
  263. if (liChun.Year != solarYear)
  264. {
  265. liChun = JieQiTable["LI_CHUN"];
  266. }
  267. var liChunYmd = liChun.Ymd;
  268. var liChunYmdHms = liChun.YmdHms;
  269. // 阳历和阴历年份相同代表正月初一及以后
  270. if (Year == solarYear)
  271. {
  272. // 立春日期判断
  273. if (string.Compare(solarYmd, liChunYmd, StringComparison.Ordinal) < 0)
  274. {
  275. g--;
  276. z--;
  277. }
  278. // 立春交接时刻判断
  279. if (string.Compare(solarYmdHms, liChunYmdHms, StringComparison.Ordinal) < 0)
  280. {
  281. gExact--;
  282. zExact--;
  283. }
  284. }
  285. else if (Year < solarYear)
  286. {
  287. if (string.Compare(solarYmd, liChunYmd, StringComparison.Ordinal) >= 0)
  288. {
  289. g++;
  290. z++;
  291. }
  292. if (string.Compare(solarYmdHms, liChunYmdHms, StringComparison.Ordinal) >= 0)
  293. {
  294. gExact++;
  295. zExact++;
  296. }
  297. }
  298. YearGanIndexByLiChun = (g < 0 ? g + 10 : g) % 10;
  299. YearZhiIndexByLiChun = (z < 0 ? z + 12 : z) % 12;
  300. YearGanIndexExact = (gExact < 0 ? gExact + 10 : gExact) % 10;
  301. YearZhiIndexExact = (zExact < 0 ? zExact + 12 : zExact) % 12;
  302. }
  303. /**
  304. * 干支纪月计算
  305. */
  306. private void ComputeMonth()
  307. {
  308. Solar start = null;
  309. Solar end;
  310. var ymd = Solar.Ymd;
  311. var time = Solar.YmdHms;
  312. var size = JIE_QI_IN_USE.Length;
  313. // 序号:大雪以前-3,大雪到小寒之间-2,小寒到立春之间-1,立春之后0
  314. var index = -3;
  315. for (var i = 0; i < size; i += 2)
  316. {
  317. end = JieQiTable[JIE_QI_IN_USE[i]];
  318. var symd = null == start ? ymd : start.Ymd;
  319. if (string.Compare(ymd, symd, StringComparison.Ordinal) >= 0 && string.Compare(ymd, end.Ymd, StringComparison.Ordinal) < 0)
  320. {
  321. break;
  322. }
  323. start = end;
  324. index++;
  325. }
  326. //干偏移值(以立春当天起算)
  327. var offset = (((YearGanIndexByLiChun + (index < 0 ? 1 : 0)) % 5 + 1) * 2) % 10;
  328. MonthGanIndex = ((index < 0 ? index + 10 : index) + offset) % 10;
  329. MonthZhiIndex = ((index < 0 ? index + 12 : index) + LunarUtil.BASE_MONTH_ZHI_INDEX) % 12;
  330. start = null;
  331. index = -3;
  332. for (var i = 0; i < size; i += 2)
  333. {
  334. end = JieQiTable[JIE_QI_IN_USE[i]];
  335. var stime = null == start ? time : start.YmdHms;
  336. if (string.Compare(time, stime, StringComparison.Ordinal) >= 0 && string.Compare(time, end.YmdHms, StringComparison.Ordinal) < 0)
  337. {
  338. break;
  339. }
  340. start = end;
  341. index++;
  342. }
  343. //干偏移值(以立春交接时刻起算)
  344. offset = (((YearGanIndexExact + (index < 0 ? 1 : 0)) % 5 + 1) * 2) % 10;
  345. MonthGanIndexExact = ((index < 0 ? index + 10 : index) + offset) % 10;
  346. MonthZhiIndexExact = ((index < 0 ? index + 12 : index) + LunarUtil.BASE_MONTH_ZHI_INDEX) % 12;
  347. }
  348. /// <summary>
  349. /// 干支纪日计算
  350. /// </summary>
  351. private void ComputeDay()
  352. {
  353. var noon = Solar.FromYmdHms(Solar.Year, Solar.Month, Solar.Day, 12);
  354. var offset = (int)noon.JulianDay - 11;
  355. DayGanIndex = offset % 10;
  356. DayZhiIndex = offset % 12;
  357. var dayGanExact = DayGanIndex;
  358. var dayZhiExact = DayZhiIndex;
  359. // 八字流派2,晚子时(夜子/子夜)日柱算当天
  360. DayGanIndexExact2 = dayGanExact;
  361. DayZhiIndexExact2 = dayZhiExact;
  362. // 八字流派1,晚子时(夜子/子夜)日柱算明天
  363. var hm = Hour.ToString().PadLeft(2, '0') + ":" + Minute.ToString().PadLeft(2, '0');
  364. if (string.Compare(hm, "23:00", StringComparison.Ordinal) >= 0 && string.Compare(hm, "23:59", StringComparison.Ordinal) <= 0)
  365. {
  366. dayGanExact++;
  367. if (dayGanExact >= 10)
  368. {
  369. dayGanExact -= 10;
  370. }
  371. dayZhiExact++;
  372. if (dayZhiExact >= 12)
  373. {
  374. dayZhiExact -= 12;
  375. }
  376. }
  377. DayGanIndexExact = dayGanExact;
  378. DayZhiIndexExact = dayZhiExact;
  379. }
  380. /// <summary>
  381. /// 干支纪时计算
  382. /// </summary>
  383. private void ComputeTime()
  384. {
  385. var hm = Hour.ToString().PadLeft(2, '0') + ":" + Minute.ToString().PadLeft(2, '0');
  386. TimeZhiIndex = LunarUtil.GetTimeZhiIndex(hm);
  387. TimeGanIndex = (DayGanIndexExact % 5 * 2 + TimeZhiIndex) % 10;
  388. }
  389. private void ComputeWeek()
  390. {
  391. WeekIndex = Solar.Week;
  392. }
  393. private void Compute(LunarYear lunarYear)
  394. {
  395. ComputeJieQi(lunarYear);
  396. ComputeYear();
  397. ComputeMonth();
  398. ComputeDay();
  399. ComputeTime();
  400. ComputeWeek();
  401. }
  402. /// <summary>
  403. /// 通过指定阳历日期获取农历
  404. /// </summary>
  405. /// <param name="date">阳历日期</param>
  406. /// <returns>农历</returns>
  407. public static Lunar FromDate(DateTime date)
  408. {
  409. return new Lunar(date);
  410. }
  411. /// <summary>
  412. /// 通过指定农历年月日时分秒获取农历
  413. /// </summary>
  414. /// <param name="lunarYear">年(农历)</param>
  415. /// <param name="lunarMonth">月(农历),1到12,闰月为负,即闰2月=-2</param>
  416. /// <param name="lunarDay">日(农历),1到31</param>
  417. /// <param name="hour">小时(阳历)</param>
  418. /// <param name="minute">分钟(阳历)</param>
  419. /// <param name="second">秒钟(阳历)</param>
  420. /// <returns>农历</returns>
  421. public static Lunar FromYmdHms(int lunarYear, int lunarMonth, int lunarDay, int hour = 0, int minute = 0, int second = 0)
  422. {
  423. return new Lunar(lunarYear, lunarMonth, lunarDay, hour, minute, second);
  424. }
  425. /// <summary>
  426. /// 年天干(以正月初一作为新年的开始),如辛
  427. /// </summary>
  428. public string YearGan => LunarUtil.GAN[YearGanIndex + 1];
  429. /// <summary>
  430. /// 年天干(以立春当天作为新年的开始),如辛
  431. /// </summary>
  432. public string YearGanByLiChun => LunarUtil.GAN[YearGanIndexByLiChun + 1];
  433. /// <summary>
  434. /// 最精确的年天干(以立春交接的时刻作为新年的开始),如辛
  435. /// </summary>
  436. public string YearGanExact => LunarUtil.GAN[YearGanIndexExact + 1];
  437. /// <summary>
  438. /// 月天干,如己
  439. /// </summary>
  440. public string MonthGan => LunarUtil.GAN[MonthGanIndex + 1];
  441. /// <summary>
  442. /// 精确的月天干(以节交接时刻起算),如己
  443. /// </summary>
  444. public string MonthGanExact => LunarUtil.GAN[MonthGanIndexExact + 1];
  445. /// <summary>
  446. /// 日天干,如甲
  447. /// </summary>
  448. public string DayGan => LunarUtil.GAN[DayGanIndex + 1];
  449. /// <summary>
  450. /// 日天干(八字流派1,晚子时日柱算明天),如甲
  451. /// </summary>
  452. public string DayGanExact => LunarUtil.GAN[DayGanIndexExact + 1];
  453. /// <summary>
  454. /// 日天干(八字流派2,晚子时日柱算当天),如甲
  455. /// </summary>
  456. public string DayGanExact2 => LunarUtil.GAN[DayGanIndexExact2 + 1];
  457. /// <summary>
  458. /// 年地支(以正月初一作为新年的开始),如亥
  459. /// </summary>
  460. public string YearZhi => LunarUtil.ZHI[YearZhiIndex + 1];
  461. /// <summary>
  462. /// 年地支(以立春当天作为新年的开始),如亥
  463. /// </summary>
  464. public string YearZhiByLiChun => LunarUtil.ZHI[YearZhiIndexByLiChun + 1];
  465. /// <summary>
  466. /// 最精确的年地支(以立春交接的时刻作为新年的开始),如亥
  467. /// </summary>
  468. public string YearZhiExact => LunarUtil.ZHI[YearZhiIndexExact + 1];
  469. /// <summary>
  470. /// 月地支,如卯
  471. /// </summary>
  472. public string MonthZhi => LunarUtil.ZHI[MonthZhiIndex + 1];
  473. /// <summary>
  474. /// 精确的月地支(以节交接时刻起算),如卯
  475. /// </summary>
  476. public string MonthZhiExact => LunarUtil.ZHI[MonthZhiIndexExact + 1];
  477. /// <summary>
  478. /// 日地支,如卯
  479. /// </summary>
  480. public string DayZhi => LunarUtil.ZHI[DayZhiIndex + 1];
  481. /// <summary>
  482. /// 日地支(八字流派1,晚子时日柱算明天),如卯
  483. /// </summary>
  484. public string DayZhiExact => LunarUtil.ZHI[DayZhiIndexExact + 1];
  485. /// <summary>
  486. /// 日地支(八字流派2,晚子时日柱算当天),如卯
  487. /// </summary>
  488. /// <returns>日地支</returns>
  489. public string DayZhiExact2 => LunarUtil.ZHI[DayZhiIndexExact2 + 1];
  490. /// <summary>
  491. /// 干支纪年(年柱)(以正月初一作为新年的开始),如辛亥
  492. /// </summary>
  493. public string YearInGanZhi => $"{YearGan}{YearZhi}";
  494. /// <summary>
  495. /// 干支纪年(年柱)(以立春当天作为新年的开始),如辛亥
  496. /// </summary>
  497. public string YearInGanZhiByLiChun => $"{YearGanByLiChun}{YearZhiByLiChun}";
  498. /// <summary>
  499. /// 干支纪年(年柱)(以立春交接的时刻作为新年的开始),如辛亥
  500. /// </summary>
  501. public string YearInGanZhiExact => $"{YearGanExact}{YearZhiExact}";
  502. /// <summary>
  503. /// 干支纪月(月柱)(以节交接当天起算),如己卯,月天干口诀:甲己丙寅首,乙庚戊寅头。丙辛从庚寅,丁壬壬寅求,戊癸甲寅居,周而复始流。月地支:正月起寅。
  504. /// </summary>
  505. public string MonthInGanZhi => $"{MonthGan}{MonthZhi}";
  506. /// <summary>
  507. /// 精确的干支纪月(月柱)(以节交接时刻起算),如己卯,月天干口诀:甲己丙寅首,乙庚戊寅头。丙辛从庚寅,丁壬壬寅求,戊癸甲寅居,周而复始流。月地支:正月起寅。
  508. /// </summary>
  509. public string MonthInGanZhiExact => $"{MonthGanExact}{MonthZhiExact}";
  510. /// <summary>
  511. /// 干支纪日(日柱),如己卯
  512. /// </summary>
  513. public string DayInGanZhi => $"{DayGan}{DayZhi}";
  514. /// <summary>
  515. /// 干支纪日(日柱,八字流派1,晚子时日柱算明天),如己卯
  516. /// </summary>
  517. public string DayInGanZhiExact => $"{DayGanExact}{DayZhiExact}";
  518. /// <summary>
  519. /// 干支纪日(日柱,八字流派2,晚子时日柱算当天),如己卯
  520. /// </summary>
  521. public string DayInGanZhiExact2 => $"{DayGanExact2}{DayZhiExact2}";
  522. /// <summary>
  523. /// 年生肖(以正月初一起算),如虎
  524. /// </summary>
  525. public string YearShengXiao => LunarUtil.SHENGXIAO[YearZhiIndex + 1];
  526. /// <summary>
  527. /// 年生肖(以立春当天起算),如虎
  528. /// </summary>
  529. public string YearShengXiaoByLiChun => LunarUtil.SHENGXIAO[YearZhiIndexByLiChun + 1];
  530. /// <summary>
  531. /// 精确的年生肖(以立春交接时刻起算),如虎
  532. /// </summary>
  533. public string YearShengXiaoExact => LunarUtil.SHENGXIAO[YearZhiIndexExact + 1];
  534. /// <summary>
  535. /// 月生肖,如虎
  536. /// </summary>
  537. public string MonthShengXiao => LunarUtil.SHENGXIAO[MonthZhiIndex + 1];
  538. /// <summary>
  539. /// 日生肖,如虎
  540. /// </summary>
  541. public string DayShengXiao => LunarUtil.SHENGXIAO[DayZhiIndex + 1];
  542. /// <summary>
  543. /// 时辰生肖,如虎
  544. /// </summary>
  545. public string TimeShengXiao => LunarUtil.SHENGXIAO[TimeZhiIndex + 1];
  546. /// <summary>
  547. /// 中文年,如二〇〇一
  548. /// </summary>
  549. public string YearInChinese
  550. {
  551. get
  552. {
  553. var y = (Year + "").ToCharArray();
  554. var s = new StringBuilder();
  555. for (int i = 0, j = y.Length; i < j; i++)
  556. {
  557. s.Append(LunarUtil.NUMBER[y[i] - '0']);
  558. }
  559. return s.ToString();
  560. }
  561. }
  562. /// <summary>
  563. /// 中文月,如正
  564. /// </summary>
  565. public string MonthInChinese => (Month < 0 ? "闰" : "") + LunarUtil.MONTH[Math.Abs(Month)];
  566. /// <summary>
  567. /// 中文日,如初一
  568. /// </summary>
  569. public string DayInChinese => LunarUtil.DAY[Day];
  570. /// <summary>
  571. /// 时辰地支
  572. /// </summary>
  573. public string TimeZhi => LunarUtil.ZHI[TimeZhiIndex + 1];
  574. /// <summary>
  575. /// 时辰天干
  576. /// </summary>
  577. public string TimeGan => LunarUtil.GAN[TimeGanIndex + 1];
  578. /// <summary>
  579. /// 时辰干支(时柱)
  580. /// </summary>
  581. public string TimeInGanZhi => $"{TimeGan}{TimeZhi}";
  582. /// <summary>
  583. /// 农历季节
  584. /// </summary>
  585. public string Season => LunarUtil.SEASON[Math.Abs(Month)];
  586. /// <summary>
  587. /// 节令
  588. /// </summary>
  589. public string Jie
  590. {
  591. get
  592. {
  593. for (int i = 0, j = JIE_QI_IN_USE.Length; i < j; i += 2)
  594. {
  595. var key = JIE_QI_IN_USE[i];
  596. var d = JieQiTable[key];
  597. if (d.Year == Solar.Year && d.Month == Solar.Month && d.Day == Solar.Day)
  598. {
  599. return ConvertJieQi(key);
  600. }
  601. }
  602. return "";
  603. }
  604. }
  605. /// <summary>
  606. /// 气令
  607. /// </summary>
  608. public string Qi
  609. {
  610. get
  611. {
  612. for (int i = 1, j = JIE_QI_IN_USE.Length; i < j; i += 2)
  613. {
  614. var key = JIE_QI_IN_USE[i];
  615. var d = JieQiTable[key];
  616. if (d.Year == Solar.Year && d.Month == Solar.Month && d.Day == Solar.Day)
  617. {
  618. return ConvertJieQi(key);
  619. }
  620. }
  621. return "";
  622. }
  623. }
  624. /// <summary>
  625. /// 星期,0123456,0代表周日,1代表周一
  626. /// </summary>
  627. public int Week => WeekIndex;
  628. /// <summary>
  629. /// 星期中文,日一二三四五六
  630. /// </summary>
  631. public string WeekInChinese => SolarUtil.WEEK[Week];
  632. /// <summary>
  633. /// 宿
  634. /// </summary>
  635. public string Xiu => LunarUtil.XIU[DayZhi + Week];
  636. /// <summary>
  637. /// 宿吉凶,吉/凶
  638. /// </summary>
  639. public string XiuLuck => LunarUtil.XIU_LUCK[Xiu];
  640. /// <summary>
  641. /// 宿歌诀
  642. /// </summary>
  643. public string XiuSong => LunarUtil.XIU_SONG[Xiu];
  644. /// <summary>
  645. /// 政
  646. /// </summary>
  647. public string Zheng => LunarUtil.ZHENG[Xiu];
  648. /// <summary>
  649. /// 动物
  650. /// </summary>
  651. public string Animal => LunarUtil.ANIMAL[Xiu];
  652. /// <summary>
  653. /// 宫
  654. /// </summary>
  655. public string Gong => LunarUtil.GONG[Xiu];
  656. /// <summary>
  657. /// 兽
  658. /// </summary>
  659. public string Shou => LunarUtil.SHOU[Gong];
  660. /// <summary>
  661. /// 节日列表,有可能一天会有多个节日
  662. /// </summary>
  663. public List<string> Festivals
  664. {
  665. get
  666. {
  667. var l = new List<string>();
  668. try
  669. {
  670. l.Add(LunarUtil.FESTIVAL[$"{Month}-{Day}"]);
  671. }
  672. catch
  673. {
  674. // ignored
  675. }
  676. if (Math.Abs(Month) == 12 && Day >= 29 && Year != Next(1).Year) {
  677. l.Add("除夕");
  678. }
  679. return l;
  680. }
  681. }
  682. /// <summary>
  683. /// 非正式的节日列表,有可能一天会有多个节日,如中元节
  684. /// </summary>
  685. public List<string> OtherFestivals
  686. {
  687. get
  688. {
  689. var l = new List<string>();
  690. try
  691. {
  692. l.AddRange(LunarUtil.OTHER_FESTIVAL[$"{Month}-{Day}"]);
  693. }
  694. catch
  695. {
  696. // ignored
  697. }
  698. var solarYmd = Solar.Ymd;
  699. var jq = JieQiTable["清明"];
  700. if (solarYmd.Equals(jq.Next(-1).Ymd))
  701. {
  702. l.Add("寒食节");
  703. }
  704. jq = JieQiTable["立春"];
  705. var offset = 4 - jq.Lunar.DayGanIndex;
  706. if (offset < 0)
  707. {
  708. offset += 10;
  709. }
  710. if (solarYmd.Equals(jq.Next(offset + 40).Ymd))
  711. {
  712. l.Add("春社");
  713. }
  714. jq = JieQiTable["立秋"];
  715. offset = 4 - jq.Lunar.DayGanIndex;
  716. if (offset < 0)
  717. {
  718. offset += 10;
  719. }
  720. if (solarYmd.Equals(jq.Next(offset + 40).Ymd))
  721. {
  722. l.Add("秋社");
  723. }
  724. return l;
  725. }
  726. }
  727. /// <summary>
  728. /// 彭祖百忌天干
  729. /// </summary>
  730. public string PengZuGan => LunarUtil.PENGZU_GAN[DayGanIndex + 1];
  731. /// <summary>
  732. /// 彭祖百忌地支
  733. /// </summary>
  734. public string PengZuZhi => LunarUtil.PENGZU_ZHI[DayZhiIndex + 1];
  735. /// <summary>
  736. /// 日喜神方位,如艮
  737. /// </summary>
  738. public string DayPositionXi => LunarUtil.POSITION_XI[DayGanIndex + 1];
  739. /// <summary>
  740. /// 日喜神方位描述,如东北
  741. /// </summary>
  742. public string DayPositionXiDesc => LunarUtil.POSITION_DESC[DayPositionXi];
  743. /// <summary>
  744. /// 日阳贵神方位,如艮
  745. /// </summary>
  746. public string DayPositionYangGui => LunarUtil.POSITION_YANG_GUI[DayGanIndex + 1];
  747. /// <summary>
  748. /// 日阳贵神方位描述,如东北
  749. /// </summary>
  750. public string DayPositionYangGuiDesc => LunarUtil.POSITION_DESC[DayPositionYangGui];
  751. /// <summary>
  752. /// 日阴贵神方位,如艮
  753. /// </summary>
  754. public string DayPositionYinGui => LunarUtil.POSITION_YIN_GUI[DayGanIndex + 1];
  755. /// <summary>
  756. /// 日阴贵神方位描述,如东北
  757. /// </summary>
  758. public string DayPositionYinGuiDesc => LunarUtil.POSITION_DESC[DayPositionYinGui];
  759. /// <summary>
  760. /// 日福神方位,流派2,如艮
  761. /// </summary>
  762. public string DayPositionFu => GetDayPositionFu();
  763. /// <summary>
  764. /// 获取日福神方位
  765. /// </summary>
  766. /// <param name="sect">流派,可选1或2</param>
  767. /// <returns>福神方位,如艮</returns>
  768. public string GetDayPositionFu(int sect = 2)
  769. {
  770. return (1 == sect ? LunarUtil.POSITION_FU : LunarUtil.POSITION_FU_2)[DayGanIndex + 1];
  771. }
  772. /// <summary>
  773. /// 日福神方位描述,如东北
  774. /// </summary>
  775. public string DayPositionFuDesc => GetDayPositionFuDesc();
  776. /// <summary>
  777. /// 获取日福神方位描述
  778. /// </summary>
  779. /// <param name="sect">流派,可选1或2</param>
  780. /// <returns>方位描述,如东北</returns>
  781. public string GetDayPositionFuDesc(int sect = 2)
  782. {
  783. return LunarUtil.POSITION_DESC[GetDayPositionFu(sect)];
  784. }
  785. /// <summary>
  786. /// 日财神方位,如艮
  787. /// </summary>
  788. public string DayPositionCai => LunarUtil.POSITION_CAI[DayGanIndex + 1];
  789. /// <summary>
  790. /// 日财神方位描述,如东北
  791. /// </summary>
  792. public string DayPositionCaiDesc => LunarUtil.POSITION_DESC[DayPositionCai];
  793. /// <summary>
  794. /// 获取年太岁方位
  795. /// </summary>
  796. /// <param name="sect">流派:2为新年以立春零点起算;1为新年以正月初一起算;3为新年以立春节气交接的时刻起算</param>
  797. /// <returns>方位</returns>
  798. public string GetYearPositionTaiSui(int sect = 2)
  799. {
  800. int yearZhiIndex;
  801. switch (sect)
  802. {
  803. case 1:
  804. yearZhiIndex = YearZhiIndex;
  805. break;
  806. case 3:
  807. yearZhiIndex = YearZhiIndexExact;
  808. break;
  809. default:
  810. yearZhiIndex = YearZhiIndexByLiChun;
  811. break;
  812. }
  813. return LunarUtil.POSITION_TAI_SUI_YEAR[yearZhiIndex];
  814. }
  815. /// <summary>
  816. /// 年太岁方位(流派2新年以立春零点起算)
  817. /// </summary>
  818. public string YearPositionTaiSui => GetYearPositionTaiSui();
  819. /// <summary>
  820. /// 年太岁方位描述(流派2新年以立春零点起算),如东北
  821. /// </summary>
  822. public string YearPositionTaiSuiDesc => GetYearPositionTaiSuiDesc();
  823. /// <summary>
  824. /// 年太岁方位描述
  825. /// </summary>
  826. /// <param name="sect">流派:2为新年以立春零点起算;1为新年以正月初一起算;3为新年以立春节气交接的时刻起算</param>
  827. /// <returns>方位描述,如东北</returns>
  828. public string GetYearPositionTaiSuiDesc(int sect = 2)
  829. {
  830. return LunarUtil.POSITION_DESC[GetYearPositionTaiSui(sect)];
  831. }
  832. /// <summary>
  833. /// 计算月太岁方
  834. /// </summary>
  835. /// <param name="monthZhiIndex">月支序号</param>
  836. /// <param name="monthGanIndex">月干序号</param>
  837. /// <returns>太岁方</returns>
  838. protected string GetMonthPositionTaiSui(int monthZhiIndex, int monthGanIndex)
  839. {
  840. string p;
  841. var m = monthZhiIndex - LunarUtil.BASE_MONTH_ZHI_INDEX;
  842. if (m < 0)
  843. {
  844. m += 12;
  845. }
  846. switch (m)
  847. {
  848. case 0:
  849. case 4:
  850. case 8:
  851. p = "艮";
  852. break;
  853. case 2:
  854. case 6:
  855. case 10:
  856. p = "坤";
  857. break;
  858. case 3:
  859. case 7:
  860. case 11:
  861. p = "巽";
  862. break;
  863. default:
  864. p = LunarUtil.POSITION_GAN[monthGanIndex];
  865. break;
  866. }
  867. return p;
  868. }
  869. /// <summary>
  870. /// 月太岁方位(流派2新的一月以节交接当天零点起算),如艮
  871. /// </summary>
  872. public string MonthPositionTaiSui => GetMonthPositionTaiSui();
  873. /// <summary>
  874. /// 获取月太岁方位
  875. /// </summary>
  876. /// <param name="sect">流派:2为新的一月以节交接当天零点起算;3为新的一月以节交接准确时刻起算</param>
  877. /// <returns>方位,如艮</returns>
  878. public string GetMonthPositionTaiSui(int sect = 2)
  879. {
  880. int monthZhiIndex;
  881. int monthGanIndex;
  882. switch (sect)
  883. {
  884. case 3:
  885. monthZhiIndex = MonthZhiIndexExact;
  886. monthGanIndex = MonthGanIndexExact;
  887. break;
  888. default:
  889. monthZhiIndex = MonthZhiIndex;
  890. monthGanIndex = MonthGanIndex;
  891. break;
  892. }
  893. return GetMonthPositionTaiSui(monthZhiIndex, monthGanIndex);
  894. }
  895. /// <summary>
  896. /// 月太岁方位描述(流派2新的一月以节交接当天零点起算),如东北
  897. /// </summary>
  898. public string MonthPositionTaiSuiDesc => GetMonthPositionTaiSuiDesc();
  899. /// <summary>
  900. /// 获取月太岁方位描述
  901. /// </summary>
  902. /// <param name="sect">流派:2为新的一月以节交接当天零点起算;3为新的一月以节交接准确时刻起算</param>
  903. /// <returns>方位描述,如东北</returns>
  904. public string GetMonthPositionTaiSuiDesc(int sect = 2)
  905. {
  906. return LunarUtil.POSITION_DESC[GetMonthPositionTaiSui(sect)];
  907. }
  908. /// <summary>
  909. /// 计算日太岁方
  910. /// </summary>
  911. /// <param name="dayInGanZhi">日干序号</param>
  912. /// <param name="yearZhiIndex">年支序号</param>
  913. /// <returns>太岁方</returns>
  914. protected string GetDayPositionTaiSui(string dayInGanZhi, int yearZhiIndex)
  915. {
  916. string p;
  917. if ("甲子,乙丑,丙寅,丁卯,戊辰,已巳".Contains(dayInGanZhi))
  918. {
  919. p = "震";
  920. }
  921. else if ("丙子,丁丑,戊寅,已卯,庚辰,辛巳".Contains(dayInGanZhi))
  922. {
  923. p = "离";
  924. }
  925. else if ("戊子,已丑,庚寅,辛卯,壬辰,癸巳".Contains(dayInGanZhi))
  926. {
  927. p = "中";
  928. }
  929. else if ("庚子,辛丑,壬寅,癸卯,甲辰,乙巳".Contains(dayInGanZhi))
  930. {
  931. p = "兑";
  932. }
  933. else if ("壬子,癸丑,甲寅,乙卯,丙辰,丁巳".Contains(dayInGanZhi))
  934. {
  935. p = "坎";
  936. }
  937. else
  938. {
  939. p = LunarUtil.POSITION_TAI_SUI_YEAR[yearZhiIndex];
  940. }
  941. return p;
  942. }
  943. /// <summary>
  944. /// 获取日太岁方位(流派2新年以立春零点起算),如艮
  945. /// </summary>
  946. public string DayPositionTaiSui => GetDayPositionTaiSui();
  947. /// <summary>
  948. /// 获取日太岁方位
  949. /// </summary>
  950. /// <param name="sect">流派:2新年以立春零点起算;1新年以正月初一起算;3新年以立春节气交接的时刻起算</param>
  951. /// <returns>方位,如艮</returns>
  952. public string GetDayPositionTaiSui(int sect = 2)
  953. {
  954. string dayInGanZhi;
  955. int yearZhiIndex;
  956. switch (sect)
  957. {
  958. case 1:
  959. dayInGanZhi = DayInGanZhi;
  960. yearZhiIndex = YearZhiIndex;
  961. break;
  962. case 3:
  963. dayInGanZhi = DayInGanZhi;
  964. yearZhiIndex = YearZhiIndexExact;
  965. break;
  966. default:
  967. dayInGanZhi = DayInGanZhiExact2;
  968. yearZhiIndex = YearZhiIndexByLiChun;
  969. break;
  970. }
  971. return GetDayPositionTaiSui(dayInGanZhi, yearZhiIndex);
  972. }
  973. /// <summary>
  974. /// 日太岁方位描述(流派2新年以立春零点起算),如东北
  975. /// </summary>
  976. public string DayPositionTaiSuiDesc => GetDayPositionTaiSuiDesc();
  977. /// <summary>
  978. /// 获取日太岁方位描述
  979. /// </summary>
  980. /// <param name="sect">流派:2新年以立春零点起算;1新年以正月初一起算;3新年以立春节气交接的时刻起算</param>
  981. /// <returns>方位描述,如东北</returns>
  982. public string GetDayPositionTaiSuiDesc(int sect = 2)
  983. {
  984. return LunarUtil.POSITION_DESC[GetDayPositionTaiSui(sect)];
  985. }
  986. /// <summary>
  987. /// 时辰喜神方位,如艮
  988. /// </summary>
  989. public string TimePositionXi => LunarUtil.POSITION_XI[TimeGanIndex + 1];
  990. /// <summary>
  991. /// 时辰喜神方位描述,如东北
  992. /// </summary>
  993. public string TimePositionXiDesc => LunarUtil.POSITION_DESC[TimePositionXi];
  994. /// <summary>
  995. /// 时辰阳贵神方位,如艮
  996. /// </summary>
  997. public string TimePositionYangGui => LunarUtil.POSITION_YANG_GUI[TimeGanIndex + 1];
  998. /// <summary>
  999. /// 时辰阳贵神方位描述,如东北
  1000. /// </summary>
  1001. public string TimePositionYangGuiDesc => LunarUtil.POSITION_DESC[TimePositionYangGui];
  1002. /// <summary>
  1003. /// 时辰阴贵神方位,如艮
  1004. /// </summary>
  1005. public string TimePositionYinGui => LunarUtil.POSITION_YIN_GUI[TimeGanIndex + 1];
  1006. /// <summary>
  1007. /// 时辰阴贵神方位描述,如东北
  1008. /// </summary>
  1009. public string TimePositionYinGuiDesc => LunarUtil.POSITION_DESC[TimePositionYinGui];
  1010. /// <summary>
  1011. /// 时辰福神方位(流派2),如艮
  1012. /// </summary>
  1013. public string TimePositionFu => GetTimePositionFu();
  1014. /// <summary>
  1015. /// 获取时辰福神方位
  1016. /// </summary>
  1017. /// <param name="sect">流派,可选1或2</param>
  1018. /// <returns>福神方位,如艮</returns>
  1019. public string GetTimePositionFu(int sect = 2)
  1020. {
  1021. return (1 == sect ? LunarUtil.POSITION_FU : LunarUtil.POSITION_FU_2)[TimeGanIndex + 1];
  1022. }
  1023. /// <summary>
  1024. /// 时辰福神方位描述(流派2),如东北
  1025. /// </summary>
  1026. public string TimePositionFuDesc => GetTimePositionFuDesc();
  1027. /// <summary>
  1028. /// 获取时辰福神方位描述
  1029. /// </summary>
  1030. /// <param name="sect">流派,可选1或2</param>
  1031. /// <returns>福神方位描述,如东北</returns>
  1032. public string GetTimePositionFuDesc(int sect = 2)
  1033. {
  1034. return LunarUtil.POSITION_DESC[GetTimePositionFu(sect)];
  1035. }
  1036. /// <summary>
  1037. /// 时辰财神方位,如艮
  1038. /// </summary>
  1039. public string TimePositionCai => LunarUtil.POSITION_CAI[TimeGanIndex + 1];
  1040. /// <summary>
  1041. /// 时辰财神方位描述,如东北
  1042. /// </summary>
  1043. public string TimePositionCaiDesc => LunarUtil.POSITION_DESC[TimePositionCai];
  1044. /// <summary>
  1045. /// 日冲,如申
  1046. /// </summary>
  1047. public string DayChong => LunarUtil.CHONG[DayZhiIndex];
  1048. /// <summary>
  1049. /// 时冲,如申
  1050. /// </summary>
  1051. public string TimeChong => LunarUtil.CHONG[TimeZhiIndex];
  1052. /// <summary>
  1053. /// 无情之克的日冲天干,如甲
  1054. /// </summary>
  1055. public string DayChongGan => LunarUtil.CHONG_GAN[DayGanIndex];
  1056. /// <summary>
  1057. /// 无情之克的时冲天干,如甲
  1058. /// </summary>
  1059. public string TimeChongGan => LunarUtil.CHONG_GAN[TimeGanIndex];
  1060. /// <summary>
  1061. /// 有情之克的日冲天干,如甲
  1062. /// </summary>
  1063. public string DayChongGanTie => LunarUtil.CHONG_GAN_TIE[DayGanIndex];
  1064. /// <summary>
  1065. /// 有情之克的时冲天干,如甲
  1066. /// </summary>
  1067. public string TimeChongGanTie => LunarUtil.CHONG_GAN_TIE[TimeGanIndex];
  1068. /// <summary>
  1069. /// 日冲生肖,如猴
  1070. /// </summary>
  1071. public string DayChongShengXiao
  1072. {
  1073. get
  1074. {
  1075. for (int i = 0, j = LunarUtil.ZHI.Length; i < j; i++)
  1076. {
  1077. if (LunarUtil.ZHI[i].Equals(DayChong))
  1078. {
  1079. return LunarUtil.SHENGXIAO[i];
  1080. }
  1081. }
  1082. return "";
  1083. }
  1084. }
  1085. /// <summary>
  1086. /// 时冲生肖,如猴
  1087. /// </summary>
  1088. public string TimeChongShengXiao
  1089. {
  1090. get
  1091. {
  1092. string chong = TimeChong;
  1093. for (int i = 0, j = LunarUtil.ZHI.Length; i < j; i++)
  1094. {
  1095. if (LunarUtil.ZHI[i].Equals(chong))
  1096. {
  1097. return LunarUtil.SHENGXIAO[i];
  1098. }
  1099. }
  1100. return "";
  1101. }
  1102. }
  1103. /// <summary>
  1104. /// 日冲描述,如(壬申)猴
  1105. /// </summary>
  1106. public string DayChongDesc => $"({DayChongGan}{DayChong}){DayChongShengXiao}";
  1107. /// <summary>
  1108. /// 时冲描述,如(壬申)猴
  1109. /// </summary>
  1110. public string TimeChongDesc => $"({TimeChongGan}{TimeChong}){TimeChongShengXiao}";
  1111. /// <summary>
  1112. /// 日煞,如北
  1113. /// </summary>
  1114. public string DaySha => LunarUtil.SHA[DayZhi];
  1115. /// <summary>
  1116. /// 时煞,如北
  1117. /// </summary>
  1118. public string TimeSha => LunarUtil.SHA[TimeZhi];
  1119. /// <summary>
  1120. /// 年纳音,如剑锋金
  1121. /// </summary>
  1122. public string YearNaYin => LunarUtil.NAYIN[YearInGanZhi];
  1123. /// <summary>
  1124. /// 月纳音,如剑锋金
  1125. /// </summary>
  1126. public string MonthNaYin => LunarUtil.NAYIN[MonthInGanZhi];
  1127. /// <summary>
  1128. /// 日纳音,如剑锋金
  1129. /// </summary>
  1130. public string DayNaYin => LunarUtil.NAYIN[DayInGanZhi];
  1131. /// <summary>
  1132. /// 时辰纳音,如剑锋金
  1133. /// </summary>
  1134. public string TimeNaYin => LunarUtil.NAYIN[TimeInGanZhi];
  1135. /// <summary>
  1136. /// 十二执星:建、除、满、平、定、执、破、危、成、收、开、闭。当月支与日支相同即为建,依次类推
  1137. /// </summary>
  1138. public string ZhiXing
  1139. {
  1140. get
  1141. {
  1142. var offset = DayZhiIndex - MonthZhiIndex;
  1143. if (offset < 0)
  1144. {
  1145. offset += 12;
  1146. }
  1147. return LunarUtil.ZHI_XING[offset + 1];
  1148. }
  1149. }
  1150. /// <summary>
  1151. /// 值日天神
  1152. /// </summary>
  1153. public string DayTianShen => LunarUtil.TIAN_SHEN[(DayZhiIndex + LunarUtil.ZHI_TIAN_SHEN_OFFSET[MonthZhi]) % 12 + 1];
  1154. /// <summary>
  1155. /// 值时天神
  1156. /// </summary>
  1157. public string TimeTianShen => LunarUtil.TIAN_SHEN[(TimeZhiIndex + LunarUtil.ZHI_TIAN_SHEN_OFFSET[DayZhiExact]) % 12 + 1];
  1158. /// <summary>
  1159. /// 值日天神类型:黄道/黑道
  1160. /// </summary>
  1161. public string DayTianShenType => LunarUtil.TIAN_SHEN_TYPE[DayTianShen];
  1162. /// <summary>
  1163. /// 值时天神类型:黄道/黑道
  1164. /// </summary>
  1165. public string TimeTianShenType => LunarUtil.TIAN_SHEN_TYPE[TimeTianShen];
  1166. /// <summary>
  1167. /// 值日天神吉凶:吉/凶
  1168. /// </summary>
  1169. public string DayTianShenLuck => LunarUtil.TIAN_SHEN_TYPE_LUCK[DayTianShenType];
  1170. /// <summary>
  1171. /// 值时天神吉凶:吉/凶
  1172. /// </summary>
  1173. public string TimeTianShenLuck => LunarUtil.TIAN_SHEN_TYPE_LUCK[TimeTianShenType];
  1174. /// <summary>
  1175. /// 逐日胎神方位
  1176. /// </summary>
  1177. public string DayPositionTai => LunarUtil.POSITION_TAI_DAY[LunarUtil.GetJiaZiIndex(DayInGanZhi)];
  1178. /// <summary>
  1179. /// 逐月胎神方位,闰月无
  1180. /// </summary>
  1181. public string MonthPositionTai => Month < 0 ? "" : LunarUtil.POSITION_TAI_MONTH[Month - 1];
  1182. /// <summary>
  1183. /// 日宜,如果没有,返回["无"]
  1184. /// </summary>
  1185. public List<string> DayYi => LunarUtil.GetDayYi(MonthInGanZhiExact, DayInGanZhi);
  1186. /// <summary>
  1187. /// 日忌,如果没有,返回["无"]
  1188. /// </summary>
  1189. public List<string> DayJi => LunarUtil.GetDayJi(MonthInGanZhiExact, DayInGanZhi);
  1190. /// <summary>
  1191. /// 日吉神(宜趋),如果没有,返回["无"]
  1192. /// </summary>
  1193. public List<string> DayJiShen => LunarUtil.GetDayJiShen(Month, DayInGanZhi);
  1194. /// <summary>
  1195. /// 日凶煞(宜忌),如果没有,返回["无"]
  1196. /// </summary>
  1197. public List<string> DayXiongSha => LunarUtil.GetDayXiongSha(Month, DayInGanZhi);
  1198. /// <summary>
  1199. /// 时辰宜,如果没有,返回["无"]
  1200. /// </summary>
  1201. /// <returns>宜</returns>
  1202. public List<string> TimeYi => LunarUtil.GetTimeYi(DayInGanZhiExact, TimeInGanZhi);
  1203. /// <summary>
  1204. /// 时辰忌,如果没有,返回["无"]
  1205. /// </summary>
  1206. public List<string> TimeJi => LunarUtil.GetTimeJi(DayInGanZhiExact, TimeInGanZhi);
  1207. /// <summary>
  1208. /// 月相
  1209. /// </summary>
  1210. public string YueXiang => LunarUtil.YUE_XIANG[Day];
  1211. /// <summary>
  1212. /// 计算年九星
  1213. /// </summary>
  1214. /// <param name="yearInGanZhi">年干支</param>
  1215. /// <returns>九星</returns>
  1216. protected NineStar GetYearNineStar(string yearInGanZhi)
  1217. {
  1218. var indexExact = LunarUtil.GetJiaZiIndex(yearInGanZhi) + 1;
  1219. var index = LunarUtil.GetJiaZiIndex(YearInGanZhi) + 1;
  1220. var yearOffset = indexExact - index;
  1221. if (yearOffset > 1) {
  1222. yearOffset -= 60;
  1223. } else if (yearOffset < -1) {
  1224. yearOffset += 60;
  1225. }
  1226. var yuan = (Year + yearOffset + 2696) / 60 % 3;
  1227. var offset = (62 + yuan * 3 - indexExact) % 9;
  1228. if (0 == offset)
  1229. {
  1230. offset = 9;
  1231. }
  1232. return NineStar.FromIndex(offset - 1);
  1233. }
  1234. /// <summary>
  1235. /// 获取值年九星(流年紫白星起例歌诀:年上吉星论甲子,逐年星逆中宫起;上中下作三元汇,一上四中七下兑。)
  1236. /// </summary>
  1237. /// <param name="sect">流派:2为新年以立春零点起算;1为新年以正月初一起算;3为新年以立春节气交接的时刻起算</param>
  1238. /// <returns>九星</returns>
  1239. public NineStar GetYearNineStar(int sect = 2)
  1240. {
  1241. string yearInGanZhi;
  1242. switch (sect)
  1243. {
  1244. case 1:
  1245. yearInGanZhi = this.YearInGanZhi;
  1246. break;
  1247. case 3:
  1248. yearInGanZhi = this.YearInGanZhiExact;
  1249. break;
  1250. default:
  1251. yearInGanZhi = this.YearInGanZhiByLiChun;
  1252. break;
  1253. }
  1254. return GetYearNineStar(yearInGanZhi);
  1255. }
  1256. /// <summary>
  1257. /// 值年九星(流派2新年以立春零点起算。流年紫白星起例歌诀:年上吉星论甲子,逐年星逆中宫起;上中下作三元汇,一上四中七下兑。)
  1258. /// </summary>
  1259. public NineStar YearNineStar => GetYearNineStar();
  1260. /// <summary>
  1261. /// 计算月九星
  1262. /// </summary>
  1263. /// <param name="yearZhiIndex">年支序号</param>
  1264. /// <param name="monthZhiIndex">月支序号</param>
  1265. /// <returns>九星</returns>
  1266. protected NineStar GetMonthNineStar(int yearZhiIndex, int monthZhiIndex)
  1267. {
  1268. var n = 27 - yearZhiIndex % 3 * 3;
  1269. if (monthZhiIndex < LunarUtil.BASE_MONTH_ZHI_INDEX)
  1270. {
  1271. n -= 3;
  1272. }
  1273. var offset = (n - monthZhiIndex) % 9;
  1274. return NineStar.FromIndex(offset);
  1275. }
  1276. /// <summary>
  1277. /// 获取值月九星(月紫白星歌诀:子午卯酉八白起,寅申巳亥二黑求,辰戌丑未五黄中。)
  1278. /// </summary>
  1279. /// <param name="sect">流派:2为新的一月以节交接当天零点起算;3为新的一月以节交接准确时刻起算</param>
  1280. /// <returns>九星</returns>
  1281. public NineStar GetMonthNineStar(int sect = 2)
  1282. {
  1283. int yearZhiIndex;
  1284. int monthZhiIndex;
  1285. switch (sect)
  1286. {
  1287. case 1:
  1288. yearZhiIndex = YearZhiIndex;
  1289. monthZhiIndex = MonthZhiIndex;
  1290. break;
  1291. case 3:
  1292. yearZhiIndex = YearZhiIndexExact;
  1293. monthZhiIndex = MonthZhiIndexExact;
  1294. break;
  1295. default:
  1296. yearZhiIndex = YearZhiIndexByLiChun;
  1297. monthZhiIndex = MonthZhiIndex;
  1298. break;
  1299. }
  1300. return GetMonthNineStar(yearZhiIndex, monthZhiIndex);
  1301. }
  1302. /// <summary>
  1303. /// 值月九星(流派2新的一月以节交接当天零点起算。月紫白星歌诀:子午卯酉八白起,寅申巳亥二黑求,辰戌丑未五黄中。)
  1304. /// </summary>
  1305. public NineStar MonthNineStar => GetMonthNineStar();
  1306. /// <summary>
  1307. /// 值日九星(日家紫白星歌诀:日家白法不难求,二十四气六宫周;冬至雨水及穀雨,阳顺一七四中游;夏至處暑霜降后,九三六星逆行求。)
  1308. /// </summary>
  1309. public NineStar DayNineStar
  1310. {
  1311. get
  1312. {
  1313. var solarYmd = Solar.Ymd;
  1314. var dongZhi = JieQiTable["冬至"];
  1315. var dongZhi2 = JieQiTable["DONG_ZHI"];
  1316. var xiaZhi = JieQiTable["夏至"];
  1317. var dongZhiIndex = LunarUtil.GetJiaZiIndex(dongZhi.Lunar.DayInGanZhi);
  1318. var dongZhiIndex2 = LunarUtil.GetJiaZiIndex(dongZhi2.Lunar.DayInGanZhi);
  1319. var xiaZhiIndex = LunarUtil.GetJiaZiIndex(xiaZhi.Lunar.DayInGanZhi);
  1320. var solarShunBai = dongZhiIndex > 29 ? dongZhi.Next(60 - dongZhiIndex) : dongZhi.Next(-dongZhiIndex);
  1321. var solarShunBaiYmd = solarShunBai.Ymd;
  1322. var solarShunBai2 = dongZhiIndex2 > 29 ? dongZhi2.Next(60 - dongZhiIndex2) : dongZhi2.Next(-dongZhiIndex2);
  1323. var solarShunBaiYmd2 = solarShunBai2.Ymd;
  1324. var solarNiZi = xiaZhiIndex > 29 ? xiaZhi.Next(60 - xiaZhiIndex) : xiaZhi.Next(-xiaZhiIndex);
  1325. var solarNiZiYmd = solarNiZi.Ymd;
  1326. var offset = 0;
  1327. if (string.Compare(solarYmd, solarShunBaiYmd, StringComparison.Ordinal) >= 0 && string.Compare(solarYmd, solarNiZiYmd, StringComparison.Ordinal) < 0)
  1328. {
  1329. offset = Solar.Subtract(solarShunBai) % 9;
  1330. }
  1331. else if (string.Compare(solarYmd, solarNiZiYmd, StringComparison.Ordinal) >= 0 && string.Compare(solarYmd, solarShunBaiYmd2, StringComparison.Ordinal) < 0)
  1332. {
  1333. offset = 8 - (Solar.Subtract(solarNiZi) % 9);
  1334. }
  1335. else if (string.Compare(solarYmd, solarShunBaiYmd2, StringComparison.Ordinal) >= 0)
  1336. {
  1337. offset = Solar.Subtract(solarShunBai2) % 9;
  1338. }
  1339. else if (string.Compare(solarYmd, solarShunBaiYmd, StringComparison.Ordinal) < 0)
  1340. {
  1341. offset = (8 + solarShunBai.Subtract(Solar)) % 9;
  1342. }
  1343. return NineStar.FromIndex(offset);
  1344. }
  1345. }
  1346. /// <summary>
  1347. /// 值时九星(时家紫白星歌诀:三元时白最为佳,冬至阳生顺莫差,孟日七宫仲一白,季日四绿发萌芽,每把时辰起甲子,本时星耀照光华,时星移入中宫去,顺飞八方逐细查。夏至阴生逆回首,孟归三碧季加六,仲在九宫时起甲,依然掌中逆轮跨。)
  1348. /// </summary>
  1349. public NineStar TimeNineStar
  1350. {
  1351. get
  1352. {
  1353. // 顺逆
  1354. var solarYmd = Solar.Ymd;
  1355. var asc = false;
  1356. if (string.Compare(solarYmd, JieQiTable["冬至"].Ymd, StringComparison.Ordinal) >= 0 && string.Compare(solarYmd, JieQiTable["夏至"].Ymd, StringComparison.Ordinal) < 0)
  1357. {
  1358. asc = true;
  1359. }
  1360. else if (string.Compare(solarYmd, JieQiTable["DONG_ZHI"].Ymd, StringComparison.Ordinal) >= 0)
  1361. {
  1362. asc = true;
  1363. }
  1364. var start = asc ? 6 : 2;
  1365. var dayZhi = DayZhi;
  1366. if ("子午卯酉".Contains(dayZhi))
  1367. {
  1368. start = asc ? 0 : 8;
  1369. }
  1370. else if ("辰戌丑未".Contains(dayZhi))
  1371. {
  1372. start = asc ? 3 : 5;
  1373. }
  1374. var index = asc ? start + TimeZhiIndex : start + 9 - TimeZhiIndex;
  1375. return new NineStar(index % 9);
  1376. }
  1377. }
  1378. /// <summary>
  1379. /// 获取下一节(顺推的第一个节)
  1380. /// </summary>
  1381. /// <param name="wholeDay">是否按天计</param>
  1382. /// <returns>节气</returns>
  1383. public JieQi GetNextJie(bool wholeDay = false)
  1384. {
  1385. var l = JIE_QI_IN_USE.Length / 2;
  1386. var conditions = new string[l];
  1387. for (var i = 0; i < l; i++)
  1388. {
  1389. conditions[i] = JIE_QI_IN_USE[i * 2];
  1390. }
  1391. return GetNearJieQi(true, conditions, wholeDay);
  1392. }
  1393. /// <summary>
  1394. /// 获取上一节(逆推的第一个节)
  1395. /// </summary>
  1396. /// <param name="wholeDay">是否按天计</param>
  1397. /// <returns>节气</returns>
  1398. public JieQi GetPrevJie(bool wholeDay = false)
  1399. {
  1400. var l = JIE_QI_IN_USE.Length / 2;
  1401. var conditions = new string[l];
  1402. for (var i = 0; i < l; i++)
  1403. {
  1404. conditions[i] = JIE_QI_IN_USE[i * 2];
  1405. }
  1406. return GetNearJieQi(false, conditions, wholeDay);
  1407. }
  1408. /// <summary>
  1409. /// 获取下一气令(顺推的第一个气令)
  1410. /// </summary>
  1411. /// <param name="wholeDay">是否按天计</param>
  1412. /// <returns>节气</returns>
  1413. public JieQi GetNextQi(bool wholeDay = false)
  1414. {
  1415. var l = JIE_QI_IN_USE.Length / 2;
  1416. var conditions = new string[l];
  1417. for (var i = 0; i < l; i++)
  1418. {
  1419. conditions[i] = JIE_QI_IN_USE[i * 2 + 1];
  1420. }
  1421. return GetNearJieQi(true, conditions, wholeDay);
  1422. }
  1423. /// <summary>
  1424. /// 获取上一气令(逆推的第一个气令)
  1425. /// </summary>
  1426. /// <param name="wholeDay">是否按天计</param>
  1427. /// <returns>节气</returns>
  1428. public JieQi GetPrevQi(bool wholeDay = false)
  1429. {
  1430. var l = JIE_QI_IN_USE.Length / 2;
  1431. var conditions = new string[l];
  1432. for (var i = 0; i < l; i++)
  1433. {
  1434. conditions[i] = JIE_QI_IN_USE[i * 2 + 1];
  1435. }
  1436. return GetNearJieQi(false, conditions, wholeDay);
  1437. }
  1438. /// <summary>
  1439. /// 获取下一节气(顺推的第一个节气)
  1440. /// </summary>
  1441. /// <param name="wholeDay">是否按天计</param>
  1442. /// <returns>节气</returns>
  1443. public JieQi GetNextJieQi(bool wholeDay = false)
  1444. {
  1445. return GetNearJieQi(true, null, wholeDay);
  1446. }
  1447. /// <summary>
  1448. /// 获取上一节气(逆推的第一个节气)
  1449. /// </summary>
  1450. /// <param name="wholeDay">是否按天计</param>
  1451. /// <returns>节气</returns>
  1452. public JieQi GetPrevJieQi(bool wholeDay = false)
  1453. {
  1454. return GetNearJieQi(false, null, wholeDay);
  1455. }
  1456. /// <summary>
  1457. /// 获取最近的节气,如果未找到匹配的,返回null
  1458. /// </summary>
  1459. /// <param name="forward">是否顺推,true为顺推,false为逆推</param>
  1460. /// <param name="conditions">过滤条件,如果设置过滤条件,仅返回匹配该名称的</param>
  1461. /// <param name="wholeDay">是否按天计</param>
  1462. /// <returns>节气</returns>
  1463. private JieQi GetNearJieQi(bool forward, string[] conditions, bool wholeDay)
  1464. {
  1465. string name = null;
  1466. Solar near = null;
  1467. var filters = new List<string>();
  1468. if (null != conditions)
  1469. {
  1470. foreach (var cond in conditions)
  1471. {
  1472. if (!filters.Contains(cond))
  1473. {
  1474. filters.Add(cond);
  1475. }
  1476. }
  1477. }
  1478. var filter = filters.Count > 0;
  1479. var today = wholeDay ? Solar.Ymd : Solar.YmdHms;
  1480. foreach (var entry in JieQiTable)
  1481. {
  1482. var jq = ConvertJieQi(entry.Key);
  1483. if (filter)
  1484. {
  1485. if (!filters.Contains(jq))
  1486. {
  1487. continue;
  1488. }
  1489. }
  1490. var current = entry.Value;
  1491. var day = wholeDay ? current.Ymd : current.YmdHms;
  1492. if (forward)
  1493. {
  1494. if (string.Compare(day, today, StringComparison.Ordinal) <= 0)
  1495. {
  1496. continue;
  1497. }
  1498. if (null == near)
  1499. {
  1500. name = jq;
  1501. near = current;
  1502. }
  1503. else
  1504. {
  1505. var nearDay = wholeDay ? near.Ymd : near.YmdHms;
  1506. if (string.Compare(day, nearDay, StringComparison.Ordinal) < 0)
  1507. {
  1508. name = jq;
  1509. near = current;
  1510. }
  1511. }
  1512. }
  1513. else
  1514. {
  1515. if (string.Compare(day, today, StringComparison.Ordinal) > 0)
  1516. {
  1517. continue;
  1518. }
  1519. if (null == near)
  1520. {
  1521. name = jq;
  1522. near = current;
  1523. }
  1524. else
  1525. {
  1526. var nearDay = wholeDay ? near.Ymd : near.YmdHms;
  1527. if (string.Compare(day, nearDay, StringComparison.Ordinal) > 0)
  1528. {
  1529. name = jq;
  1530. near = current;
  1531. }
  1532. }
  1533. }
  1534. }
  1535. return null == near ? null : new JieQi(name, near);
  1536. }
  1537. /// <summary>
  1538. /// 转节气名
  1539. /// </summary>
  1540. /// <param name="name">节气名</param>
  1541. /// <returns>正式的节气名</returns>
  1542. protected string ConvertJieQi(string name)
  1543. {
  1544. var jq = name;
  1545. switch (jq)
  1546. {
  1547. case "DONG_ZHI":
  1548. jq = "冬至";
  1549. break;
  1550. case "DA_HAN":
  1551. jq = "大寒";
  1552. break;
  1553. case "XIAO_HAN":
  1554. jq = "小寒";
  1555. break;
  1556. case "LI_CHUN":
  1557. jq = "立春";
  1558. break;
  1559. case "DA_XUE":
  1560. jq = "大雪";
  1561. break;
  1562. case "YU_SHUI":
  1563. jq = "雨水";
  1564. break;
  1565. case "JING_ZHE":
  1566. jq = "驚蟄";
  1567. break;
  1568. }
  1569. return jq;
  1570. }
  1571. /// <summary>
  1572. /// 节气名称,如果无节气,返回空字符串
  1573. /// </summary>
  1574. public string JieQi
  1575. {
  1576. get
  1577. {
  1578. foreach (var entry in JieQiTable)
  1579. {
  1580. var d = entry.Value;
  1581. if (d.Year == Solar.Year && d.Month == Solar.Month && d.Day == Solar.Day)
  1582. {
  1583. return ConvertJieQi(entry.Key);
  1584. }
  1585. }
  1586. return "";
  1587. }
  1588. }
  1589. /// <summary>
  1590. /// 当天节气对象,如果无节气,返回null
  1591. /// </summary>
  1592. public JieQi CurrentJieQi => (from jq in JieQiTable let d = jq.Value where d.Year == Solar.Year && d.Month == Solar.Month && d.Day == Solar.Day select new JieQi(ConvertJieQi(jq.Key), d)).FirstOrDefault();
  1593. /// <summary>
  1594. /// 当天节令对象,如果无节令,返回null
  1595. /// </summary>
  1596. public JieQi CurrentJie
  1597. {
  1598. get
  1599. {
  1600. for (int i = 0, j = JIE_QI_IN_USE.Length; i < j; i += 2)
  1601. {
  1602. var key = JIE_QI_IN_USE[i];
  1603. var d = JieQiTable[key];
  1604. if (d.Year == Solar.Year && d.Month == Solar.Month && d.Day == Solar.Day)
  1605. {
  1606. return new JieQi(ConvertJieQi(key), d);
  1607. }
  1608. }
  1609. return null;
  1610. }
  1611. }
  1612. /// <summary>
  1613. /// 当天气令对象,如果无气令,返回null
  1614. /// </summary>
  1615. public JieQi CurrentQi
  1616. {
  1617. get
  1618. {
  1619. for (int i = 1, j = JIE_QI_IN_USE.Length; i < j; i += 2)
  1620. {
  1621. var key = JIE_QI_IN_USE[i];
  1622. var d = JieQiTable[key];
  1623. if (d.Year == Solar.Year && d.Month == Solar.Month && d.Day == Solar.Day)
  1624. {
  1625. return new JieQi(ConvertJieQi(key), d);
  1626. }
  1627. }
  1628. return null;
  1629. }
  1630. }
  1631. /// <summary>
  1632. /// 完整字符串输出
  1633. /// </summary>
  1634. public string FullString
  1635. {
  1636. get
  1637. {
  1638. StringBuilder s = new StringBuilder();
  1639. s.Append(ToString());
  1640. s.Append(' ');
  1641. s.Append(YearInGanZhi);
  1642. s.Append('(');
  1643. s.Append(YearShengXiao);
  1644. s.Append(")年 ");
  1645. s.Append(MonthInGanZhi);
  1646. s.Append('(');
  1647. s.Append(MonthShengXiao);
  1648. s.Append(")月 ");
  1649. s.Append(DayInGanZhi);
  1650. s.Append('(');
  1651. s.Append(DayShengXiao);
  1652. s.Append(")日 ");
  1653. s.Append(TimeZhi);
  1654. s.Append('(');
  1655. s.Append(TimeShengXiao);
  1656. s.Append(")时 纳音[");
  1657. s.Append(YearNaYin);
  1658. s.Append(' ');
  1659. s.Append(MonthNaYin);
  1660. s.Append(' ');
  1661. s.Append(DayNaYin);
  1662. s.Append(' ');
  1663. s.Append(TimeNaYin);
  1664. s.Append("] 星期");
  1665. s.Append(WeekInChinese);
  1666. foreach (var f in Festivals)
  1667. {
  1668. s.Append(" (");
  1669. s.Append(f);
  1670. s.Append(')');
  1671. }
  1672. foreach (var f in OtherFestivals)
  1673. {
  1674. s.Append(" (");
  1675. s.Append(f);
  1676. s.Append(')');
  1677. }
  1678. var jq = JieQi;
  1679. if (jq.Length > 0)
  1680. {
  1681. s.Append(" [");
  1682. s.Append(jq);
  1683. s.Append(']');
  1684. }
  1685. s.Append(' ');
  1686. s.Append(Gong);
  1687. s.Append('方');
  1688. s.Append(Shou);
  1689. s.Append(" 星宿[");
  1690. s.Append(Xiu);
  1691. s.Append(Zheng);
  1692. s.Append(Animal);
  1693. s.Append("](");
  1694. s.Append(XiuLuck);
  1695. s.Append(") 彭祖百忌[");
  1696. s.Append(PengZuGan);
  1697. s.Append(' ');
  1698. s.Append(PengZuZhi);
  1699. s.Append("] 喜神方位[");
  1700. s.Append(DayPositionXi);
  1701. s.Append("](");
  1702. s.Append(DayPositionXiDesc);
  1703. s.Append(") 阳贵神方位[");
  1704. s.Append(DayPositionYangGui);
  1705. s.Append("](");
  1706. s.Append(DayPositionYangGuiDesc);
  1707. s.Append(") 阴贵神方位[");
  1708. s.Append(DayPositionYinGui);
  1709. s.Append("](");
  1710. s.Append(DayPositionYinGuiDesc);
  1711. s.Append(") 福神方位[");
  1712. s.Append(DayPositionFu);
  1713. s.Append("](");
  1714. s.Append(DayPositionFuDesc);
  1715. s.Append(") 财神方位[");
  1716. s.Append(DayPositionCai);
  1717. s.Append("](");
  1718. s.Append(DayPositionCaiDesc);
  1719. s.Append(") 冲[");
  1720. s.Append(DayChongDesc);
  1721. s.Append("] 煞[");
  1722. s.Append(DaySha);
  1723. s.Append(']');
  1724. return s.ToString();
  1725. }
  1726. }
  1727. /// <inheritdoc />
  1728. public override string ToString()
  1729. {
  1730. return $"{YearInChinese}年{MonthInChinese}月{DayInChinese}";
  1731. }
  1732. /// <summary>
  1733. /// 获取往后推几天的农历日期,如果要往前推,则天数用负数
  1734. /// </summary>
  1735. /// <param name="days">天数</param>
  1736. /// <returns>农历日期</returns>
  1737. public Lunar Next(int days)
  1738. {
  1739. return Solar.Next(days).Lunar;
  1740. }
  1741. /// <summary>
  1742. /// 年所在旬(以正月初一作为新年的开始)
  1743. /// </summary>
  1744. public string YearXun => LunarUtil.GetXun(YearInGanZhi);
  1745. /// <summary>
  1746. /// 年所在旬(以立春当天作为新年的开始)
  1747. /// </summary>
  1748. public string YearXunByLiChun => LunarUtil.GetXun(YearInGanZhiByLiChun);
  1749. /// <summary>
  1750. /// 年所在旬(以立春交接时刻作为新年的开始)
  1751. /// </summary>
  1752. public string YearXunExact => LunarUtil.GetXun(YearInGanZhiExact);
  1753. /// <summary>
  1754. /// 值年空亡(旬空)(以正月初一作为新年的开始)
  1755. /// </summary>
  1756. public string YearXunKong => LunarUtil.GetXunKong(YearInGanZhi);
  1757. /// <summary>
  1758. /// 值年空亡(旬空)(以立春当天作为新年的开始)
  1759. /// </summary>
  1760. public string YearXunKongByLiChun => LunarUtil.GetXunKong(YearInGanZhiByLiChun);
  1761. /// <summary>
  1762. /// 值年空亡(旬空)(以立春交接时刻作为新年的开始)
  1763. /// </summary>
  1764. public string YearXunKongExact => LunarUtil.GetXunKong(YearInGanZhiExact);
  1765. /// <summary>
  1766. /// 月所在旬(以节交接当天起算)
  1767. /// </summary>
  1768. public string MonthXun => LunarUtil.GetXun(MonthInGanZhi);
  1769. /// <summary>
  1770. /// 月所在旬(以节交接时刻起算)
  1771. /// </summary>
  1772. public string MonthXunExact => LunarUtil.GetXun(MonthInGanZhiExact);
  1773. /// <summary>
  1774. /// 值月空亡(旬空)(以节交接当天起算)
  1775. /// </summary>
  1776. public string MonthXunKong => LunarUtil.GetXunKong(MonthInGanZhi);
  1777. /// <summary>
  1778. /// 值月空亡(旬空)(以节交接时刻起算)
  1779. /// </summary>
  1780. public string MonthXunKongExact => LunarUtil.GetXunKong(MonthInGanZhiExact);
  1781. /// <summary>
  1782. /// 日所在旬(以节交接当天起算)
  1783. /// </summary>
  1784. public string DayXun => LunarUtil.GetXun(DayInGanZhi);
  1785. /// <summary>
  1786. /// 日所在旬(八字流派1,晚子时日柱算明天)
  1787. /// </summary>
  1788. public string DayXunExact => LunarUtil.GetXun(DayInGanZhiExact);
  1789. /// <summary>
  1790. /// 日所在旬(八字流派2,晚子时日柱算当天)
  1791. /// </summary>
  1792. public string DayXunExact2 => LunarUtil.GetXun(DayInGanZhiExact2);
  1793. /// <summary>
  1794. /// 值日空亡(旬空)
  1795. /// </summary>
  1796. public string DayXunKong => LunarUtil.GetXunKong(DayInGanZhi);
  1797. /// <summary>
  1798. /// 值日空亡(旬空)(八字流派1,晚子时日柱算明天)
  1799. /// </summary>
  1800. public string DayXunKongExact => LunarUtil.GetXunKong(DayInGanZhiExact);
  1801. /// <summary>
  1802. /// 值日空亡(旬空)(八字流派2,晚子时日柱算当天)
  1803. /// </summary>
  1804. /// <returns>空亡(旬空)</returns>
  1805. public string DayXunKongExact2 => LunarUtil.GetXunKong(DayInGanZhiExact2);
  1806. /// <summary>
  1807. /// 时辰所在旬
  1808. /// </summary>
  1809. public string TimeXun => LunarUtil.GetXun(TimeInGanZhi);
  1810. /// <summary>
  1811. /// 值时空亡(旬空)
  1812. /// </summary>
  1813. public string TimeXunKong => LunarUtil.GetXunKong(TimeInGanZhi);
  1814. /// <summary>
  1815. /// 数九,如果不是数九天,返回null
  1816. /// </summary>
  1817. public ShuJiu ShuJiu
  1818. {
  1819. get
  1820. {
  1821. var current = new Solar(Solar.Year, Solar.Month, Solar.Day);
  1822. var start = JieQiTable["DONG_ZHI"];
  1823. start = new Solar(start.Year, start.Month, start.Day);
  1824. if (current.IsBefore(start))
  1825. {
  1826. start = JieQiTable["冬至"];
  1827. start = new Solar(start.Year, start.Month, start.Day);
  1828. }
  1829. var end = new Solar(start.Year, start.Month, start.Day).Next(81);
  1830. if (current.IsBefore(start) || !current.IsBefore(end))
  1831. {
  1832. return null;
  1833. }
  1834. var days = current.Subtract(start);
  1835. return new ShuJiu($"{LunarUtil.NUMBER[days / 9 + 1]}九", days % 9 + 1);
  1836. }
  1837. }
  1838. /// <summary>
  1839. /// 三伏,如果不是伏天,返回null
  1840. /// </summary>
  1841. public Fu Fu
  1842. {
  1843. get
  1844. {
  1845. var current = new Solar(Solar.Year, Solar.Month, Solar.Day);
  1846. var xiaZhi = JieQiTable["夏至"];
  1847. var liQiu = JieQiTable["立秋"];
  1848. var start = new Solar(xiaZhi.Year, xiaZhi.Month, xiaZhi.Day);
  1849. var add = 6 - xiaZhi.Lunar.DayGanIndex;
  1850. if (add < 0)
  1851. {
  1852. add += 10;
  1853. }
  1854. add += 20;
  1855. start = start.Next(add);
  1856. if (current.IsBefore(start))
  1857. {
  1858. return null;
  1859. }
  1860. var days = current.Subtract(start);
  1861. if (days < 10)
  1862. {
  1863. return new Fu("初伏", days + 1);
  1864. }
  1865. start = start.Next(10);
  1866. days = current.Subtract(start);
  1867. if (days < 10)
  1868. {
  1869. return new Fu("中伏", days + 1);
  1870. }
  1871. start = start.Next(10);
  1872. days = current.Subtract(start);
  1873. var liQiuSolar = new Solar(liQiu.Year, liQiu.Month, liQiu.Day);
  1874. if (liQiuSolar.IsAfter(start))
  1875. {
  1876. if (days < 10)
  1877. {
  1878. return new Fu("中伏", days + 11);
  1879. }
  1880. start = start.Next(10);
  1881. days = current.Subtract(start);
  1882. }
  1883. if (days < 10)
  1884. {
  1885. return new Fu("末伏", days + 1);
  1886. }
  1887. return null;
  1888. }
  1889. }
  1890. /// <summary>
  1891. /// 六曜
  1892. /// </summary>
  1893. public string LiuYao => LunarUtil.LIU_YAO[(Math.Abs(Month) + Day - 2) % 6];
  1894. /// <summary>
  1895. /// 物候
  1896. /// </summary>
  1897. public string WuHou
  1898. {
  1899. get
  1900. {
  1901. var jieQi = GetPrevJieQi(true);
  1902. var offset = 0;
  1903. for (int i = 0, j = JIE_QI.Length; i < j; i++)
  1904. {
  1905. if (jieQi.Name.Equals(JIE_QI[i]))
  1906. {
  1907. offset = i;
  1908. break;
  1909. }
  1910. }
  1911. var index = Solar.Subtract(jieQi.Solar) / 5;
  1912. if (index > 2) {
  1913. index = 2;
  1914. }
  1915. return LunarUtil.WU_HOU[(offset * 3 + index) % LunarUtil.WU_HOU.Length];
  1916. }
  1917. }
  1918. /// <summary>
  1919. /// 候
  1920. /// </summary>
  1921. public string Hou
  1922. {
  1923. get
  1924. {
  1925. var jieQi = GetPrevJieQi(true);
  1926. var max = LunarUtil.HOU.Length - 1;
  1927. var offset = Solar.Subtract(jieQi.Solar) / 5;
  1928. if (offset > max)
  1929. {
  1930. offset = max;
  1931. }
  1932. //return $"{jieQi.Name} {LunarUtil.HOU[offset]}";
  1933. return $"{LunarUtil.HOU[offset]}";
  1934. }
  1935. }
  1936. /// <summary>
  1937. /// 日禄
  1938. /// </summary>
  1939. public string DayLu
  1940. {
  1941. get
  1942. {
  1943. var gan = LunarUtil.LU[DayGan];
  1944. string zhi = null;
  1945. try
  1946. {
  1947. zhi = LunarUtil.LU[DayZhi];
  1948. }
  1949. catch
  1950. {
  1951. // ignored
  1952. }
  1953. var lu = $"{gan}命互禄";
  1954. if (null != zhi)
  1955. {
  1956. lu = $"{lu} {zhi}命进禄";
  1957. }
  1958. return lu;
  1959. }
  1960. }
  1961. /// <summary>
  1962. /// 时辰
  1963. /// </summary>
  1964. public LunarTime Time => new LunarTime(Year, Month, Day, Hour, Minute, Second);
  1965. /// <summary>
  1966. /// 当天的时辰列表
  1967. /// </summary>
  1968. public List<LunarTime> Times
  1969. {
  1970. get
  1971. {
  1972. var l = new List<LunarTime> {new LunarTime(Year, Month, Day, 0, 0, 0)};
  1973. for (var i = 0; i < 12; i++)
  1974. {
  1975. l.Add(new LunarTime(Year, Month, Day, (i + 1) * 2 - 1, 0, 0));
  1976. }
  1977. return l;
  1978. }
  1979. }
  1980. }
  1981. }