// ------------------------------------------------------------------ // Fields to time // ------------------------------------------------------------------ /// <summary> /// Return the Chinese new year of the given Gregorian year. /// </summary> /// /// <param name="gyear">a Gregorian year</param> /// <returns>days after January 1, 1970 0:00 Asia/Shanghai of the Chinese new /// year of the given year (this will be a new moon)</returns> private int NewYear(int gyear) { long cacheValue = newYearCache.Get(gyear); if (cacheValue == IBM.ICU.Impl.CalendarCache.EMPTY) { int solsticeBefore = WinterSolstice(gyear - 1); int solsticeAfter = WinterSolstice(gyear); int newMoon1 = NewMoonNear(solsticeBefore + 1, true); int newMoon2 = NewMoonNear(newMoon1 + SYNODIC_GAP, true); int newMoon11 = NewMoonNear(solsticeAfter + 1, false); if (SynodicMonthsBetween(newMoon1, newMoon11) == 12 && (HasNoMajorSolarTerm(newMoon1) || HasNoMajorSolarTerm(newMoon2))) { cacheValue = NewMoonNear(newMoon2 + SYNODIC_GAP, true); } else { cacheValue = newMoon2; } newYearCache.Put(gyear, cacheValue); } return((int)cacheValue); }
/// <summary> /// Finds the day # of the first day in the given Hebrew year. To do this, we /// want to calculate the time of the Tishri 1 new moon in that year. /// <p> /// The algorithm here is similar to ones described in a number of /// references, including: /// <ul> /// <li>"Calendrical Calculations", by Nachum Dershowitz & Edward Reingold, /// Cambridge University Press, 1997, pages 85-91. /// <li>Hebrew Calendar Science and Myths, <a /// href="http://www.geocities.com/Athens/1584/"> /// http://www.geocities.com/Athens/1584/</a> /// <li>The Calendar FAQ, <a href="http://www.faqs.org/faqs/calendars/faq/"> /// http://www.faqs.org/faqs/calendars/faq/</a> /// </ul> /// </summary> /// private static long StartOfYear(int year) { long day = cache.Get(year); if (day == IBM.ICU.Impl.CalendarCache.EMPTY) { int months = (235 * year - 234) / 19; // # of months before year long frac = months * MONTH_FRACT + BAHARAD; // Fractional part of // day # day = months * 29 + (frac / DAY_PARTS); // Whole # part of // calculation frac = frac % DAY_PARTS; // Time of day int wd = (int)(day % 7); // Day of week (0 == Monday) if (wd == 2 || wd == 4 || wd == 6) { // If the 1st is on Sun, Wed, or Fri, postpone to the next day day += 1; wd = (int)(day % 7); } if (wd == 1 && frac > 15 * HOUR_PARTS + 204 && !IsLeapYear(year)) { // If the new moon falls after 3:11:20am (15h204p from the // previous noon) // on a Tuesday and it is not a leap year, postpone by 2 days. // This prevents 356-day years. day += 2; } else if (wd == 0 && frac > 21 * HOUR_PARTS + 589 && IsLeapYear(year - 1)) { // If the new moon falls after 9:32:43 1/3am (21h589p from // yesterday noon) // on a Monday and *last* year was a leap year, postpone by 1 // day. // Prevents 382-day years. day += 1; } cache.Put(year, day); } return(day); }
// ------------------------------------------------------------------ // Astronomical computations // ------------------------------------------------------------------ /// <summary> /// Return the major solar term on or after December 15 of the given /// Gregorian year, that is, the winter solstice of the given year. /// Computations are relative to Asia/Shanghai time zone. /// </summary> /// /// <param name="gyear">a Gregorian year</param> /// <returns>days after January 1, 1970 0:00 Asia/Shanghai of the winter /// solstice of the given year</returns> private int WinterSolstice(int gyear) { long cacheValue = winterSolsticeCache.Get(gyear); if (cacheValue == IBM.ICU.Impl.CalendarCache.EMPTY) { // In books December 15 is used, but it fails for some years // using our algorithms, e.g.: 1298 1391 1492 1553 1560. That // is, winterSolstice(1298) starts search at Dec 14 08:00:00 // PST 1298 with a final result of Dec 14 10:31:59 PST 1299. long ms = DaysToMillis(ComputeGregorianMonthStart(gyear, IBM.ICU.Util.Calendar.DECEMBER) + 1 - IBM.ICU.Util.Calendar.EPOCH_JULIAN_DAY); astro.SetTime(ms); // Winter solstice is 270 degrees solar longitude aka Dongzhi long solarLong = astro.GetSunTime( IBM.ICU.Impl.CalendarAstronomer.WINTER_SOLSTICE, true); cacheValue = MillisToDays(solarLong); winterSolsticeCache.Put(gyear, cacheValue); } return((int)cacheValue); }