internal static TimeSpan CalculateUtcOffset(DateTime time, DaylightTime daylightTimes) {
if (daylightTimes==null) {
return TimeSpan.Zero;
}
DateTimeKind kind = time.Kind;
if (kind == DateTimeKind.Utc) {
return TimeSpan.Zero;
}
DateTime startTime;
DateTime endTime;
// startTime and endTime represent the period from either the start of DST to the end and includes the
// potentially overlapped times
startTime = daylightTimes.Start + daylightTimes.Delta;
endTime = daylightTimes.End;
// For normal time zones, the ambiguous hour is the last hour of daylight saving when you wind the
// clock back. It is theoretically possible to have a positive delta, (which would really be daylight
// reduction time), where you would have to wind the clock back in the begnning.
DateTime ambiguousStart;
DateTime ambiguousEnd;
if (daylightTimes.Delta.Ticks > 0) {
ambiguousStart = endTime - daylightTimes.Delta;
ambiguousEnd = endTime;
} else {
ambiguousStart = startTime;
ambiguousEnd = startTime - daylightTimes.Delta;
}
Boolean isDst = false;
if (startTime > endTime) {
// In southern hemisphere, the daylight saving time starts later in the year, and ends in the beginning of next year.
// Note, the summer in the southern hemisphere begins late in the year.
if (time >= startTime || time < endTime) {
isDst = true;
}
}
else if (time>=startTime && time < endTime) {
// In northern hemisphere, the daylight saving time starts in the middle of the year.
isDst = true;
}
// If this date was previously converted from a UTC date and we were able to detect that the local
// DateTime would be ambiguous, this data is stored in the DateTime to resolve this ambiguity.
if (isDst && time >= ambiguousStart && time < ambiguousEnd) {
isDst = time.IsAmbiguousDaylightSavingTime();
}
if (isDst) {
return daylightTimes.Delta;
}
return TimeSpan.Zero;
}
}