C#ConvertTimeFromUtc funkiness


C# ConvertTimeFromUtc funkiness

使用下面的代码,我正在尝试将此datetime字符串转换为Local datetime

1
2
3
4
5
6
7
private DateTime ConvertToLocalTime(string datetimestring)
{
    DateTime timeUtc = DateTime.Parse(datetimestring);
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
    return cstTime;
}

这是我得到的例外情况:

at System.TimeZoneInfo.ConvertTime(DateTime dateTime, TimeZoneInfo sourceTimeZone, TimeZoneInfo destinationTimeZone, TimeZoneInfoOptions flags, CachedData cachedData)
at System.TimeZoneInfo.ConvertTimeFromUtc(DateTime dateTime, TimeZoneInfo destinationTimeZone)

The conversion could not be completed because the supplied DateTime did not have the Kind
property set correctly. For example, when the Kind property is DateTimeKind.Local, the
source time zone must be TimeZoneInfo.Local.

ConvertTimeFromUtc的示例与我的代码完全相同,只是我将此字符串解析为timeUtc:
2017-01-23T05:00:00+00:00

如果我像这样打电话给Parse:

1
DateTime.Parse(datetimestring, null, System.Globalization.DateTimeStyles.RoundtripKind);

timeUtc.Kind.ToString()返回"本地"

那么,我该如何解决这个问题呢? 时间将发送给我UTC。


无论输入字符串中指定的区域如何,DateTime.Parse都会将结果转换为本地时间。 您必须明确指定您想要UTC结果,因为TimeZoneInfo.ConvertTimeFromUtc要求DateTime值为UTC类型。

1
2
3
4
5
6
7
private DateTime ConvertToLocalTime(string datetimestring)
{
    DateTime timeUtc = DateTime.Parse(datetimestring, null, System.Globalization.DateTimeStyles.AdjustToUniversal);
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
    return cstTime;
}


您必须添加DateTime.SpecifyKind

1
2
3
4
5
6
7
8
private static DateTime ConvertToLocalTime(string datetimestring)
{
    DateTime timeUtc = DateTime.Parse(datetimestring);
    var dt = DateTime.SpecifyKind(timeUtc, DateTimeKind.Utc);
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(dt, cstZone);
    return cstTime;
}

.net小提琴


如果您只想转换为本地日期时间并且您不需要偏移量,因为您的字符串具有偏移信息,DateTime.Parse将使用偏移信息并转换为本地日期时间。 那么你需要做的就是:

1
2
3
4
5
6
private static DateTime ConvertToLocalTime(string datetimestring)
{
    // Parses to local datetime
    // check the Kind property and you will see it has Local
    return DateTime.Parse(datetimestring);
}

如果您需要带有偏移量信息的本地日期时间,那么请查看DateTimeOffset,因为它是出于这个目的:

1
2
3
4
5
6
7
private static DateTimeOffset ConvertToLocalTime(string datetimestring)
{
    DateTime timeUtc = DateTime.Parse(datetimestring, null, DateTimeStyles.AdjustToUniversal);
    DateTimeOffset dateCst = new DateTimeOffset(timeUtc, TimeZoneInfo.Local.BaseUtcOffset);

    return dateCst;
}

如果您需要将utc datetime转换为其他时区而不是本地时区,请按以下方式指定:

1
2
3
4
5
6
7
8
private static DateTimeOffset ConvertToLocalTime(string datetimestring)
{
    DateTime timeUtc = DateTime.Parse(datetimestring, null, DateTimeStyles.AdjustToUniversal);
    TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
    DateTimeOffset dateCst = new DateTimeOffset(timeUtc, cstZone.GetUtcOffset(timeUtc));

    return dateCst;
}

这是文档:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//
// Summary:
//     Initializes a new instance of the System.DateTimeOffset structure using the specified
//     System.DateTime value and offset.
//
// Parameters:
//   dateTime:
//     A date and time.
//
//   offset:
//     The time's offset from Coordinated Universal Time (UTC).
//
// Exceptions:
//   T:System.ArgumentException:
//     dateTime.Kind equals System.DateTimeKind.Utc and offset does not equal zero.-or-dateTime.Kind
//     equals System.DateTimeKind.Local and offset does not equal the offset of the
//     system's local time zone.-or-offset is not specified in whole minutes.
//
//   T:System.ArgumentOutOfRangeException:
//     offset is less than -14 hours or greater than 14 hours.-or-System.DateTimeOffset.UtcDateTime
//     is less than System.DateTimeOffset.MinValue or greater than System.DateTimeOffset.MaxValue.