/* Analysation of algorithm of Hồ Ngọc Đức * --------------------------------------- * double off = LocalToJD(31, 12, Y) - 2415021.076998695; * ^ returns Julian Date of 31st December #Year, 00:00:00 UTC+7 * i.e. 30th December #Year, 17:00:00 UTC * int k = INT(off / 29.530588853); * double jd = NewMoon(k); * ^ returns the new moon date *time* in Julian Dater, *UTC* * int[] ret = LocalFromJD(jd); * ^ converts (jd + timezone/24) back to Calendar Date, * disregrading the time (i.e. the begining of day in local time zone * [00:00:00 local] that contains the new moon.) * * // sun longitude at local midnight * double sunLong = SunLongitude(LocalToJD(ret[0], ret[1], ret[2])); * if (sunLong > 3 * PI / 2) * { * jd = NewMoon(k - 1); * } * return LocalFromJD(jd); * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * e.g.: * NewMoon(1236) = 2451520.4393767994 * = 7/12/1999 10:32:42 UTC * = 8/12/1999 17:32:42 UTC+7, thus, * * [ Note: UniversalFromJD(2451520.4393767994) = (7, 12, 1999) ] * LocalFromJD(2451520.4393767994) = * UniversalFromJD(JD + LOCAL_TIMEZONE/24.0) = (8, 12, 1999) * * LocalToJD(8, 12, 1999) = * UniversalToJD(D, M, Y) - LOCAL_TIMEZONE/24.0 = 8/12/1999 00:00:00 - 7 * ^ ^ = 7/12/1999 17:00:00 UTC <---+ * | +---[ Shift back to local midnight ] | * +---[ Julius Date of D/M/Y 00:00:00 UTC (midnight), 8/12/1999 00:00:00] | * [ This value is used to determine the sun longitude ]---+ */ /// <summary> /// Returns the local date time of the new moon just before /// the winter solstice in the given lunar year. /// </summary> /// <param name="lunarYear"></param> /// <param name="timeZone"></param> /// <returns></returns> public static DateTime GetNewMoon11(int lunarYear, double timeZone) { // number of days from J1900 to local midnight of 31st December #Year // (lunarYear, 12, 31): local // (lunarYear, 12, 31, timeZone): universal var offset = JulianDateConverter.UniversalDateTimeToJulianDate(lunarYear, 12, 31, timeZone) - Constants.J1900; var k = (int)(offset / Constants.SynodicMonth); // local date & *time* of new moon var newMoonLocalDateTime = JulianDateConverter.JulianDateToUniversalDateTime(GetNewMoon(k)).AddHours(timeZone); // beginning of that day (i.e. midnight, i.e. strip off the time) var newMoonMidnightLocal = newMoonLocalDateTime.Date; // Julian Date at the beginning of that day var julianDate = newMoonMidnightLocal.AddHours(-timeZone).UniversalDateTimeToJulianDate(); var sunLongitude = Sun.GetSunLongitudeAtJulianDate(julianDate); // Check the winter solstice is after the beginning of that day: // If the winter soltice is *before* the beginning of that day, // the previous new moon is the new moon just before winter solstice, // else the current new moon is the new moon just before winter solstice. if (sunLongitude > (3 * Math.PI / 2)) { newMoonLocalDateTime = JulianDateConverter.JulianDateToUniversalDateTime(GetNewMoon(k - 1)).AddHours(timeZone); } return(newMoonLocalDateTime); }
public static int GetSolarTermIndex(DateTime dateTime) { var julianDate = JulianDateConverter.UniversalDateTimeToJulianDate(dateTime); return((int)(GetSunLongitudeAtJulianDate(julianDate) / Math.PI * 12)); }