Actually the difference between the two.
In .NET 3.5 and below , Datetime.ToUniversalTime implemented as:
public DateTime ToUniversalTime() { return TimeZone.CurrentTimeZone.ToUniversalTime(this); }
Since he used the TimeZone class, he suffered the same problems that were mentioned in MSDN docs :
The TimeZone class supports only one rule of daylight saving time adjustment for the local time zone. As a result, the TimeZone class can accurately report TimeZone time information or convert between GMT and local time only for the period in which the last adjustment rule applies. In contrast, the TimeZoneInfo class supports several configuration rules, which allows you to work with historical time zone data.
In .NET 4.0 and later , Datetime.ToUniversalTime is implemented as:
public DateTime ToUniversalTime() { return TimeZoneInfo.ConvertTimeToUtc(this, TimeZoneInfoOptions.NoThrowOnInvalidTime); }
This fixes the lack of support for historical adjustment rules, but because of the NoThrowOnInvalidTime flag NoThrowOnInvalidTime this is not the same as calling TimeZoneInfo.ConvertimeToUtc .
The method that it calls is the internal ConvertTimeToUtc overload, which accepts the TimeZoneInfoOptions flag. The public version of the method uses TimeZoneInfoOptions.None , while in this case it uses TimeZoneInfoOptions.NoThrowOnInvalidTime .
The difference can be illustrated as follows. If the time zone is set to US Pacific Time:
DateTime dt = new DateTime(2015, 3, 8, 2, 0, 0, DateTimeKind.Local); DateTime utc = dt.ToUniversalTime(); Console.WriteLine(utc); // "3/8/2015 10:00:00 AM"
Vs:
DateTime dt = new DateTime(2015, 3, 8, 2, 0, 0, DateTimeKind.Local); DateTime utc = TimeZoneInfo.ConvertTimeToUtc(dt);
Since on this date in this time zone, the time is scanned from 1:59:59 to 3:00:00, the delivery time of 2:00:00 is not valid. The right thing is to make an exception (as in the second case). However, since the existing Datetime.ToUniversalTime contract from earlier versions of the framework did not allow this, the structure decides to return the value instead of the metalization.
The selected value is calculated using the standard time offset, as if the DST transition was not performed.