
Что-то, что мне недавно было трудно понять, это то, как работают часовые пояса. Это одна из тех вещей, которые вы склонны избегать, насколько это возможно, однако я понял, что на моем веб-сайте Revisify есть довольно большой недостаток, который необходимо устранить.
Для тех из вас, кто не знает, Revisify — это инструмент, который я создал, чтобы помочь студентам учиться. Студенты могут создавать вопросы, проверять себя и прогрессировать. У меня есть одна доступная функция — полосы обучения, которые подсчитывают количество дней, в течение которых студент учился подряд.

Теперь это должно быть довольно просто запрограммировать, верно? Я сохранил все даты/время, когда студент проверял себя в базе данных, теперь все, что мне нужно сделать, это получить сегодняшнюю дату и работать в обратном направлении через базу данных, проверить, есть ли вчерашняя дата, и если да, проверить предыдущий день дату и продолжайте до тех пор, пока одна из дат не станет доступной. Однако я забыл о том, что это не сработает для студентов, которые живут в часовом поясе, отличном от GMT. Почему? Потому что сервер находится в Великобритании. Я запрограммировал сервер так, что каждый раз, когда студент тестирует себя, сервер получает дату/время сервера и записывает их в базу данных.
Всемирное координированное время
Я обнаружил, что существует такое понятие, как Всемирное координированное время (UTC). Не спрашивайте меня, почему его не сокращают до UTC вместо CUT, почему вы можете прочитать здесь. UTC в основном является глобальным стандартом для часовых поясов и имеет то же время, что и GMT.
- Время в Великобритании, представленное в UTC, будет просто UTC+00:00, потому что, как я уже сказал, время UTC совпадает с GMT.
- Если бы нам нужно было время в Австралии, оно было бы представлено как UTC+09:30, так как оно на 9 часов и 30 минут опережает время в Великобритании.
- Время на Гавайях будет UTC-10:00, так как оно на 10 часов отстает от времени в Великобритании.
Работа с сервером UTC
Итак, вернемся к Revisify. Зная это, если бы мы сохранили дату/время в формате UTC+00:00, мы могли бы затем преобразовать это в местное время местонахождения студента. К счастью, поскольку у меня есть только 1 сервер, который находится в Великобритании, даты в базе данных уже указаны в формате UTC+00:00. Однако мне все еще нужно было изменить некоторый код Python на сервере:
from datetime import datetime # This gets the server time. If I moved the server to say Australia, it would not get UTC time. date = datetime.now() # This gets UTC time regardless of where the server is located. date = datetime.utcnow()
Работа с клиентской стороной UTC
Теперь, когда я официально сохраняю дату/время в формате UTC в базе данных, мне нужно правильно преобразовать их в местное время учащегося. Это может быть сложно запрограммировать самостоятельно, но, к счастью, есть фантастическая библиотека Javascript под названием Moment.js, которая снимает много усилий по преобразованию часовых поясов. Вот как легко мне было преобразовать дату/время UTC, которые я получил из базы данных, в местное время компьютера ученика:
// Server's UTC datetime var utcDate = '2016-12-20 14:56:51'; // Client's local datetime var localDate = moment.utc(utcDate).local();
Эта простая строка кода — все, что нужно клиенту, чтобы получить правильную дату. В этой библиотеке гораздо больше функций, но я оставлю это на другой раз.
Вернувшись к полосе исследований, я обновил код, чтобы сервер отправлял даты, а некоторый Javascript на стороне клиента вычислял полосу учебы. Окончательный результат доступен здесь с некоторыми пояснениями о том, как это работает. Вы также можете увидеть это ниже:
// Values for dates are received from the server
dates = [];
for (i=0; i <= dates.length-1; i++) {
var date = date[i];
var localDate = moment.utc(date).local().format('DDMMYY');
if (i === 0) {
var today = moment().format('DDMMYY');
var yesterday = moment().format('DDMMYY');
if (localDate === today) ||
localDate === yesterday) {
streak += 1;
}
}
else {
var previousDate = moment.utc(dates[i-1]).local().format('DDMMYY');
var previousDateYesterday = moment.utc(dates[i-1]).local().subtract(1, 'days').format('DDMMYY');
if (localDate !== previousDate) {
if (localDate === previousDateYesterday) {
streak += 1;
}
else {
break;
}
}
}
}
Вот оно. Я обнаружил, что теперь, когда я использовал часовые пояса один раз, это не так сложно, но все же несколько сбивает с толку, если я думаю об этом слишком подробно.
Если вы действительно хотите растопить свой мозг, это видео Тома Скотта на YouTube объясняет часовые пояса гораздо более подробно, наслаждайтесь (или нет).
Этот пост доступен в моем блоге: The Timezone Struggle
для чтения! Дайте мне знать ваши мысли или прошлый опыт по управлению часовыми поясами. 😄