Как получить разницу во времени между тем которое прислал сервер и Date.now?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между временем сервера и клиента
Это практическая задача, которая часто возникает при работе с real-time функциями: чатами, таймерами, синхронизацией данных. Клиент и сервер могут иметь разные системные часы, и нужно это учитывать.
Проблема
Если просто сравнить Date.now() (время клиента) с временем сервера, получим неправильный результат. Причины:
- Системные часы на разных машинах могут различаться на несколько минут/часов
- Пользователь может специально или случайно изменить системное время
- Часовые пояса разные
Решение: получить offset
Стратегия: когда сервер отправляет время, мы вычисляем разницу между его временем и текущим Date.now(). Эту разницу сохраняем и используем для всех последующих вычислений.
Шаг 1: получить время сервера
// Запрашиваем текущее время у сервера
const response = await fetch('/api/time');
const data = await response.json();
const serverTime = new Date(data.timestamp).getTime(); // Время в миллисекундах
const clientTime = Date.now();
// Вычисляем offset (разницу)
const timeOffset = serverTime - clientTime;
// Сохраняем в localStorage или переменную
window.timeOffset = timeOffset;
Шаг 2: использовать это для получения текущего серверного времени
// Функция для получения текущего времени сервера в любой момент
function getServerTime() {
return Date.now() + window.timeOffset;
}
// Пример использования
console.log(getServerTime()); // Текущее время сервера
Полный пример
// API endpoint на сервере возвращает текущее время
// GET /api/time -> { "timestamp": "2026-04-02T12:30:45Z" }
class ServerTime {
constructor() {
this.offset = 0;
}
// Синхронизировать часы с сервером
async sync() {
const response = await fetch('/api/time');
const data = await response.json();
const serverTime = new Date(data.timestamp).getTime();
const clientTime = Date.now();
// offset = сколько миллисекунд отставляет/опережает клиент
this.offset = serverTime - clientTime;
console.log(`Синхронизация: offset = ${this.offset}ms`);
}
// Получить текущее время сервера
now() {
return Date.now() + this.offset;
}
// Получить дату сервера
getDate() {
return new Date(this.now());
}
}
// Использование
const serverTime = new ServerTime();
await serverTime.sync();
console.log(serverTime.now()); // Текущее время сервера в ms
console.log(serverTime.getDate()); // Текущая дата сервера
Практический пример: таймер обратного отсчёта
class CountdownTimer {
constructor(expiresAt, onExpire) {
this.expiresAt = new Date(expiresAt).getTime();
this.onExpire = onExpire;
this.intervalId = null;
}
// Получить оставшееся время (в секундах)
getRemainingSeconds() {
const remaining = this.expiresAt - (Date.now() + window.timeOffset);
return Math.max(0, Math.floor(remaining / 1000));
}
start() {
this.intervalId = setInterval(() => {
const remaining = this.getRemainingSeconds();
console.log(`Осталось: ${remaining}s`);
if (remaining <= 0) {
this.stop();
this.onExpire();
}
}, 1000);
}
stop() {
clearInterval(this.intervalId);
}
}
// Использование
// Сервер отправил: { "expiresAt": "2026-04-02T13:00:00Z" }
const timer = new CountdownTimer('2026-04-02T13:00:00Z', () => {
console.log('Время истекло!');
});
timer.start();
Повторная синхронизация
Ответ пользователя может развивать проект долгое время. Часы дрейфуют (медленно разбегаются). Периодически пересинхронизируй:
// Синхронизировать каждые 5 минут
setInterval(() => {
serverTime.sync();
}, 5 * 60 * 1000);
Обработка задержки сети
Для более точной синхронизации можно учесть задержку сети (latency):
async function syncWithLatency() {
const clientTime1 = Date.now();
const response = await fetch('/api/time');
const clientTime2 = Date.now();
const data = await response.json();
const serverTime = new Date(data.timestamp).getTime();
// Предполагаем, что сервер ответил в середине этого времени
const latency = (clientTime2 - clientTime1) / 2;
const estimatedServerTime = serverTime + latency;
window.timeOffset = estimatedServerTime - clientTime2;
}
Когда это нужно
- Таймеры и countdown — для аукционов, сессий
- Real-time синхронизация — чаты, совместное редактирование
- Истечение токенов — проверка, не истёк ли JWT
- Оптимистичные обновления — когда нужно знать точное время
Заключение
Три шага:
- Запроси время у сервера:
GET /api/time - Вычисли разницу:
offset = serverTime - Date.now() - Используй:
getServerTime() = Date.now() + offset
Периодически пересинхронизируй для компенсации дрейфа часов.