/// <summary> /// 计算指定节气的时间 /// </summary> /// <param name="year">公历年份</param> /// <param name="st">节气</param> /// <returns>返回指定节气的儒略日时间</returns> public static double CalcSolarTerms(int year, SolarTerm24Types st) { SolarTerm24 jq = new SolarTerm24(st); int jq1 = jq.Degree; // 节气月份 int SolarTermsMonth = (int)(Math.Ceiling(((jq1 + 90.0) / 30.0))); SolarTermsMonth = SolarTermsMonth > 12 ? SolarTermsMonth - 12 : SolarTermsMonth; // 节令的发生日期基本都在每月 3 - 9 号间 update by Ukey 2017-01-01 从4-9提升到3-9,有年的立春在3号 int LowerLimitSolarTermsDay = jq1 % 15 == 0 && jq1 % 30 != 0 ? 3 : 16; // 节气的发生日期基本都在每月 16 - 24 号间 int UpperLimitSolarTermsDay = jq1 % 15 == 0 && jq1 % 30 != 0 ? 9 : 24; // 采用二分法逼近计算 double dbLowerLinit = Julday(year, SolarTermsMonth, LowerLimitSolarTermsDay, 0, 0, 0); double dbUpperLinit = Julday(year, SolarTermsMonth, UpperLimitSolarTermsDay, 23, 59, 59); // 二分法分界点日期 double dbDichotomyDivisionDayJD = 0; // 太阳黄经角度 double dbLongitude = 0; // 对比二分法精度是否达到要求 do { dbDichotomyDivisionDayJD = ((dbUpperLinit - dbLowerLinit) / 2.0) + dbLowerLinit; // 计算太阳黄经 dbLongitude = GetSunLongitude(dbDichotomyDivisionDayJD); // 一次校正经度 dbLongitude += CorrectionCalcSunLongitude(dbLongitude, GetSunLatitude(dbDichotomyDivisionDayJD), dbDichotomyDivisionDayJD); // 二次校正天体章动 dbLongitude += GetNutationJamScalar(dbDichotomyDivisionDayJD) / 3600.0; // 三次校正太阳半径向量 dbLongitude -= (20.4898 / GetSunRadiusVector(dbDichotomyDivisionDayJD)) / 3600.0; // 由于春分这天黄经为 0 度,比较特殊,因此专门判断(如不加以特殊对待则会导致计算范围覆盖整个 360 度角) dbLongitude = ((st == SolarTerm24Types.ChunFen) && (dbLongitude > 345.0)) ? -dbLongitude : dbLongitude; // 调整二分法上下限 if (dbLongitude > (double)(jq1)) { dbUpperLinit = dbDichotomyDivisionDayJD; } else { dbLowerLinit = dbDichotomyDivisionDayJD; } } while (Math.Abs(dbLongitude - (double)(jq1)) >= 0.00001); return(dbDichotomyDivisionDayJD); }
/// <summary> /// 获取本实例日期值是否正值某一节气日期。 /// </summary> /// <returns>如果正好在某一节气上,返回节气信息,否则返回null</returns> public string GetSolarTermInfo(DateTime Value) { try { string returnValue = ""; int y = Value.Year; string ds = Value.ToString("yyyy-MM-dd"); SolarTerm24 t = new SolarTerm24(SolarTerm24Types.XiaoHan); //公历1月份第一个节气为小寒 int n = Value.Month - 1; SolarTerm24 t1 = t.Inc(2 * n); //每个公历月上有2个节气 ,该月第一个节气 DateTime d1 = CalendarUtil.GetSolarTermDateTime(y, t1.ID); if (ds == d1.ToString("yyyy-MM-dd")) { solarTermInfo = new HFDateSolarTermInfo(t1.ID, d1); } SolarTerm24 t2 = new SolarTerm24(); SolarTerm24 t3 = new SolarTerm24(); //上个月的第二个节气 DateTime d3; //上个月第二个节气的时间 t3 = t1.Prior(); if (Value.Month == 1) // edit by Ukey 2017-01-03 每年一月份计算上一个月第二个节气出错 { d3 = CalendarUtil.GetSolarTermDateTime(y - 1, t3.ID); } else { d3 = CalendarUtil.GetSolarTermDateTime(y, t3.ID); } DateTime d2; //本月第二个节气的日期 t2 = t1.Next(); //本月第二个节气 d2 = CalendarUtil.GetSolarTermDateTime(y, t2.ID); if (ds == d2.ToString("yyyy-MM-dd")) { solarTermInfo = new HFDateSolarTermInfo(t2.ID, d2); } SolarTerm24 t4 = new SolarTerm24(); //下个月的第一个节气 DateTime d4; //下个月第一个节气的日期 t4 = t2.Next(); //下个月的第一个节气 d4 = CalendarUtil.GetSolarTermDateTime(y, t4.ID); if (ds == d2.ToString("yyyy-MM-dd")) { solarTermInfo = new HFDateSolarTermInfo(t2.ID, d2); } if (solarTermInfo != null) { returnValue = solarTermInfo.Name; } else { int daydiff = 0; if (Value < d1) //d1 该月的第一个节气时间 d2 该月的第二个节气时间 d3 上个月的第二个节气的时间 前七后八的显示方式 { daydiff = (Value - d3).Days + 1; if (daydiff <= 7) { returnValue = t3.Name + "后" + daydiff.ToString() + "天"; } else { daydiff = (d1 - Value).Days; returnValue = t1.Name + "前" + daydiff.ToString() + "天"; } } else if (Value > d1 && Value < d2) { // returnValue = t1.Name + "第" + (Value.Date - d1.Date).Days.ToString() + "天"; daydiff = (Value - d1).Days + 1; if (daydiff <= 7) { returnValue = t1.Name + "后" + daydiff.ToString() + "天"; } else { daydiff = (d2 - Value).Days; returnValue = t2.Name + "前" + daydiff.ToString() + "天"; } } else if (Value > d2) { // returnValue = t2.Name + "第" + (Value.Date - d2.Date).Days.ToString() + "天"; daydiff = (Value - d2).Days + 1; if (daydiff <= 7) { returnValue = t2.Name + "后" + daydiff.ToString() + "天"; } else { daydiff = (d4 - Value).Days; returnValue = t4.Name + "前" + daydiff.ToString() + "天"; } } } solarTermInfo = null; return(returnValue); } catch (Exception ex) { return("小寒"); } }