пятница, декабря 01, 2006

Проблема TimeZone при использовании web сервисов ASP.NET 1.1

Сразу оговорюсь, что все ужасы, о которых пойдет речь, имеют место только в .NET Framework 1. . Так вот, если ваш web сервис предает или принимает в своих сообщениях данные типа DateTime, то вы можете недосчитаться в них часов. Или наоборот, найдете там лишние часы. Происходит это следующим образом.


Предположим у нас есть web сервис с вот таким методом



[WebMethod]
public Report GetReport(DateTime from, DateTime to)
{
//…
}

И вот клиент вызывает его следующим образом



Report rep = service.GetReport(new DateTime(2006, 12, 1), new DateTime(2006, 12, 2));

Если этот клиент находится где-то неподалеку, то все будет Ok. А вот если он будет достаточно далеко на восток, настолько далеко, чтобы быть в следующей часовой зоне по сравнению с нами, то знаете, что мы получим на сервере? В первом параметре будет дата 31 ноября 2006 года, а во втором 1 декабря 2006 года. И знаете почему? Виноват SOAP форматер, который считает себя самым умным. При сериализации наших параметров типа DateTime он добавляет информацию о локальной временной зоне (заметьте, его об этом никто не просил). При десериализации на сервере, SOAP форматер видит, что временная зона в пришедшей дате больше чем локальная, и корректирует значение даты, выбрасывая «лишний» час. В результате оба наши параметра перескочили на один день назад! Причем полученные на сервере даты не несут никакой информации о временных зонах! Восстановить реальные значения уже нельзя.


Выход только один. На клиенте перед передачей преобразовывать все даты к локальному времени, а на сервере, после приема к универсальному.



// клиент
Report rep = service.GetReport(new DateTime(2006, 12, 1).ToLocalTime(),
new DateTime(2006, 12, 2).ToLocalTime());

// сервер
[WebMethod]
public Report GetReport(DateTime from, DateTime to)
{
from = from.ToUniversalTime();
to = to.ToUniversalTime();
//…
}


Комментариев нет: