Ошибка DateTimeOffset: смещение UTC локального dateTime не соответствует аргументу смещения

Я пытаюсь создать небольшой метод, который преобразует время из одного часового пояса в другой. Я думал, что это будет достаточно просто, но когда я развернуть его, я получаю эту ошибку The UTC Offset of the local dateTime parameter does not match the offset argument. Я предполагаю, что это потому, что сервер не находится в том же часовом поясе, что и пользователь, что не полезно, Так как это будет использоваться со всего мира.

public object ConvertDate(DateTime inputTime, string fromOffset, string toZone)
{
    var fromTimeOffset = new TimeSpan(0, - int.Parse(fromOffset), 0);
    var to = TimeZoneInfo.FindSystemTimeZoneById(toZone);
    var offset = new DateTimeOffset(inputTime, fromTimeOffset);
    var destination = TimeZoneInfo.ConvertTime(offset, to); 
    return destination.DateTime;
}

здесь fromOffset - это число, преобразованное в timespan из часового пояса пользователей и toZone - это название зоны, в которую мы переходим. Этот ошибка в этой строке var offset = new DateTimeOffset(inputTime, fromTimeOffset);

есть идеи о том, как заставить это работать?

2 ответов


посмотреть документация для почему исключение бросается:

ArgumentException: dateTime.Kind равна Local и offset не равно смещению локального часового пояса системы.

на


вот метод расширения, который я использую, чтобы обойти это невероятно разочаровывающее рамочное решение. См. Примечания, лучший и наиболее эффективный способ справиться с этим-использовать конструктор тиков DateTimeOffset, вместо того, чтобы выделять другое промежуточное DateTime просто изменить это Kind собственность.

    /// <summary>
    /// Converts a DateTime to a DateTimeOffset, without risking any onerous exceptions
    /// the framework quite unfortunately throws within the DateTimeOffset constructor, 
    /// such as they do when the source DateTime's Kind is not set to UTC. The best and 
    /// most performant way around this, which we do herein, is to simply construct the 
    /// new DateTimeOffset with the overload that excepts Ticks. Also, we will simply 
    /// return <see cref="DateTimeOffset.MinValue"/> if the source DateTime was 
    /// <see cref="DateTime.MinValue"/>.
    /// </summary>
    /// <param name="dt">Source DateTime.</param>
    /// <param name="offset">Offset</param>
    public static DateTimeOffset ToDateTimeOffset(this DateTime dt, TimeSpan offset)
    {
        // adding negative offset to a min-datetime will throw, this is a 
        // sufficient catch. Note however that a DateTime of just a few hours can still throw
        if (dt == DateTime.MinValue)
            return DateTimeOffset.MinValue;

        return new DateTimeOffset(dt.Ticks, offset);
    }

    public static DateTimeOffset ToDateTimeOffset(this DateTime dt, double offsetInHours = 0)
        => ToDateTimeOffset(dt, offsetInHours == 0 ? TimeSpan.Zero : TimeSpan.FromHours(offsetInHours));