/// <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 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); }
/// <summary> /// Implements a simple year-setting policy, truncating the day /// if necessary. /// </summary> internal override YearMonthDay SetYear(YearMonthDay yearMonthDay, [Trusted] int year) { // TODO(2.0): All subclasses have the same logic of "detect leap years, // and otherwise we're fine". Put it here instead. int currentMonth = yearMonthDay.Month; int currentDay = yearMonthDay.Day; int newDay = GetDaysInMonth(year, currentMonth); return new YearMonthDay(year, currentMonth, Math.Min(currentDay, newDay)); }
internal override YearMonthDay SetYear(YearMonthDay yearMonthDay, [Trusted] int year) { int month = yearMonthDay.Month; int day = yearMonthDay.Day; // The only value which might change day is Feb 29th. if (month == 2 && day == 29 && !IsLeapYear(year)) { day = 28; } return new YearMonthDay(year, month, day); }
internal override YearMonthDay SetYear(YearMonthDay yearMonthDay, int year) { int month = yearMonthDay.Month; int day = yearMonthDay.Day; // The only value which might change day is the last day of a leap year if (month == 12 && day == 30 && !IsLeapYear(year)) { day = 29; } return new YearMonthDay(year, month, day); }
public void AllYears() { // Range of years we actually care about. We support more, but that's okay. for (int year = -9999; year <= 9999; year++) { var ymd = new YearMonthDay(year, 5, 20); Assert.AreEqual(year, ymd.Year); Assert.AreEqual(5, ymd.Month); Assert.AreEqual(20, ymd.Day); } }
public void AllMonths() { // We'll never actually need 16 months, but we support that many... for (int month = 1; month < 16; month++) { var ymd = new YearMonthDay(-123, month, 20); Assert.AreEqual(-123, ymd.Year); Assert.AreEqual(month, ymd.Month); Assert.AreEqual(20, ymd.Day); } }
public void AllDays() { // We'll never actually need 64 days, but we support that many... for (int day = 1; day < 64; day++) { var ymd = new YearMonthDay(-123, 12, day); Assert.AreEqual(-123, ymd.Year); Assert.AreEqual(12, ymd.Month); Assert.AreEqual(day, ymd.Day); } }
internal override YearMonthDay AddMonths(YearMonthDay yearMonthDay, int months) { if (months == 0) { return yearMonthDay; } // Get the year and month int thisYear = yearMonthDay.Year; int thisMonth = yearMonthDay.Month; // 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 = yearMonthDay.Day; int maxDay = GetDaysInMonth(yearToUse, monthToUse); dayToUse = Math.Min(dayToUse, maxDay); return new YearMonthDay(yearToUse, monthToUse, dayToUse); }
public void GetYearMonthDay_YearAndDayOfYear() { var calculator = new UmAlQuraYearMonthDayCalculator(); for (int year = calculator.MinYear; year <= calculator.MaxYear; year++) { int dayOfYear = 1; for (int month = 1; month <= 12; month++) { for (int day = 1; day <= calculator.GetDaysInMonth(year, month); day++) { var actual = calculator.GetYearMonthDay(year, dayOfYear); var expected = new YearMonthDay(year, month, day); Assert.AreEqual(expected, actual, "year={0}; dayOfYear={1}", year, dayOfYear); dayOfYear++; } } } }
public void GetYearMonthDay_DaysSinceEpoch() { var calculator = new UmAlQuraYearMonthDayCalculator(); int daysSinceEpoch = calculator.GetStartOfYearInDays(calculator.MinYear); for (int year = calculator.MinYear; year <= calculator.MaxYear; year++) { for (int month = 1; month <= 12; month++) { for (int day = 1; day <= calculator.GetDaysInMonth(year, month); day++) { var actual = calculator.GetYearMonthDay(daysSinceEpoch); var expected = new YearMonthDay(year, month, day); Assert.AreEqual(expected, actual, "daysSinceEpoch={0}", daysSinceEpoch); daysSinceEpoch++; } } } }
public void TestDayOfYear() { YearMonthDay nonLeapBeforeEndOfFeb = new YearMonthDay(2006, 2, 15); Assert.AreEqual(46, nonLeapBeforeEndOfFeb.DayOfYear); YearMonthDay nonLeapAfterEndOfFeb = new YearMonthDay(2006, 3, 14); Assert.AreEqual(73, nonLeapAfterEndOfFeb.DayOfYear); YearMonthDay leapBeforeEndOfFeb = new YearMonthDay(2008, 2, 15); Assert.AreEqual(46, leapBeforeEndOfFeb.DayOfYear); YearMonthDay leapAfterEndOfFeb = new YearMonthDay(2008, 3, 14); Assert.AreEqual(74, leapAfterEndOfFeb.DayOfYear); }
public void TestConstructWithInvalidDate() { YearMonthDay ymd = new YearMonthDay(2006, 2, 29); }
public override int Compare(YearMonthDay lhs, YearMonthDay rhs) { // The civil month numbering system allows a naive comparison. if (monthNumbering == HebrewMonthNumbering.Civil) { return lhs.CompareTo(rhs); } // Otherwise, try one component at a time. (We could benchmark this // against creating a new pair of YearMonthDay values in the civil month numbering, // and comparing them...) int yearComparison = lhs.Year.CompareTo(rhs.Year); if (yearComparison != 0) { return yearComparison; } int lhsCivilMonth = CalendarToCivilMonth(lhs.Year, lhs.Month); int rhsCivilMonth = CalendarToCivilMonth(rhs.Year, rhs.Month); int monthComparison = lhsCivilMonth.CompareTo(rhsCivilMonth); if (monthComparison != 0) { return monthComparison; } return lhs.Day.CompareTo(rhs.Day); }
// 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(YearMonthDay minuendDate, YearMonthDay subtrahendDate) { // First (quite rough) guess... we could probably be more efficient than this, but it's unlikely to be very far off. int minuendCivilMonth = CalendarToCivilMonth(minuendDate.Year, minuendDate.Month); int subtrahendCivilMonth = CalendarToCivilMonth(subtrahendDate.Year, subtrahendDate.Month); double minuendTotalMonths = minuendCivilMonth + (minuendDate.Year * MonthsPerLeapCycle) / (double) YearsPerLeapCycle; double subtrahendTotalMonths = subtrahendCivilMonth + (subtrahendDate.Year * MonthsPerLeapCycle) / (double) YearsPerLeapCycle; int diff = (int) (minuendTotalMonths - subtrahendTotalMonths); if (Compare(subtrahendDate, minuendDate) <= 0) { // Go backwards until we've got a tight upper bound... while (Compare(AddMonths(subtrahendDate, diff), minuendDate) > 0) { diff--; } // Go forwards until we've overshot while (Compare(AddMonths(subtrahendDate, diff), minuendDate) <= 0) { 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 (Compare(AddMonths(subtrahendDate, diff), minuendDate) < 0) { diff++; } // Go backwards until we've overshot while (Compare(AddMonths(subtrahendDate, diff), minuendDate) >= 0) { diff--; } // Take account of the overshoot return diff + 1; } }
public void TestGetHashCode() { YearMonthDay ymd1 = new YearMonthDay(2006, 3, 14); YearMonthDay ymd2 = new YearMonthDay(2006, 3, 14); YearMonthDay ymd3 = new YearMonthDay(2006, 5, 26); Assert.AreEqual(ymd1.GetHashCode(), ymd2.GetHashCode()); Assert.AreNotEqual(ymd1.GetHashCode(), ymd3.GetHashCode()); }
public void TestRoundTripDefaultConstructed() { YearMonthDay ymd = new YearMonthDay(); YearMonthDay ymd2 = new YearMonthDay(ymd.JulianDayNumber); Assert.AreEqual(ymd, ymd2); }
public void GetDaysSinceEpoch() { var calculator = new HebrewYearMonthDayCalculator(HebrewMonthNumbering.Scriptural); var unixEpoch = new YearMonthDay(5730, 10, 23); Assert.AreEqual(0, calculator.GetDaysSinceEpoch(unixEpoch)); }
public void TestJulianDayNumber() { const int astronomicalJulianDayNumber = 2454959; YearMonthDay ymd = new YearMonthDay(astronomicalJulianDayNumber); Assert.AreEqual(astronomicalJulianDayNumber, ymd.JulianDayNumber); }
public void TestCompareToObject() { YearMonthDay ymd1 = new YearMonthDay(2006, 3, 14); object ymd4 = new YearMonthDay(2004, 2, 21); Assert.IsTrue(ymd1.CompareTo(null) > 0); Assert.IsTrue(ymd1.CompareTo(ymd4) > 0); }
public void TestConstructFromDayOfYear() { int[] years = { 2000, 2001 }; Assert.IsTrue(YearMonthDay.IsLeapYear(years[0])); Assert.IsFalse(YearMonthDay.IsLeapYear(years[1])); foreach (int year in years) { int cumulativeDays = 0; for (int month = 1; month <= 12; ++month) { // Test first of the month. YearMonthDay ymd = new YearMonthDay(year, cumulativeDays + 1); Assert.AreEqual(year, ymd.Year); Assert.AreEqual(month, ymd.Month); Assert.AreEqual(1, ymd.Day); int daysInMonth = YearMonthDay.DaysInMonth(year, month); // Test last of the month. ymd = new YearMonthDay(year, cumulativeDays + daysInMonth); Assert.AreEqual(year, ymd.Year); Assert.AreEqual(month, ymd.Month); Assert.AreEqual(daysInMonth, ymd.Day); cumulativeDays += daysInMonth; } } }
public void TestConstructFromJulianDate() { DateTime dt = new DateTime(2008, 10, 23, 12, 0, 0); JulianDate jd = new JulianDate(dt); YearMonthDay ymd = new YearMonthDay(jd); Assert.AreEqual(2008, ymd.Year); Assert.AreEqual(10, ymd.Month); Assert.AreEqual(23, ymd.Day); dt = new DateTime(2008, 10, 23, 0, 0, 0); jd = new JulianDate(dt); ymd = new YearMonthDay(jd); Assert.AreEqual(2008, ymd.Year); Assert.AreEqual(10, ymd.Month); Assert.AreEqual(23, ymd.Day); dt = new DateTime(2008, 10, 23, 23, 59, 59); jd = new JulianDate(dt); ymd = new YearMonthDay(jd); Assert.AreEqual(2008, ymd.Year); Assert.AreEqual(10, ymd.Month); Assert.AreEqual(23, ymd.Day); }
public void TestToString() { YearMonthDay ymd1 = new YearMonthDay(2006, 3, 14); Assert.AreEqual(ymd1.ToString(), "2006:3:14"); }
public void TestEquality() { YearMonthDay first = new YearMonthDay(2000, 1, 1); YearMonthDay second = new YearMonthDay(2000, 1, 1); Assert.AreEqual(first, second); Assert.IsTrue(first.Equals(second)); Assert.IsTrue(second.Equals(first)); Assert.AreEqual(0, first.CompareTo(second)); Assert.AreEqual(0, second.CompareTo(first)); second = new YearMonthDay(2001, 1, 1); Assert.AreNotEqual(first, second); Assert.IsFalse(first.Equals(second)); Assert.IsFalse(second.Equals(first)); Assert.AreNotEqual(0, first.CompareTo(second)); Assert.AreNotEqual(0, second.CompareTo(first)); second = new YearMonthDay(2000, 2, 1); Assert.AreNotEqual(first, second); Assert.IsFalse(first.Equals(second)); Assert.IsFalse(second.Equals(first)); Assert.AreNotEqual(0, first.CompareTo(second)); Assert.AreNotEqual(0, second.CompareTo(first)); second = new YearMonthDay(2000, 1, 2); Assert.AreNotEqual(first, second); Assert.IsFalse(first.Equals(second)); Assert.IsFalse(second.Equals(first)); Assert.AreNotEqual(0, first.CompareTo(second)); Assert.AreNotEqual(0, second.CompareTo(first)); Assert.AreNotEqual(first, 5); }
public void TestDefaultConstructedIsValid() { YearMonthDay ymd = new YearMonthDay(); YearMonthDay ymd2 = new YearMonthDay(ymd.Year, ymd.Month, ymd.Day); Assert.AreEqual(ymd, ymd2); Assert.AreEqual(ymd.DayOfWeek, ymd2.DayOfWeek); Assert.AreEqual(ymd.DayOfYear, ymd2.DayOfYear); }
public void TestRetainValue() { YearMonthDay date = new YearMonthDay(2000, 1, 1); Assert.AreEqual(2000, date.Year); Assert.AreEqual(1, date.Month); Assert.AreEqual(1, date.Day); }
public void TestComparisons() { YearMonthDay ymd1 = new YearMonthDay(2006, 3, 14); YearMonthDay ymd2 = new YearMonthDay(2006, 3, 14); YearMonthDay ymd3 = new YearMonthDay(2006, 5, 26); object ymd4 = new YearMonthDay(2004, 2, 21); Assert.IsTrue(ymd1 == ymd2); Assert.IsTrue(ymd2 == ymd1); Assert.IsTrue(ymd1 != ymd3); Assert.IsTrue(ymd1 >= ymd2); Assert.IsTrue(ymd1 <= ymd2); Assert.IsTrue(ymd1.CompareTo(ymd2) == 0); Assert.IsTrue(ymd2 < ymd3); Assert.IsTrue(ymd2 <= ymd3); Assert.IsTrue(ymd3 > ymd2); Assert.IsTrue(ymd3 >= ymd2); Assert.AreNotEqual(ymd1, ymd4); }
internal override int GetDaysSinceEpoch(YearMonthDay yearMonthDay) => // Just inline the arithmetic that would be done via various methods. GetStartOfYearInDays(yearMonthDay.Year) + (yearMonthDay.Month - 1) * DaysInMonth + (yearMonthDay.Day - 1);
internal override YearMonthDay AddMonths(YearMonthDay yearMonthDay, 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 yearMonthDay; } int year = yearMonthDay.Year; int month = CalendarToCivilMonth(year, yearMonthDay.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 >= GetMonthsInYear(year)) { months -= GetMonthsInYear(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 -= GetMonthsInYear(year) - month; // Subtract a year at a time while (months + GetMonthsInYear(year) <= 0) { months += GetMonthsInYear(year); year--; } // However many months we've got left to add (which will still be negative...) // tells us the final month. month = GetMonthsInYear(year) + months; } // Convert back to calendar month month = CivilToCalendarMonth(year, month); int day = Math.Min(GetDaysInMonth(year, month), yearMonthDay.Day); return new YearMonthDay(year, month, day); }
public void TestDayOfWeek() { YearMonthDay ymd = new YearMonthDay(2009, 06, 10); Assert.AreEqual(DayOfWeek.Wednesday, ymd.DayOfWeek); ymd = new YearMonthDay(2009, 06, 11); Assert.AreEqual(DayOfWeek.Thursday, ymd.DayOfWeek); }
public void TestCompareToWrongType() { YearMonthDay ymd = new YearMonthDay(2006, 3, 14); ymd.CompareTo(5); }