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

для чтения! Дайте мне знать ваши мысли или прошлый опыт по управлению часовыми поясами. 😄