internal override LocalInstant SetYear(LocalInstant localInstant, int year)
        {
            int  thisYear  = GetYear(localInstant);
            int  dayOfYear = GetDayOfYear(localInstant, thisYear);
            long tickOfDay = TimeOfDayCalculator.GetTickOfDay(localInstant);

            if (dayOfYear > (31 + 28))
            {
                // after Feb 28
                if (IsLeapYear(thisYear))
                {
                    // Current date is Feb 29 or later.
                    if (!IsLeapYear(year))
                    {
                        // Moving to a non-leap year, Feb 29 does not exist.
                        dayOfYear--;
                    }
                }
                else
                {
                    // Current date is Mar 01 or later.
                    if (IsLeapYear(year))
                    {
                        // Moving to a leap year, account for Feb 29.
                        dayOfYear++;
                    }
                }
            }

            long ticks = GetYearMonthDayTicks(year, 1, dayOfYear);

            return(new LocalInstant(ticks + tickOfDay));
        }
Exemple #2
0
        override internal LocalInstant AddMonths(LocalInstant localInstant, int months)
        {
            if (months == 0)
            {
                return(localInstant);
            }
            // Save the time part first
            long timePart = TimeOfDayCalculator.GetTickOfDay(localInstant);
            // Get the year and month
            int thisYear  = GetYear(localInstant);
            int thisMonth = GetMonthOfYear(localInstant, thisYear);

            // Do not refactor without careful consideration.
            // Order of calculation is important.

            int yearToUse;
            // Initially, monthToUse is zero-based
            int monthToUse = thisMonth - 1 + months;

            if (monthToUse >= 0)
            {
                yearToUse  = thisYear + (monthToUse / monthsInYear);
                monthToUse = (monthToUse % monthsInYear) + 1;
            }
            else
            {
                yearToUse  = thisYear + (monthToUse / monthsInYear) - 1;
                monthToUse = Math.Abs(monthToUse);
                int remMonthToUse = monthToUse % monthsInYear;
                // Take care of the boundary condition
                if (remMonthToUse == 0)
                {
                    remMonthToUse = monthsInYear;
                }
                monthToUse = monthsInYear - remMonthToUse + 1;
                // Take care of the boundary condition
                if (monthToUse == 1)
                {
                    yearToUse++;
                }
            }
            // End of do not refactor.

            // Quietly force DOM to nearest sane value.
            int dayToUse = GetDayOfMonth(localInstant, thisYear, thisMonth);
            int maxDay   = GetDaysInMonth(yearToUse, monthToUse);

            dayToUse = Math.Min(dayToUse, maxDay);
            // Get proper date part, and return result
            long datePart = GetYearMonthDayTicks(yearToUse, monthToUse, dayToUse);

            return(new LocalInstant(datePart + timePart));
        }
Exemple #3
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));
        }
        internal override LocalInstant SetYear(LocalInstant localInstant, int year)
        {
            // Optimized implementation of SetYear, due to fixed months.
            int thisYear  = GetYear(localInstant);
            int dayOfYear = GetDayOfYear(localInstant, thisYear);

            // Truncate final day of leap year.
            if (dayOfYear == DaysPerLeapYear && !IsLeapYear(year))
            {
                dayOfYear--;
            }
            long tickOfDay = TimeOfDayCalculator.GetTickOfDay(localInstant);

            return(new LocalInstant(GetYearTicks(year) + ((dayOfYear - 1) * NodaConstants.TicksPerStandardDay) + tickOfDay));
        }
        internal override LocalInstant SetYear(LocalInstant localInstant, int year)
        {
            // Optimized implementation of set, due to fixed months
            int  thisYear  = GetYear(localInstant);
            int  dayOfYear = GetDayOfYear(localInstant, thisYear);
            long tickOfDay = TimeOfDayCalculator.GetTickOfDay(localInstant);

            if (dayOfYear > 365)
            {
                // Current year is leap, and day is leap.
                if (!IsLeapYear(year))
                {
                    // Moving to a non-leap year, leap day doesn't exist.
                    dayOfYear--;
                }
            }

            long ticks = GetYearTicks(year) + (dayOfYear - 1) * NodaConstants.TicksPerStandardDay + tickOfDay;

            return(new LocalInstant(ticks));
        }
Exemple #6
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));
        }