Примерно 4 года назад я следовал рекомендациям по использованию Статья MSDN для DateTime для создания клиента .Net на веб-сервисах .Net 1.1 и ASMX (с сервером SQL 2000 в качестве бэкэнда). Я до сих пор помню проблемы сериализации, которые у меня были с DateTime, и усилия по тестированию серверов в разных часовых поясах.
Мои вопросы таковы: существует ли аналогичный документ с лучшими практиками для некоторых новых технологий, таких как WCF и SQL server 2008, особенно с добавлением новых типов datetime для хранения информации о часовом поясе.
Это среда:
Любые хорошие предложения / лучшие практики для типов данных, которые будут использоваться на каждом уровне?





Я думаю, что лучший способ сделать это - всегда передавать объект как UTC и конвертировать в местное время на клиентах. Таким образом, все клиенты получают общую точку отсчета.
Чтобы преобразовать в UTC, вызовите ToUniversalTime для объекта DateTime. Затем на клиентах вызовите ToLocalTime, чтобы получить его в их текущем часовом поясе.
Мне повезло, что я просто сохранил тип данных DateTime и всегда сохранял его как GMT. В каждом слое я бы настроил значение GMT на локальное значение для слоя.
Пока ваш уровень веб-сервисов и уровень клиента используют тип .NET DateTime, он должен правильно сериализоваться и десериализоваться как стандартная локальная дата / время SOAP с информацией о часовом поясе, например:
2008-09-15T13: 14: 36.9502109-05: 00
Если вы абсолютно точно должны знать сам часовой пояс (т.е.вышеупомянутое может быть восточно-стандартное время или центральное летнее время), вам необходимо создать свой собственный тип данных, который представляет эти части как таковые:
[Serializable]
public sealed class MyDateTime
{
public MyDateTime()
{
this.Now = DateTime.Now;
this.IsDaylightSavingTime = this.Now.IsDaylightSavingTime();
this.TimeZone = this.IsDaylightSavingTime
? System.TimeZone.CurrentTimeZone.DaylightName
: System.TimeZone.CurrentTimeZone.StandardName;
}
public DateTime Now
{
get;
set;
}
public string TimeZone
{
get;
set;
}
public bool IsDaylightSavingTime
{
get;
set;
}
}
тогда ваш ответ будет выглядеть так:
<Now>2008-09-15T13:34:08.0039447-05:00</Now>
<TimeZone>Central Daylight Time</TimeZone>
<IsDaylightSavingTime>true</IsDaylightSavingTime>
Вот как теперь работает WCF. Я не получаю ничего с указанием часового пояса (например, -05: 00).
UTC / GMT будет согласованным в распределенной среде.
Важным моментом является указание datetimeKind после заполнения вашего свойства DateTime значением из базы данных.
dateTimeValueUtcKind = DateTime.SpecifyKind(dateTimeValue, DateTimeKind.Utc);
Одна большая проблема заключается в том, что сериализация WCF не поддерживает xs: Date. Это большая проблема, так как если все, что вам нужно, это свидание, вам не следует беспокоиться о часовых поясах. В следующей проблеме подключения обсуждаются некоторые из проблем: http://connect.microsoft.com/wcf/feedback/ViewFeedback.aspx?FeedbackID=349215
Если вы хотите однозначно представить момент времени, то есть не только дату, вы можете использовать класс DateTimeOffset, если у вас есть .NET 3.5 как на клиенте, так и на сервере. Или для обеспечения совместимости всегда передавайте значения даты и времени в формате UTC.
Если вы хотите использовать DateTimeOffset и WCF, эти две статьи могут быть полезны при возникновении проблем с сериализацией: msdn.microsoft.com/en-us/library/ms730167(v=VS.90).aspxblogs.msdn.com/b/drnick/archive/2008/09/04/…
по состоянию на 28.03.2013 ссылка в посте Джо не работает.
В случаях, когда объект datetime должен оставаться неизменным, используйте JsonConvert:
DateTime now = DateTime.Now;
string json = JsonConvert.SerializeObject(now);
DateTime nowJson = JsonConvert.DeserializeObject<DateTime>(json);
Обратите внимание, что клиент получит тип datetime как
Unspecified. Когда вы вызываете на немToUniversalTime, он будет предполагатьLocaltime и фактически выполнит преобразование. Правильный способ - использоватьDateTime.SpecifyKind(myUtcTime, DateTimeKind.Utc)вместоToUniversalTime.