// Hoist most of the bounds checks on buffer.
{ var unused = destination[MinimumBytesNeeded - 1]; }
- // TODO: Introduce an API which can parse DateTime instances efficiently, pulling out
- // all their properties (Month, Day, etc.) in one shot. This would help avoid the
- // duplicate work that implicitly results from calling these properties individually.
+ value.GetDate(out int year, out int month, out int day);
+ value.GetTime(out int hour, out int minute, out int second);
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Month, destination, 0);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)month, destination, 0);
destination[2] = Utf8Constants.Slash;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Day, destination, 3);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)day, destination, 3);
destination[5] = Utf8Constants.Slash;
- FormattingHelpers.WriteFourDecimalDigits((uint)value.Year, destination, 6);
+ FormattingHelpers.WriteFourDecimalDigits((uint)year, destination, 6);
destination[10] = Utf8Constants.Space;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Hour, destination, 11);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)hour, destination, 11);
destination[13] = Utf8Constants.Colon;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Minute, destination, 14);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)minute, destination, 14);
destination[16] = Utf8Constants.Colon;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Second, destination, 17);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)second, destination, 17);
if (offset != Utf8Constants.NullUtcOffset)
{
+ int offsetTotalMinutes = (int)(offset.Ticks / TimeSpan.TicksPerMinute);
byte sign;
- if (offset < default(TimeSpan) /* a "const" version of TimeSpan.Zero */)
+ if (offsetTotalMinutes < 0)
{
sign = Utf8Constants.Minus;
- offset = TimeSpan.FromTicks(-offset.Ticks);
+ offsetTotalMinutes = -offsetTotalMinutes;
}
else
{
sign = Utf8Constants.Plus;
}
+ int offsetHours = Math.DivRem(offsetTotalMinutes, 60, out int offsetMinutes);
+
// Writing the value backward allows the JIT to optimize by
// performing a single bounds check against buffer.
- FormattingHelpers.WriteTwoDecimalDigits((uint)offset.Minutes, destination, 24);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)offsetMinutes, destination, 24);
destination[23] = Utf8Constants.Colon;
- FormattingHelpers.WriteTwoDecimalDigits((uint)offset.Hours, destination, 21);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)offsetHours, destination, 21);
destination[20] = sign;
destination[19] = Utf8Constants.Space;
}
return false;
}
+ value.GetDate(out int year, out int month, out int day);
+ value.GetTime(out int hour, out int minute, out int second);
+
uint dayAbbrev = s_dayAbbreviationsLowercase[(int)value.DayOfWeek];
destination[0] = (byte)dayAbbrev;
destination[3] = Utf8Constants.Comma;
destination[4] = Utf8Constants.Space;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Day, destination, 5);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)day, destination, 5);
destination[7] = Utf8Constants.Space;
- uint monthAbbrev = s_monthAbbreviationsLowercase[value.Month - 1];
+ uint monthAbbrev = s_monthAbbreviationsLowercase[month - 1];
destination[8] = (byte)monthAbbrev;
monthAbbrev >>= 8;
destination[9] = (byte)monthAbbrev;
destination[10] = (byte)monthAbbrev;
destination[11] = Utf8Constants.Space;
- FormattingHelpers.WriteFourDecimalDigits((uint)value.Year, destination, 12);
+ FormattingHelpers.WriteFourDecimalDigits((uint)year, destination, 12);
destination[16] = Utf8Constants.Space;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Hour, destination, 17);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)hour, destination, 17);
destination[19] = Utf8Constants.Colon;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Minute, destination, 20);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)minute, destination, 20);
destination[22] = Utf8Constants.Colon;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Second, destination, 23);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)second, destination, 23);
destination[25] = Utf8Constants.Space;
destination[26] = GMT1Lowercase;
// Hoist most of the bounds checks on buffer.
{ _ = destination[MinimumBytesNeeded - 1]; }
- FormattingHelpers.WriteFourDecimalDigits((uint)value.Year, destination, 0);
+ value.GetDate(out int year, out int month, out int day);
+ value.GetTimePrecise(out int hour, out int minute, out int second, out int ticks);
+
+ FormattingHelpers.WriteFourDecimalDigits((uint)year, destination, 0);
destination[4] = Utf8Constants.Minus;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Month, destination, 5);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)month, destination, 5);
destination[7] = Utf8Constants.Minus;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Day, destination, 8);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)day, destination, 8);
destination[10] = TimeMarker;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Hour, destination, 11);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)hour, destination, 11);
destination[13] = Utf8Constants.Colon;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Minute, destination, 14);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)minute, destination, 14);
destination[16] = Utf8Constants.Colon;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Second, destination, 17);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)second, destination, 17);
destination[19] = Utf8Constants.Period;
- FormattingHelpers.WriteDigits((uint)((ulong)value.Ticks % (ulong)TimeSpan.TicksPerSecond), destination.Slice(20, 7));
+ FormattingHelpers.WriteDigits((uint)ticks, destination.Slice(20, 7));
if (kind == DateTimeKind.Local)
{
+ int offsetTotalMinutes = (int)(offset.Ticks / TimeSpan.TicksPerMinute);
byte sign;
- if (offset < default(TimeSpan) /* a "const" version of TimeSpan.Zero */)
+ if (offsetTotalMinutes < 0)
{
sign = Utf8Constants.Minus;
- offset = TimeSpan.FromTicks(-offset.Ticks);
+ offsetTotalMinutes = -offsetTotalMinutes;
}
else
{
sign = Utf8Constants.Plus;
}
+ int offsetHours = Math.DivRem(offsetTotalMinutes, 60, out int offsetMinutes);
+
// Writing the value backward allows the JIT to optimize by
// performing a single bounds check against buffer.
- FormattingHelpers.WriteTwoDecimalDigits((uint)offset.Minutes, destination, 31);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)offsetMinutes, destination, 31);
destination[30] = Utf8Constants.Colon;
- FormattingHelpers.WriteTwoDecimalDigits((uint)offset.Hours, destination, 28);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)offsetHours, destination, 28);
destination[27] = sign;
}
else if (kind == DateTimeKind.Utc)
return false;
}
+ value.GetDate(out int year, out int month, out int day);
+ value.GetTime(out int hour, out int minute, out int second);
+
uint dayAbbrev = s_dayAbbreviations[(int)value.DayOfWeek];
destination[0] = (byte)dayAbbrev;
destination[3] = Utf8Constants.Comma;
destination[4] = Utf8Constants.Space;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Day, destination, 5);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)day, destination, 5);
destination[7] = Utf8Constants.Space;
- uint monthAbbrev = s_monthAbbreviations[value.Month - 1];
+ uint monthAbbrev = s_monthAbbreviations[month - 1];
destination[8] = (byte)monthAbbrev;
monthAbbrev >>= 8;
destination[9] = (byte)monthAbbrev;
destination[10] = (byte)monthAbbrev;
destination[11] = Utf8Constants.Space;
- FormattingHelpers.WriteFourDecimalDigits((uint)value.Year, destination, 12);
+ FormattingHelpers.WriteFourDecimalDigits((uint)year, destination, 12);
destination[16] = Utf8Constants.Space;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Hour, destination, 17);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)hour, destination, 17);
destination[19] = Utf8Constants.Colon;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Minute, destination, 20);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)minute, destination, 20);
destination[22] = Utf8Constants.Colon;
- FormattingHelpers.WriteTwoDecimalDigits((uint)value.Second, destination, 23);
+ FormattingHelpers.WriteTwoDecimalDigits((uint)second, destination, 23);
destination[25] = Utf8Constants.Space;
destination[26] = GMT1;
{
DateTime dt = new DateTime(ticks);
- int year, month, day;
- dt.GetDatePart(out year, out month, out day);
+ dt.GetDate(out int year, out int month, out int day);
+ dt.GetTime(out int hour, out int minute, out int second, out int millisecond);
systemTime.Year = (ushort)year;
systemTime.Month = (ushort)month;
systemTime.DayOfWeek = (ushort)dt.DayOfWeek;
systemTime.Day = (ushort)day;
- systemTime.Hour = (ushort)dt.Hour;
- systemTime.Minute = (ushort)dt.Minute;
- systemTime.Second = (ushort)dt.Second;
- systemTime.Milliseconds = (ushort)dt.Millisecond;
+ systemTime.Hour = (ushort)hour;
+ systemTime.Minute = (ushort)minute;
+ systemTime.Second = (ushort)second;
+ systemTime.Milliseconds = (ushort)millisecond;
hundredNanoSecond = 0;
}
}
public DateTime AddMonths(int months)
{
if (months < -120000 || months > 120000) throw new ArgumentOutOfRangeException(nameof(months), SR.ArgumentOutOfRange_DateTimeBadMonths);
- GetDatePart(out int y, out int m, out int d);
+ GetDate(out int y, out int m, out int d);
int i = m - 1 + months;
if (i >= 0)
{
return n - days[m - 1] + 1;
}
- // Exactly the same as GetDatePart(int part), except computing all of
- // year/month/day rather than just one of them. Used when all three
+ // Exactly the same as GetDatePart, except computing all of
+ // year/month/day rather than just one of them. Used when all three
// are needed rather than redoing the computations for each.
- internal void GetDatePart(out int year, out int month, out int day)
+ internal void GetDate(out int year, out int month, out int day)
{
long ticks = InternalTicks;
// n = number of days since 1/1/0001
day = n - days[m - 1] + 1;
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal void GetTime(out int hour, out int minute, out int second)
+ {
+ long n = InternalTicks / TicksPerSecond;
+ n = Math.DivRem(n, 60, out long m);
+ second = (int)m;
+ n = Math.DivRem(n, 60, out m);
+ minute = (int)m;
+ hour = (int)(n % 24);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal void GetTime(out int hour, out int minute, out int second, out int millisecond)
+ {
+ long n = InternalTicks / TicksPerMillisecond;
+ n = Math.DivRem(n, 1000, out long m);
+ millisecond = (int)m;
+ n = Math.DivRem(n, 60, out m);
+ second = (int)m;
+ n = Math.DivRem(n, 60, out m);
+ minute = (int)m;
+ hour = (int)(n % 24);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal void GetTimePrecise(out int hour, out int minute, out int second, out int tick)
+ {
+ long n = Math.DivRem(InternalTicks, TicksPerSecond, out long m);
+ tick = (int)m;
+ n = Math.DivRem(n, 60, out m);
+ second = (int)m;
+ n = Math.DivRem(n, 60, out m);
+ minute = (int)m;
+ hour = (int)(n % 24);
+ }
+
// Returns the day-of-month part of this DateTime. The returned
// value is an integer between 1 and 31.
//
// Hoist most of the bounds checks on destination.
{ _ = destination[MinimumBytesNeeded - 1]; }
- WriteFourDecimalDigits((uint)dateTime.Year, destination, 0);
+ dateTime.GetDate(out int year, out int month, out int day);
+ dateTime.GetTimePrecise(out int hour, out int minute, out int second, out int tick);
+
+ WriteFourDecimalDigits((uint)year, destination, 0);
destination[4] = '-';
- WriteTwoDecimalDigits((uint)dateTime.Month, destination, 5);
+ WriteTwoDecimalDigits((uint)month, destination, 5);
destination[7] = '-';
- WriteTwoDecimalDigits((uint)dateTime.Day, destination, 8);
+ WriteTwoDecimalDigits((uint)day, destination, 8);
destination[10] = 'T';
- WriteTwoDecimalDigits((uint)dateTime.Hour, destination, 11);
+ WriteTwoDecimalDigits((uint)hour, destination, 11);
destination[13] = ':';
- WriteTwoDecimalDigits((uint)dateTime.Minute, destination, 14);
+ WriteTwoDecimalDigits((uint)minute, destination, 14);
destination[16] = ':';
- WriteTwoDecimalDigits((uint)dateTime.Second, destination, 17);
+ WriteTwoDecimalDigits((uint)second, destination, 17);
destination[19] = '.';
- WriteDigits((uint)((ulong)dateTime.Ticks % (ulong)TimeSpan.TicksPerSecond), destination.Slice(20, 7));
+ WriteDigits((uint)tick, destination.Slice(20, 7));
if (kind == DateTimeKind.Local)
{
+ int offsetTotalMinutes = (int)(offset.Ticks / TimeSpan.TicksPerMinute);
+
char sign;
- if (offset < default(TimeSpan) /* a "const" version of TimeSpan.Zero */)
+ if (offsetTotalMinutes < 0)
{
sign = '-';
- offset = TimeSpan.FromTicks(-offset.Ticks);
+ offsetTotalMinutes = -offsetTotalMinutes;
}
else
{
sign = '+';
}
+ int offsetHours = Math.DivRem(offsetTotalMinutes, 60, out int offsetMinutes);
+
// Writing the value backward allows the JIT to optimize by
// performing a single bounds check against buffer.
- WriteTwoDecimalDigits((uint)offset.Minutes, destination, 31);
+ WriteTwoDecimalDigits((uint)offsetMinutes, destination, 31);
destination[30] = ':';
- WriteTwoDecimalDigits((uint)offset.Hours, destination, 28);
+ WriteTwoDecimalDigits((uint)offsetHours, destination, 28);
destination[27] = sign;
}
else if (kind == DateTimeKind.Utc)
dateTime -= offset;
}
- dateTime.GetDatePart(out int year, out int month, out int day);
+ dateTime.GetDate(out int year, out int month, out int day);
+ dateTime.GetTime(out int hour, out int minute, out int second);
string dayAbbrev = InvariantAbbreviatedDayNames[(int)dateTime.DayOfWeek];
Debug.Assert(dayAbbrev.Length == 3);
destination[11] = ' ';
WriteFourDecimalDigits((uint)year, destination, 12);
destination[16] = ' ';
- WriteTwoDecimalDigits((uint)dateTime.Hour, destination, 17);
+ WriteTwoDecimalDigits((uint)hour, destination, 17);
destination[19] = ':';
- WriteTwoDecimalDigits((uint)dateTime.Minute, destination, 20);
+ WriteTwoDecimalDigits((uint)minute, destination, 20);
destination[22] = ':';
- WriteTwoDecimalDigits((uint)dateTime.Second, destination, 23);
+ WriteTwoDecimalDigits((uint)second, destination, 23);
destination[25] = ' ';
destination[26] = 'G';
destination[27] = 'M';
private DateTime LunarToTime(DateTime time, int year, int month, int day)
{
LunarToGregorian(year, month, day, out int gy, out int gm, out int gd);
- return GregorianCalendar.GetDefaultInstance().ToDateTime(gy, gm, gd, time.Hour, time.Minute, time.Second, time.Millisecond);
+ time.GetTime(out int hour, out int minute, out int second, out int millisecond);
+ return GregorianCalendar.GetDefaultInstance().ToDateTime(gy, gm, gd, hour, minute, second, millisecond);
}
private void TimeToLunar(DateTime time, out int year, out int month, out int day)
SR.Format(SR.ArgumentOutOfRange_Range, -120000, 120000));
}
- time.GetDatePart(out int y, out int m, out int d);
+ time.GetDate(out int y, out int m, out int d);
int i = m - 1 + months;
if (i >= 0)
{
DateTime time = new DateTime(ticks);
// Save the Gregorian date values.
- time.GetDatePart(out gregorianYear, out gregorianMonth, out gregorianDay);
+ time.GetDate(out gregorianYear, out gregorianMonth, out gregorianDay);
DateBuffer lunarDate = new DateBuffer(); // lunar month and day for Jan 1
}
dt = dt.AddDays(nDays);
- dt.GetDatePart(out yg, out mg, out dg);
+ dt.GetDate(out yg, out mg, out dg);
}
private static long GetAbsoluteDateUmAlQura(int year, int month, int day)
//
internal bool IsStartDateMarkerForBeginningOfYear() =>
!NoDaylightTransitions &&
- DaylightTransitionStart.Month == 1 && DaylightTransitionStart.Day == 1 && DaylightTransitionStart.TimeOfDay.Hour == 0 &&
- DaylightTransitionStart.TimeOfDay.Minute == 0 && DaylightTransitionStart.TimeOfDay.Second == 0 &&
+ DaylightTransitionStart.Month == 1 && DaylightTransitionStart.Day == 1 &&
+ DaylightTransitionStart.TimeOfDay.TimeOfDay.Ticks < TimeSpan.TicksPerSecond && // < 12:00:01 AM
_dateStart.Year == _dateEnd.Year;
//
//
internal bool IsEndDateMarkerForEndOfYear() =>
!NoDaylightTransitions &&
- DaylightTransitionEnd.Month == 1 && DaylightTransitionEnd.Day == 1 && DaylightTransitionEnd.TimeOfDay.Hour == 0 &&
- DaylightTransitionEnd.TimeOfDay.Minute == 0 && DaylightTransitionEnd.TimeOfDay.Second == 0 &&
+ DaylightTransitionEnd.Month == 1 && DaylightTransitionEnd.Day == 1 &&
+ DaylightTransitionEnd.TimeOfDay.TimeOfDay.Ticks < TimeSpan.TicksPerSecond && // < 12:00:01 AM
_dateStart.Year == _dateEnd.Year;
/// <summary>
throw new ArgumentOutOfRangeException(nameof(dayOfWeek), SR.ArgumentOutOfRange_DayOfWeek);
}
- timeOfDay.GetDatePart(out int timeOfDayYear, out int timeOfDayMonth, out int timeOfDayDay);
+ timeOfDay.GetDate(out int timeOfDayYear, out int timeOfDayMonth, out int timeOfDayDay);
if (timeOfDayYear != 1 || timeOfDayMonth != 1 || timeOfDayDay != 1 || (timeOfDay.Ticks % TimeSpan.TicksPerMillisecond != 0))
{
throw new ArgumentException(SR.Argument_DateTimeHasTicks, nameof(timeOfDay));
internal static DateTime TransitionTimeToDateTime(int year, TransitionTime transitionTime)
{
DateTime value;
- DateTime timeOfDay = transitionTime.TimeOfDay;
+ TimeSpan timeOfDay = transitionTime.TimeOfDay.TimeOfDay;
if (transitionTime.IsFixedDateRule)
{
// create a DateTime from the passed in year and the properties on the transitionTime
+ int day = transitionTime.Day;
// if the day is out of range for the month then use the last day of the month
- int day = DateTime.DaysInMonth(year, transitionTime.Month);
+ if (day > 28)
+ {
+ int daysInMonth = DateTime.DaysInMonth(year, transitionTime.Month);
+ if (day > daysInMonth)
+ {
+ day = daysInMonth;
+ }
+ }
- value = new DateTime(year, transitionTime.Month, (day < transitionTime.Day) ? day : transitionTime.Day,
- timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);
+ value = new DateTime(year, transitionTime.Month, day) + timeOfDay;
}
else
{
//
// Get the (transitionTime.Week)th Sunday.
//
- value = new DateTime(year, transitionTime.Month, 1,
- timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);
+ value = new DateTime(year, transitionTime.Month, 1) + timeOfDay;
int dayOfWeek = (int)value.DayOfWeek;
int delta = (int)transitionTime.DayOfWeek - dayOfWeek;
// If TransitionWeek is greater than 4, we will get the last week.
//
int daysInMonth = DateTime.DaysInMonth(year, transitionTime.Month);
- value = new DateTime(year, transitionTime.Month, daysInMonth,
- timeOfDay.Hour, timeOfDay.Minute, timeOfDay.Second, timeOfDay.Millisecond);
+ value = new DateTime(year, transitionTime.Month, daysInMonth) + timeOfDay;
// This is the day of week for the last day of the month.
int dayOfWeek = (int)value.DayOfWeek;