一、DateTime是值类型还是引用类型的探索
二、了解DateTime结构体
三、DateTime.Now和DateTime.UtcNow是怎么计算出来的
一、DateTime是值类型还是引用类型的探索
DateTime是值类型,因为DateTime是结构体,而结构体继承自System.ValueType,属于值类型
1 [Serializable, __DynamicallyInvokable] 2 public struct DateTime : IComparable, IFormattable, IConvertible, ISerializable, IComparable<DateTime>, IEquatable<DateTime> 3 { 4 // Fields 5 private ulong dateData; 6 private const string DateDataField = "dateData"; 7 private const int DatePartDay = 3; 8 private const int DatePartDayOfYear = 1; 9 private const int DatePartMonth = 2; 10 private const int DatePartYear = 0; 11 private const int DaysPer100Years = 0x8eac; 12 private const int DaysPer400Years = 0x23ab1; 13 private const int DaysPer4Years = 0x5b5; 14 private const int DaysPerYear = 0x16d; 15 private const int DaysTo10000 = 0x37b9db; 16 private const int DaysTo1601 = 0x8eac4; 17 private const int DaysTo1899 = 0xa9559; 18 private static readonly int[] DaysToMonth365; 19 private static readonly int[] DaysToMonth366; 20 private const long DoubleDateOffset = 0x85103c0cb83c000L; 21 private const long FileTimeOffset = 0x701ce1722770000L; 22 private const ulong FlagsMask = 13835058055282163712L; 23 private const ulong KindLocal = 9223372036854775808L; 24 private const ulong KindLocalAmbiguousDst = 13835058055282163712L; 25 private const int KindShift = 0x3e; 26 private const ulong KindUnspecified = 0L; 27 private const ulong KindUtc = 0x4000000000000000L; 28 private const ulong LocalMask = 9223372036854775808L; 29 private const long MaxMillis = 0x11efae44cb400L; 30 internal const long MaxTicks = 0x2bca2875f4373fffL; 31 [__DynamicallyInvokable] 32 public static readonly DateTime MaxValue; 33 private const int MillisPerDay = 0x5265c00; 34 private const int MillisPerHour = 0x36ee80; 35 private const int MillisPerMinute = 0xea60; 36 private const int MillisPerSecond = 0x3e8; 37 internal const long MinTicks = 0L; 38 [__DynamicallyInvokable] 39 public static readonly DateTime MinValue; 40 private const double OADateMaxAsDouble = 2958466.0; 41 private const double OADateMinAsDouble = -657435.0; 42 private const long OADateMinAsTicks = 0x6efdddaec64000L; 43 private const long TicksCeiling = 0x4000000000000000L; 44 private const string TicksField = "ticks"; 45 private const ulong TicksMask = 0x3fffffffffffffffL; 46 private const long TicksPerDay = 0xc92a69c000L; 47 private const long TicksPerHour = 0x861c46800L; 48 private const long TicksPerMillisecond = 0x2710L; 49 private const long TicksPerMinute = 0x23c34600L; 50 private const long TicksPerSecond = 0x989680L; 51 52 // Methods 53 static DateTime(); 54 [__DynamicallyInvokable] 55 public DateTime(long ticks); 56 [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 57 private DateTime(ulong dateData); 58 [__DynamicallyInvokable] 59 public DateTime(long ticks, DateTimeKind kind); 60 private DateTime(SerializationInfo info, StreamingContext context); 61 [__DynamicallyInvokable] 62 public DateTime(int year, int month, int day); 63 internal DateTime(long ticks, DateTimeKind kind, bool isAmbiguousDst); 64 [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 65 public DateTime(int year, int month, int day, Calendar calendar); 66 [__DynamicallyInvokable] 67 public DateTime(int year, int month, int day, int hour, int minute, int second); 68 [__DynamicallyInvokable] 69 public DateTime(int year, int month, int day, int hour, int minute, int second, DateTimeKind kind); 70 public DateTime(int year, int month, int day, int hour, int minute, int second, Calendar calendar); 71 [__DynamicallyInvokable] 72 public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond); 73 [__DynamicallyInvokable] 74 public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, DateTimeKind kind); 75 public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar); 76 public DateTime(int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar, DateTimeKind kind); 77 [__DynamicallyInvokable] 78 public DateTime Add(TimeSpan value); 79 private DateTime Add(double value, int scale); 80 [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 81 public DateTime AddDays(double value); 82 [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 83 public DateTime AddHours(double value); 84 [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 85 public DateTime AddMilliseconds(double value); 86 [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 87 public DateTime AddMinutes(double value); 88 [__DynamicallyInvokable] 89 public DateTime AddMonths(int months); 90 [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 91 public DateTime AddSeconds(double value); 92 [__DynamicallyInvokable] 93 public DateTime AddTicks(long value); 94 [__DynamicallyInvokable] 95 public DateTime AddYears(int value); 96 [__DynamicallyInvokable] 97 public static int Compare(DateTime t1, DateTime t2); 98 [__DynamicallyInvokable] 99 public int CompareTo(DateTime value); 100 public int CompareTo(object value); 101 private static long DateToTicks(int year, int month, int day); 102 [__DynamicallyInvokable] 103 public static int DaysInMonth(int year, int month); 104 internal static long DoubleDateToTicks(double value); 105 [return: MarshalAs(UnmanagedType.Bool)] 106 [SecurityCritical, SuppressUnmanagedCodeSecurity, DllImport("QCall", CharSet=CharSet.Unicode)] 107 internal static extern bool EnableAmPmParseAdjustment(); 108 [__DynamicallyInvokable] 109 public bool Equals(DateTime value); 110 [__DynamicallyInvokable] 111 public override bool Equals(object value); 112 [__DynamicallyInvokable] 113 public static bool Equals(DateTime t1, DateTime t2); 114 [__DynamicallyInvokable] 115 public static DateTime FromBinary(long dateData); 116 internal static DateTime FromBinaryRaw(long dateData); 117 [__DynamicallyInvokable] 118 public static DateTime FromFileTime(long fileTime); 119 [__DynamicallyInvokable] 120 public static DateTime FromFileTimeUtc(long fileTime); 121 [__DynamicallyInvokable] 122 public static DateTime FromOADate(double d); 123 private int GetDatePart(int part); 124 [__DynamicallyInvokable] 125 public string[] GetDateTimeFormats(); 126 [__DynamicallyInvokable] 127 public string[] GetDateTimeFormats(char format); 128 [__DynamicallyInvokable] 129 public string[] GetDateTimeFormats(IFormatProvider provider); 130 [__DynamicallyInvokable] 131 public string[] GetDateTimeFormats(char format, IFormatProvider provider); 132 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 133 public override int GetHashCode(); 134 [MethodImpl(MethodImplOptions.InternalCall), SecurityCritical] 135 internal static extern long GetSystemTimeAsFileTime(); 136 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 137 public TypeCode GetTypeCode(); 138 internal bool IsAmbiguousDaylightSavingTime(); 139 [__DynamicallyInvokable] 140 public bool IsDaylightSavingTime(); 141 [__DynamicallyInvokable] 142 public static bool IsLeapYear(int year); 143 [__DynamicallyInvokable] 144 public static DateTime operator +(DateTime d, TimeSpan t); 145 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 146 public static bool operator ==(DateTime d1, DateTime d2); 147 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 148 public static bool operator >(DateTime t1, DateTime t2); 149 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 150 public static bool operator >=(DateTime t1, DateTime t2); 151 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 152 public static bool operator !=(DateTime d1, DateTime d2); 153 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 154 public static bool operator <(DateTime t1, DateTime t2); 155 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 156 public static bool operator <=(DateTime t1, DateTime t2); 157 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 158 public static TimeSpan operator -(DateTime d1, DateTime d2); 159 [__DynamicallyInvokable] 160 public static DateTime operator -(DateTime d, TimeSpan t); 161 [__DynamicallyInvokable] 162 public static DateTime Parse(string s); 163 [__DynamicallyInvokable] 164 public static DateTime Parse(string s, IFormatProvider provider); 165 [__DynamicallyInvokable] 166 public static DateTime Parse(string s, IFormatProvider provider, DateTimeStyles styles); 167 [__DynamicallyInvokable] 168 public static DateTime ParseExact(string s, string format, IFormatProvider provider); 169 [__DynamicallyInvokable] 170 public static DateTime ParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style); 171 [__DynamicallyInvokable] 172 public static DateTime ParseExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style); 173 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 174 public static DateTime SpecifyKind(DateTime value, DateTimeKind kind); 175 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 176 public TimeSpan Subtract(DateTime value); 177 [__DynamicallyInvokable] 178 public DateTime Subtract(TimeSpan value); 179 bool IConvertible.ToBoolean(IFormatProvider provider); 180 byte IConvertible.ToByte(IFormatProvider provider); 181 char IConvertible.ToChar(IFormatProvider provider); 182 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 183 DateTime IConvertible.ToDateTime(IFormatProvider provider); 184 decimal IConvertible.ToDecimal(IFormatProvider provider); 185 double IConvertible.ToDouble(IFormatProvider provider); 186 short IConvertible.ToInt16(IFormatProvider provider); 187 int IConvertible.ToInt32(IFormatProvider provider); 188 long IConvertible.ToInt64(IFormatProvider provider); 189 sbyte IConvertible.ToSByte(IFormatProvider provider); 190 float IConvertible.ToSingle(IFormatProvider provider); 191 object IConvertible.ToType(Type type, IFormatProvider provider); 192 ushort IConvertible.ToUInt16(IFormatProvider provider); 193 uint IConvertible.ToUInt32(IFormatProvider provider); 194 ulong IConvertible.ToUInt64(IFormatProvider provider); 195 [SecurityCritical] 196 void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context); 197 private static double TicksToOADate(long value); 198 private static long TimeToTicks(int hour, int minute, int second); 199 [__DynamicallyInvokable] 200 public long ToBinary(); 201 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] 202 internal long ToBinaryRaw(); 203 [__DynamicallyInvokable] 204 public long ToFileTime(); 205 [__DynamicallyInvokable] 206 public long ToFileTimeUtc(); 207 [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] 208 public DateTime ToLocalTime(); 209 internal DateTime ToLocalTime(bool throwOnOverflow); 210 public string ToLongDateString(); 211 public string ToLongTimeString(); 212 [__DynamicallyInvokable] 213 public double ToOADate(); 214 public string ToShortDateString(); 215 public string ToShortTimeString(); 216 [__DynamicallyInvokable] 217 public override string ToString(); 218 [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] 219 public string ToString(IFormatProvider provider); 220 [__DynamicallyInvokable] 221 public string ToString(string format); 222 [__DynamicallyInvokable] 223 public string ToString(string format, IFormatProvider provider); 224 [__DynamicallyInvokable] 225 public DateTime ToUniversalTime(); 226 internal static bool TryCreate(int year, int month, int day, int hour, int minute, int second, int millisecond, out DateTime result); 227 [__DynamicallyInvokable] 228 public static bool TryParse(string s, out DateTime result); 229 [__DynamicallyInvokable] 230 public static bool TryParse(string s, IFormatProvider provider, DateTimeStyles styles, out DateTime result); 231 [__DynamicallyInvokable] 232 public static bool TryParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result); 233 [__DynamicallyInvokable] 234 public static bool TryParseExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style, out DateTime result); 235 236 // Properties 237 [__DynamicallyInvokable] 238 public DateTime Date { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] get; } 239 [__DynamicallyInvokable] 240 public int Day { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get; } 241 [__DynamicallyInvokable] 242 public DayOfWeek DayOfWeek { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] get; } 243 [__DynamicallyInvokable] 244 public int DayOfYear { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get; } 245 [__DynamicallyInvokable] 246 public int Hour { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] get; } 247 private ulong InternalKind { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] get; } 248 internal long InternalTicks { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")] get; } 249 [__DynamicallyInvokable] 250 public DateTimeKind Kind { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] get; } 251 [__DynamicallyInvokable] 252 public int Millisecond { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] get; } 253 [__DynamicallyInvokable] 254 public int Minute { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] get; } 255 [__DynamicallyInvokable] 256 public int Month { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get; } 257 [__DynamicallyInvokable] 258 public static DateTime Now { [__DynamicallyInvokable] get; } 259 [__DynamicallyInvokable] 260 public int Second { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] get; } 261 [__DynamicallyInvokable] 262 public long Ticks { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get; } 263 [__DynamicallyInvokable] 264 public TimeSpan TimeOfDay { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] get; } 265 [__DynamicallyInvokable] 266 public static DateTime Today { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), __DynamicallyInvokable] get; } 267 [__DynamicallyInvokable] 268 public static DateTime UtcNow { [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries"), SecuritySafeCritical, __DynamicallyInvokable] get; } 269 [__DynamicallyInvokable] 270 public int Year { [__DynamicallyInvokable, TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")] get; } 271 } 272 273 274 275
二、了解DateTime结构体
转到DateTime的定义,也可以看到DateTime确实是struct类型,
看来前面的试验都是无用功了,但DateTime到底是怎样的结构体呢,主要有如下成员
这些成员里面最关键的是Ticks
Ticks的时间值以 100 毫微秒为单位,它的64位中,前两位表示Kind,后面62位表示有多少个毫微秒。Kind用来指示 DateTime 结构是表示本地时间、协调通用时间 (UTC) 还是 UTC 和本地时间都未指定。Kind 字段用于处理本地时间和 UTC 时间之间的转换。
DateTime的值范围在0001/1/1 00:00:00到9999/12/31 23:59:59之间
三、DateTime.Now和DateTime.UtcNow是怎么计算出来的
反编译DateTime.Now如下:
1 [__DynamicallyInvokable] 2 public static DateTime Now 3 { 4 [__DynamicallyInvokable] 5 get 6 { 7 DateTime utcNow = UtcNow; 8 bool isAmbiguousLocalDst = false; 9 long ticks = TimeZoneInfo.GetDateTimeNowUtcOffsetFromUtc(utcNow, out isAmbiguousLocalDst).Ticks; 10 long num2 = utcNow.Ticks + ticks; 11 if (num2 > 0x2bca2875f4373fffL) 12 { 13 return new DateTime(0x2bca2875f4373fffL, DateTimeKind.Local); 14 } 15 if (num2 < 0L) 16 { 17 return new DateTime(0L, DateTimeKind.Local); 18 } 19 return new DateTime(num2, DateTimeKind.Local, isAmbiguousLocalDst); 20 } 21 } 22 23 24
大致的意思是先获取DateTime.UtcNow,然后转换为本地时间
再反编译DateTime.UtcNow:
1 [__DynamicallyInvokable] 2 public static DateTime UtcNow => 3 new DateTime((ulong) ((GetSystemTimeAsFileTime() + 0x701ce1722770000L) | 0x4000000000000000L)); 4 5 6
最后查阅GetSystemTimeAsFileTime()是Windows的API,作用便是获取当前的UTC时间