Иногда бывает очень красиво хранить время на сервере в UTC и преобразовывать его в локальное время пользователя при выдаче страницы. По крайней мере такая задача встала в проекте, в котором я участвую. Перевод из utc в локальное время задача непростая, но по нему достаточно много информации и опубликованных алгоритмов. Все что для них нужно это данные о временной зоне клиента, но как оказалось информации об этом как раз не так уж и много.
Все опубликованное ниже результаты собственных наработок
Вот что мы имеем в итоге исполнения этого кода. На выходе у нас получается два массива dlt и std. Первый содержит данные о точке перехода на летнее время, второй на стандартное. Первым элементом каждого массива идет timestamp точки перехода в локальном времени, второй смещенние относительно GMT после перехода. Если в временной зоне клиента нет перехода на летнее время, то первые элементы обоих массивов будут равны нулю, а вторые смещению временной зоны по GMT
Конечно по этим данным нельзя однозначно определить временную зону клиента, так как среди них много пересечений в настоящее время, но есть расхождение в прошлом. Тем не менее если использовать их для автоматической конвертации времени, то этого вполне достаточно.
Все опубликованное ниже результаты собственных наработок
var now = new Date();
function СheckDLT(sm, em)
{
return ((new Date(em)).getTimezoneOffset() - (new Date(sm)).getTimezoneOffset());
}
function getTZLowerBound( start, end, cmp )
{
var nstart, count, count2;
count = end - start;
while(count>0)
{
end = start + count;
nstart = start + ( count2 = Math.floor(count / 2) );
if ( cmp(СheckDLT(nstart,end)) )
{
start = nstart + 1;
count -= count2 + 1;
}
else
count = count2;
}
return [start, -(new Date(start)).getTimezoneOffset()];
}
var dlt = Date.UTC(now.getFullYear(), 0, 1, 0, 0, 0, 0),
std = Date.UTC(now.getFullYear(), 6, 1, 0, 0, 0, 0);
if(СheckDLT(dlt,std))
{
dlt = getTZLowerBound(dlt,std, function (b) {return (b<0)});
std = getTZLowerBound(Date.UTC(now.getFullYear(), 6, 1, 0, 0, 0, 0),
Date.UTC(now.getFullYear(), 11, 1, 0, 0, 0, 0),
function (b) {return (b>0)});
dlt[0] = dlt[0] + std[1]*60000;
std[0] = std[0] + dlt[1]*60000;
}
else
std = dlt = [0,-now.getTimezoneOffset()];
Вот что мы имеем в итоге исполнения этого кода. На выходе у нас получается два массива dlt и std. Первый содержит данные о точке перехода на летнее время, второй на стандартное. Первым элементом каждого массива идет timestamp точки перехода в локальном времени, второй смещенние относительно GMT после перехода. Если в временной зоне клиента нет перехода на летнее время, то первые элементы обоих массивов будут равны нулю, а вторые смещению временной зоны по GMT
Конечно по этим данным нельзя однозначно определить временную зону клиента, так как среди них много пересечений в настоящее время, но есть расхождение в прошлом. Тем не менее если использовать их для автоматической конвертации времени, то этого вполне достаточно.