Дата и время в веб-приложениях

Одна из самых замороченных задач - обработка даты-времени и представление и хранение их с учетом локального формата. В PHP решения представлены, на мой взгляд, крайне коряво. Попробуйте разобраться в time, mktime, strtotime  и иже с ними. Однако, задача очень элегантно решается при помощи MooTools и его расширения к нативному JavaScript-объекту Date.

 

Основное решение

Суть: браузер уже имеет встроенный объект типа Date. Нам осталось только отформатировать его для пользователя, а на сервер передаем данные в нужном формате: или timestamp или database. В обратной последовательности - с сервера принимаем timestamp или database, преобразовываем в экземпляр класса Date, форматируем, как нам угодно. 

Пример:

HTML

 

<input id="myDate" type="text" value=""> <!-- сюда будем писать данные -->

 

JavaScript

 
window.addEvent('load',function(){ //После загрузки страницы 
    var curDate = new Date(); //создаем новый объект типа Date. По умолчанию - текущая дата. 
    $('myDate').value = curDate.format('%d.%m.%Y'); // В инпут записываем дату в нужном нам формате 
    $('myDate').store('curDate',curDate); // Интересный метод store, который позволяет сохранить в DOM-узле любую информацию. Записываем туда неформатированный объект целиком 
}); 

Теперь можем делать все, что захотим.

Например, передать на сервер посредством AJAX в формате database, который прекрасно понимает и парсит php:

 
var myAjax = new Request.JSON({ 
    url:'myPHP.php', 
    method:'post', 
    data:{ 
        dateDB:$('myDate').retrieve('curDate').format('db'),//Здесь передается строка вида 'YYYY-mm-dd'. Ошибки при разборе на сервере исключены. 
        dateTimestamp:$('myDate').retrieve('curDate').format('%s')//А здесь - просто timestamp, вообще беспроигрышный вариант. 
    }, 
    onSuccess:function(jsn){ 
 
    //Здесь обрабатываем ответ сервера, если он есть 
 
    } 
 
}).send(); 

Обратные преобразования выполняются так же просто. Лучше всего, конечно, получать данные также в формате timestamp или db. При этом, если мы получаем данные в формате DB, то разбор выглядит так:

 

var myDateFromServer = "2013-08-21 20:20:08";//Здесь дата, полученная с сервера.

 

var myDate = new Date.parse(myDateFromServer); //Преобразовываем строку в объект Data. Теперь точно не потеряемся в форматировании, и не поменяем число и месяц местами, например.

 

Если же нам удобен для хранения timestamp, то преобразование такое:

 

var myDateFromServer = "1377102008"; //Например, с сервера пришла строка.

 

var myDate = new Date(myDateFromServer.toInt()*1000);//Приводим к int, выражаем в миллисекундах и, "Вуаля!!!", просто передаем полученное число как параметр при создании экземпляра класса Date.

 

Результат тот же, что и в предыдущем случае. 

 

Что примечательно, в случае использования связки Date+myElement.store() в качестве элемента для хранения и представления данных можно использовать не только input, но и span, div, p и вообще любой элемент DOM. 

 

Поясню идею еще раз: сервер отвечает за хранение даты, и, при необходимости, за ее генерацию в виде timestamp или db. Это нужно, чтобы не зависеть от установок времени на машине-клиенте. Клиент обрабатывает данные и представляет их пользователю в необходимом формате. Также на клиенте может временно сохраняться обрабатываемая дата. Можно в отдельной переменной, а можно прямо в DOM-узле, который отвечает за визуальное отображение. Таким образом, серверу все равно, в каком виде будет представлена дата пользователю, он обеспечивает точность и единообразие хранения и создания, а также синхронизированность операций со временной меткой для всех пользователей. А клиент, в свою очередь, заботится только о представлении данных. 

Какие паттерны можно использовать для представления:

  • %a -  день сокращенно ("Mon", "Tue")
  • %A - день полностью ("Monday")
  • %b - месяц сокращенно ("Jan", "Feb")
  • %B - месяц полностью ("January")
  • %c - полная дата в строку ("Mon Dec 10 14:35:42 2007"; %a %b %d %H:%m:%S %Y)
  • %d - число месяца, с ведущим 0 (01, 05, etc)
  • %e - число месяца, без ведущего 0 (1, 5, 12, etc)
  • %H - часы, с ведущим 0 (24-ч формат) (00, 11, 14, etc)
  • %I - часы,  с ведущим 0 (12-ч формат)
  • %j - день года, три цифры (от 001 до 366)
  • %k - часы,  без ведущего 0 (24-ч формат)
  • %l - часы, без ведущего0 (12-ч формат)
  • %L - миллисекунды, 3 цифры с ведущими нулями ( "081")
  • %m - номер месяца, с ведущим 0 (01 - Jan, 12 - Dec)
  • %M - минуты, с ведущим 0 (01, 40, 59)
  • %o - сокращение для числа месяца ("st" for the 1st, "nd" for the 2nd, etc.)
  • %p - эквивалент AM или PM для текущего языка
  • %s - the Unix Epoch Time timestamp
  • %S - секунды, с ведущим 0 (01, 40, 59)
  • %T - время в формате %H:%M:%S
  • %U - номер недели в году с ведущим 0 (01 is the week of Jan 1, 52 is the week of Dec 31)
  • %w - номер дня в неделе. Внимание! Нумерация ведется, как это принято в США (0 is Sunday, 1 is Monday)
  • %x - полная дата, отформатированная c учетом текущей локали: en-US -  %m/%d/%Y (12/10/2007) ru-RU - %m.%d.%Y
  • %X - время часы и минуты, отформатированные с учетом текущей локали. en-US: %I:%M%p (02:45PM) ru-RU - %H:%M
  • %y - год, две цифры ( "07")
  • %Y - год, четыре цифры. Летоисчисление от Р.Х. (four digits; "2007")
  • %z - сдвиг GMT ("-0800")
  • %Z - временная зона ("GMT")
  • % - возвращает знак % (%y%% = 07%)

 

Рекомендую обратить внимание на %x, %X  - очень помогает именно в локализации приложения. Для использования локализаций должна быть подгружена библиотека mootools-more с необходимыми локалями.

Для большего удобства в MooTools имеются готовые сокращения:

  • db - "%Y-%m-%d %H:%M:%S",
  • compact - "%Y%m%dT%H%M%S",
  • iso8601 - "%Y-%m-%dT%H:%M:%S%z",
  • rfc822 - "%a, %d %b %Y %H:%M:%S %Z",
  • rfc2822 - "%a, %d %b %Y %H:%M:%S %z",
  • short - "%d %b %H:%M",
  • long - "%B %d, %Y %H:%M"

Внимание! сокращения записываются без знака "%". т.е. myDate.format('db')

Что еще можно делать с датой-временем:

 myDate.clearTime() - сбрасывает время в 00:00

 

myDate.increment(string what, int) - очень полезная функция, позволяет увеличить значение myDate на нужное количество секунд, минут, часов, дней, недель,  месяцев или лет. Первый аргумент, - единица времени, т.е. на что увеличиваем (по умолчанию 'day'), второй на сколько увеличиваем (по умолчанию 1). В качестве первого аргумента может быть:

  • second
  • minute
  • hour
  • day
  • week
  • month
  • year

 

myDate.decrement(string what, int) - то же самое, только, соответственно, уменьшение.

 

(int) myDate.diff(otherDate[, string resolution]) - разница между двумя датами, второй параметр - в каких единицах. Возможные значения как и в increment/decrement.

 

(mixed) myDate.get(string what) - позволяет получить из даты массу полезных сведений:

  • 'timezone' - временная зона, например "GMT"
  • 'gmtoffset' - сдвиг временной зоны
  • 'week' - номер недели в году
  • 'ordinal' - сокращение для числа -('th', 'st', 'nd', etc)
  • 'dayofyear' - номер дня в году
  • 'lastdayofmonth' - последний день месяца

 

(bool) myDate.isLeapYear() - позволяет узнать, находится ли дата в високосном году


Редко используемые, но полезные (для конченных гиков)

myDate.defineFormat('time', '%H:%M');  - позволяет задать собственное сокращение для паттерна формата, в качестве второго аргумента может быть функция.

             myDate().format('time'); //17:30  

             myDate.defineFormat('timeago', function(date){ var now = Date.now(); return Math.round((now - date) / (1000 * 60)) + ' minutes ago'; });

 

myDate.defineFormats(object) - то же самое, но принимает объект, соотвестственно, позволяет определить сразу несколько сокращений.

 

и даже есть возможность задать такое:

 

myDate.define2DigitYearStart(number) - принимает число (год, четырехзначное), устанавливает этот год в качестве начального для вычисления двузначных лет.

 

В общем, как всегда, мощный и удобный инструмент получился у команды MooTools.

Добавить комментарий


Защитный код
Обновить