internal override LocalInstant AddMonths(LocalInstant localInstant, int months) { // Note: this method gives the same result regardless of the month numbering used // by the instance. The method works in terms of civil month numbers for most of // the time in order to simplify the logic. if (months == 0) { return(localInstant); } long tickOfDay = TimeOfDayCalculator.GetTickOfDay(localInstant); var startDate = HebrewScripturalCalculator.HebrewFromAbsolute(AbsoluteDayFromLocalInstant(localInstant)); int year = startDate.Year; int month = HebrewMonthConverter.ScripturalToCivil(year, startDate.Month); // This arithmetic works the same both backwards and forwards. year += (months / MonthsPerLeapCycle) * YearsPerLeapCycle; months = months % MonthsPerLeapCycle; if (months > 0) { // Add as many months as we need to in order to act as if we'd begun at the start // of the year, for simplicity. months += month - 1; // Add a year at a time while (months >= GetMaxMonth(year)) { months -= GetMaxMonth(year); year++; } // However many months we've got left to add tells us the final month. month = months + 1; } else { // Pretend we were given the month at the end of the years. months -= GetMaxMonth(year) - month; // Subtract a year at a time while (months + GetMaxMonth(year) <= 0) { months += GetMaxMonth(year); year--; } // However many months we've got left to add (which will still be negative...) // tells us the final month. month = GetMaxMonth(year) + months; } // Convert back to scriptural for the last bit month = HebrewMonthConverter.CivilToScriptural(year, month); int day = Math.Min(HebrewScripturalCalculator.DaysInMonth(year, month), startDate.Day); int absoluteDay = HebrewScripturalCalculator.AbsoluteFromHebrew(year, month, day); return(LocalInstantFromAbsoluteDay(absoluteDay, tickOfDay)); }
internal override YearMonthDay GetYearMonthDay(int year, int dayOfYear) { YearMonthDay scriptural = HebrewScripturalCalculator.GetYearMonthDay(year, dayOfYear); return(monthNumbering == HebrewMonthNumbering.Scriptural ? scriptural : new YearMonthDay(year, HebrewMonthConverter.ScripturalToCivil(year, scriptural.Month), scriptural.Day)); }
private int ScripturalToCalendarMonth(int year, int month) => monthNumbering == HebrewMonthNumbering.Scriptural ? month : HebrewMonthConverter.ScripturalToCivil(year, month);
// Note to self: this is (minuendInstant - subtrahendInstant) in months. So if minuendInstant // is later than subtrahendInstant, the result should be positive. internal override int MonthsBetween(LocalInstant minuendInstant, LocalInstant subtrahendInstant) { var minuendDate = HebrewScripturalCalculator.HebrewFromAbsolute(AbsoluteDayFromLocalInstant(minuendInstant)); var subtrahendDate = HebrewScripturalCalculator.HebrewFromAbsolute(AbsoluteDayFromLocalInstant(subtrahendInstant)); // First (quite rough) guess... we could probably be more efficient than this, but it's unlikely to be very far off. double minuendMonths = (minuendDate.Year * MonthsPerLeapCycle) / (double)YearsPerLeapCycle + HebrewMonthConverter.ScripturalToCivil(minuendDate.Year, minuendDate.Month); double subtrahendMonths = (subtrahendDate.Year * MonthsPerLeapCycle) / (double)YearsPerLeapCycle + HebrewMonthConverter.ScripturalToCivil(subtrahendDate.Year, subtrahendDate.Month); int diff = (int)(minuendMonths - subtrahendMonths); if (subtrahendInstant <= minuendInstant) { // Go backwards until we've got a tight upper bound... while (AddMonths(subtrahendInstant, diff) > minuendInstant) { diff--; } // Go forwards until we've overshot while (AddMonths(subtrahendInstant, diff) <= minuendInstant) { diff++; } // Take account of the overshoot return(diff - 1); } else { // Moving backwards, so we need to end up with a result greater than or equal to // minuendInstant... // Go forwards until we've got a tight upper bound... while (AddMonths(subtrahendInstant, diff) < minuendInstant) { diff++; } // Go backwards until we've overshot while (AddMonths(subtrahendInstant, diff) >= minuendInstant) { diff--; } // Take account of the overshoot return(diff + 1); } }