Во-первых, я бы не назвал вашу функцию GetUtcDateTime
, потому что это не то, что она делает. Он пытается получить DateTimeOffset
для определенного часового пояса за определенное время, поэтому назовите его как GetDateTimeOffset
.
Основная концепция, которую вам не хватает в вашем коде, заключается в том, что DateTime
имеет свойство .Kind
, которое устанавливает значение DateTimeKind
. Вид учитывается несколькими местами в вашем коде:
GetUtcOffset
преобразует Utc
или Local
видов в указанную зону до определения смещения.
new DateTimeOffset
(конструктор) выдаст ошибку, если тип и смещение конфликтуют, если вы предоставите смещение.
Когда вы присваиваете DateTime
для DateTimeOffset
, неявное преобразование оценивает тип.
Когда вы звоните .DateTime
из DateTimeOffset
, вид будет всегда быть Unspecified
- независимо от смещения.
Если вы примете все это во внимание, вы поймете, что вам нужно самостоятельно проверить тип, прежде чем звонить GetUtcOffset
. Если это , а не Unspecified
, вам нужно преобразовать его в указанный часовой пояс, прежде чем получить смещение.
public static DateTimeOffset GetDateTimeOffset(DateTime sourceDateTime, string timeZoneId)
{
TimeZoneInfo timeZone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId);
// here, is where you need to convert
if (sourceDateTime.Kind != DateTimeKind.Unspecified)
sourceDateTime = TimeZoneInfo.ConvertTime(sourceDateTime, timeZone);
TimeSpan offset = timeZone.GetUtcOffset(sourceDateTime);
return new DateTimeOffset(sourceDateTime, offset);
}
Теперь, когда это решено, перейдите к следующему набору проблем, где вы его и называете.
DateTimeOffset utcDate = (DateTime.UtcNow);
DateTime fromUtc = utcDate.DateTime;
В строке 1 неявное приведение от DateTime
до DateTimeOffset
устанавливает смещение на 00:00
- потому что DateTime.UtcNow
имеет .Kind == DateTimeKind.Utc
.
В строке 2 вызов свойства .DateTime
устанавливает fromUtc.Kind == DateTimeKind.Unspecified
. По сути, вы отстранены от вида.
Так что вместо этого просто передайте DateTime.UtcNow
непосредственно в функцию. Тип сохранится, и все будет работать - теперь, когда Kind
распознан и преобразование происходит внутри функции.
С учетом всего сказанного, если все ваши исходные значения равны DateTimeOffset
(например, DateTimeOffset.UtcNow
), тогда вам вообще не нужна эта функция. Просто позвоните TimeZoneInfo.ConvertTime
с DateTimeOffset
напрямую.