Иногда бывает очень красиво хранить время на сервере в 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
Конечно по этим данным нельзя однозначно определить временную зону клиента, так как среди них много пересечений в настоящее время, но есть расхождение в прошлом. Тем не менее если использовать их для автоматической конвертации времени, то этого вполне достаточно.