2015-04-10 2 views
4

У меня есть строка времени UTC (которую я получаю из базы данных, поэтому я не могу изменить формат), который создается с помощью DateTime.UtcNow.ToString("s"). Я хотел бы показать что-то пользовательское, похожее на «10:00 AM». Где я (в Англии), часы недавно пошел вперед, и следующий способ час из:Почему DateTime.ToLocalTime() не учитывает летнее время?

var timenowstring = DateTime.UtcNow.ToString("s"); 
var dateutc = DateTime.Parse(timenowstring).ToShortTimeString(); 
var datelocal = DateTime.Parse(timenowstring).ToLocalTime().ToShortTimeString(); 

Console.WriteLine("Utc time string: " + dateutc); 
Console.WriteLine("Local time string: " + datelocal); 

И печать «9:02 AM», когда на самом деле это 10:02 PM.

Вот скриншот этого репро-ки на http://csharppad.com/:

utc and local show the same time - see system clock in lower right, which is correct bigger image

CSharpPad gist

Что я делаю не так и то, что это самый простой способ, чтобы получить объект DateTime, который возвращает Правильное время, когда я звоню .ToShortTimeString()?

NB the docs on ToLocalTime() говорят:

Преобразование также учитывает летнее время правила, которое применяется ко времени, представленного текущим объектом DateTime.

+0

Возможный дубликат [Почему не может DateTime.Parse parse UTC date] (http://stackoverflow.com/questions/1756639/why-cant-datetime-parse-parse-utc-date) – rdans

ответ

7

Вы сказали:

У меня есть время 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. Он не знает, что вы хотите использовать правила часовых поясов Англии.

CSharpPad Time Zone

Если вы собираетесь запустить свой код на сервере, то вы не должны использовать 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(); 
0

Когда я запускаю свой код локально, он дает ожидается результаты (местное время соответствует местному времени моей машины). Хотя, когда я запускаю его на http://csharppad.com, время такое же. Причина упоминается в ответе Мэтта Джонсона: у серверов есть разные часовые пояса от местных машин.

Смежные вопросы