Вы сказали:
У меня есть время UTC строка (что я получаю из базы данных, так что я не могу изменить формат), который создается с DateTime.UtcNow.ToString("s")
.
С самого начала, у вас есть проблема. Даты в базе данных (обычно) не сохраняются в виде строк. Они хранятся в полях с определенным типом данных. В SQL Server (например) вы можете использовать поле datetime
или datetime2
. Это не строки. Когда вы извлекаете их в свой код .NET, они преобразуются непосредственно в тип DateTime
. Если вы рассматриваете его как строку, вы делаете это неправильно.
Например, код доступа к данным может делать что-то вроде этого:
DateTime dt = Convert.ToDateTime(dataReader["myDateTimeField"].ToString());
Это является очень распространенным явлением, и совершенно неправильно. Вы должны вместо этого делать:
DateTime dt = (DateTime) dataReader["myDateTimeField"];
Или, если поле обнуляемым:
DateTime? dt = dataReader["myDateTimeField"] as DateTime;
После того, как вы загрузите значение правильно, а не разбор его в виде строки, остальное будет работать хорошо. Значение DateTime
будет иметь DateTimeKind.Unspecified
за его имущество Kind
, а при звонке ToLocalTime
на нем предполагается, что вы хотите обрабатывать неопределенное значение в качестве UTC. (. See the chart on MSDN)
Что касается кода, который размещен, в то время как это немного грязный (идущий через строки без необходимости), это будет на самом деле прекрасно работать - если вы запускали его в вашего часового пояса. В методе ToLocalTime
«местный» означает местное задание часового пояса машины, где бы ни работал код.Для csharppad.com часовым поясом происходит UTC. Он не знает, что вы хотите использовать правила часовых поясов Англии.
Если вы собираетесь запустить свой код на сервере, то вы не должны использовать ToLocalTime
на всех - как часовой пояс сервера, вероятно, будет неуместным. Вместо этого, вы можете использовать TimeZoneInfo
для преобразования времени:
// this uses the time zone for England
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById("GMT Standard Time");
DateTime englandDatetime = TimeZoneInfo.ConvertTimeFromUtc(utcDateTime, tz);
В качестве альтернативы можно использовать библиотеку с открытым исходным кодом Noda Time, как это:
DateTimeZone tz = DateTimeZoneProviders.Tzdb["Europe/London"];
DateTime englandDateTime = Instant.FromDateTimeUtc(utcDateTime)
.InZone(tz)
.ToDateTimeUnspecified();
Возможный дубликат [Почему не может DateTime.Parse parse UTC date] (http://stackoverflow.com/questions/1756639/why-cant-datetime-parse-parse-utc-date) – rdans