Skip to content

Commit 6df2b8d

Browse files
authored
Optimize PersianCalendar.AddMonths calculations (dotnet#60778)
1 parent 9ba1b85 commit 6df2b8d

File tree

1 file changed

+29
-3
lines changed

1 file changed

+29
-3
lines changed

src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,34 @@ internal int GetDatePart(long ticks, int part)
188188
throw new InvalidOperationException(SR.InvalidOperation_DateTimeParsing);
189189
}
190190

191+
// Exactly the same as GetDatePart, except computing all of
192+
// year/month/day rather than just one of them. Used when all three
193+
// are needed rather than redoing the computations for each.
194+
internal void GetDate(long ticks, out int year, out int month, out int day)
195+
{
196+
CheckTicksRange(ticks);
197+
198+
// Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D.
199+
// 1/1/0001 is absolute date 1.
200+
long numDays = ticks / GregorianCalendar.TicksPerDay + 1;
201+
202+
// Calculate the appromixate Persian Year.
203+
long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(numDays);
204+
year = (int)(Math.Floor(((yearStart - s_persianEpoch) / CalendricalCalculationsHelper.MeanTropicalYearInDays) + 0.5)) + 1;
205+
Debug.Assert(year >= 1);
206+
207+
// Calculate the Persian Month.
208+
int ordinalDay = (int)(numDays - CalendricalCalculationsHelper.GetNumberOfDays(this.ToDateTime(year, 1, 1, 0, 0, 0, 0, 1)));
209+
210+
month = MonthFromOrdinalDay(ordinalDay);
211+
Debug.Assert(ordinalDay >= 1);
212+
Debug.Assert(month >= 1 && month <= 12);
213+
214+
day = ordinalDay - DaysInPreviousMonths(month);
215+
Debug.Assert(1 <= day);
216+
Debug.Assert(day <= 31);
217+
}
218+
191219
public override DateTime AddMonths(DateTime time, int months)
192220
{
193221
if (months < -120000 || months > 120000)
@@ -199,9 +227,7 @@ public override DateTime AddMonths(DateTime time, int months)
199227
}
200228

201229
// Get the date in Persian calendar.
202-
int y = GetDatePart(time.Ticks, DatePartYear);
203-
int m = GetDatePart(time.Ticks, DatePartMonth);
204-
int d = GetDatePart(time.Ticks, DatePartDay);
230+
GetDate(time.Ticks, out int y, out int m, out int d);
205231
int i = m - 1 + months;
206232
if (i >= 0)
207233
{

0 commit comments

Comments
 (0)