예제 #1
0
        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));
        }
예제 #2
0
        /// <summary>
        /// Change the year, maintaining month and day as well as possible. This doesn't
        /// work in the same way as other calendars; see http://judaism.stackexchange.com/questions/39053
        /// for the reasoning behind the rules.
        /// </summary>
        internal override LocalInstant SetYear(LocalInstant localInstant, int year)
        {
            long         tickOfDay         = TimeOfDayCalculator.GetTickOfDay(localInstant);
            int          absoluteSourceDay = AbsoluteDayFromLocalInstant(localInstant);
            YearMonthDay ymd                   = HebrewScripturalCalculator.HebrewFromAbsolute(absoluteSourceDay);
            int          targetDay             = ymd.Day;
            int          targetScripturalMonth = ymd.Month;

            if (targetScripturalMonth == 13 && !IsLeapYear(year))
            {
                // If we were in Adar II and the target year is not a leap year, map to Adar.
                targetScripturalMonth = 12;
            }
            else if (targetScripturalMonth == 12 && IsLeapYear(year) && !IsLeapYear(ymd.Year))
            {
                // If we were in Adar (non-leap year), go to Adar II rather than Adar I in a leap year.
                targetScripturalMonth = 13;
            }
            // If we're aiming for the 30th day of Heshvan, Kislev or an Adar, it's possible that the change in year
            // has meant the day becomes invalid. In that case, roll over to the 1st of the subsequent month.
            if (targetDay == 30 && (targetScripturalMonth == 8 || targetScripturalMonth == 9 || targetScripturalMonth == 12))
            {
                if (HebrewScripturalCalculator.DaysInMonth(year, targetScripturalMonth) != 30)
                {
                    targetDay = 1;
                    targetScripturalMonth++;
                    // From Adar, roll to Nisan.
                    if (targetScripturalMonth == 13)
                    {
                        targetScripturalMonth = 1;
                    }
                }
            }
            int absoluteTargetDay = HebrewScripturalCalculator.AbsoluteFromHebrew(year, targetScripturalMonth, targetDay);

            return(LocalInstantFromAbsoluteDay(absoluteTargetDay, tickOfDay));
        }
        /// <summary>
        /// Change the year, maintaining month and day as well as possible. This doesn't
        /// work in the same way as other calendars; see https://judaism.stackexchange.com/questions/39053
        /// for the reasoning behind the rules.
        /// </summary>
        internal override YearMonthDay SetYear(YearMonthDay yearMonthDay, int year)
        {
            int currentYear           = yearMonthDay.Year;
            int currentMonth          = yearMonthDay.Month;
            int targetDay             = yearMonthDay.Day;
            int targetScripturalMonth = CalendarToScripturalMonth(currentYear, currentMonth);

            if (targetScripturalMonth == 13 && !IsLeapYear(year))
            {
                // If we were in Adar II and the target year is not a leap year, map to Adar.
                targetScripturalMonth = 12;
            }
            else if (targetScripturalMonth == 12 && IsLeapYear(year) && !IsLeapYear(currentYear))
            {
                // If we were in Adar (non-leap year), go to Adar II rather than Adar I in a leap year.
                targetScripturalMonth = 13;
            }
            // If we're aiming for the 30th day of Heshvan, Kislev or an Adar, it's possible that the change in year
            // has meant the day becomes invalid. In that case, roll over to the 1st of the subsequent month.
            if (targetDay == 30 && (targetScripturalMonth == 8 || targetScripturalMonth == 9 || targetScripturalMonth == 12))
            {
                if (HebrewScripturalCalculator.DaysInMonth(year, targetScripturalMonth) != 30)
                {
                    targetDay = 1;
                    targetScripturalMonth++;
                    // From Adar, roll to Nisan.
                    if (targetScripturalMonth == 13)
                    {
                        targetScripturalMonth = 1;
                    }
                }
            }
            int targetCalendarMonth = ScripturalToCalendarMonth(year, targetScripturalMonth);

            return(new YearMonthDay(year, targetCalendarMonth, targetDay));
        }
 internal override int GetDaysInMonth(int year, int month) =>
 HebrewScripturalCalculator.DaysInMonth(year, CalendarToScripturalMonth(year, month));
예제 #5
0
 internal override int GetDaysInMonth(int year, int month)
 {
     return(HebrewScripturalCalculator.DaysInMonth(year, calendarToScriptural(year, month)));
 }