Javascript-форум (https://javascript.ru/forum/)
-   Элементы интерфейса (https://javascript.ru/forum/dom-window/)
-   -   Вывести количество часов и минут до рабочего времени (https://javascript.ru/forum/dom-window/55288-vyvesti-kolichestvo-chasov-i-minut-do-rabochego-vremeni.html)

Sigizmund2012 21.04.2015 18:30

Вывести количество часов и минут до рабочего времени
 
Здравствуйте. На сайте есть форма "Заказать обратный звонок". Если время нерабочее, нужно показать пользователю что-то типа "Мы перезвоним вам через 11 часов 18 мин". Вот код:
var sTime,
		hours,
		minutes;
		$.ajax({
			url: "/sendmailforms/time.php",
			cache: false,
			success: function(data){
				sTime = new Date(data);
				hours = sTime.getHours();
				minutes = sTime.getMinutes();
				if(hours > 19){
					var workDate = new Date();
					workDate.setDate(sTime.getDate()+1);
					workDate.setHours(8);
					workDate.setMinutes(0);
					console.log(workDate);
					var diff = workDate - sTime;
					var min = ((diff/1000)/60);
					console.log(min);
				}
			}
		});

Собственно, я не знаю как правильно преобразовать полученные минуты в часы и минуты.
Содержимое time.php:
<?php
echo date("c");
?>

laimas 21.04.2015 22:43

Сервер (вы) работаете разве по времени клиента? Нет. Ну а зачем тогда эти расчеты на клиенте:
а) сервер получил запрос от клиента
б) запрос получен по Т-времени сервера
в) относительно этого времени рассчитали через сколько возобновиться работа и ответили "текстом" клиенту.

Другое дело, если вы хотите сообщить клиенту о времени не серверном, а о локальном относительно сервера, но не факт, что в этом случае клиент не будет обнимать подушку.

Sigizmund2012 22.04.2015 08:01

Цитата:

Сообщение от laimas (Сообщение 367684)
Сервер (вы) работаете разве по времени клиента? Нет. Ну а зачем тогда эти расчеты на клиенте:
а) сервер получил запрос от клиента
б) запрос получен по Т-времени сервера
в) относительно этого времени рассчитали через сколько возобновиться работа и ответили "текстом" клиенту.

Именно это я и пытаюсь сделать, только не получается рассчитать правильно оставшееся количество часов и минут. Прокомментирую:
$.ajax({
			url: "/sendmailforms/time.php",
			cache: false,
			success: function(data){
				sTime = new Date(data); // Получили серверное время в формате js
				hours = sTime.getHours(); // Получили часы
				minutes = sTime.getMinutes(); // Получили минуты
				if(hours > 19){
					var workDate = new Date(); // Генерируем дату 8:00 следующего дня
					workDate.setDate(sTime.getDate()+1);
					workDate.setHours(8);
					workDate.setMinutes(0);
					console.log(workDate);
					var diff = workDate - sTime; // Разница дат в миллисекундах
					var min = ((diff/1000)/60); // Разница в минутах
					 console.log(min);
				}
			}
		});

Собственно я не могу корректно рассчитать оставшиеся часы и минуты. Если min/60, я получаю часы, но с остатком, как получить количество оставшихся минут?

laimas 22.04.2015 08:45

Не понятно что вы хотите сделать.

Мы перезвоним вам через 11 часов 18 мин

Почему через 11:18?

Например, сервер работает по московскому времени и рабочий день операторов сервиса с 9 утра до 6 вечера. Вам заказывают звонок с Камчатки, у которой 9 утра по Москве, это 16:00, а 6 вечера по Москве уже следующий день. Отрывать человека от подушки звонком, это непорядочно. И если считать, что он ложится в 9 вечера по местному времени, то ответить Камчатке у вас в распоряжении 5 часов из 8 рабочих. А может и ранее спать ложится, или с утра по Москве для него звонок будет неудобен.

Может лучше при заказе звонка получать часовой пояс клиента. На сервере по нему можно рассчитать промежуток времени для ответа (по времени сервера), чтобы клиенту было удобно. Этот интервал от и до, и уже как UTC метки отдать клиенту, где они будут отображать локальное время.

Sigizmund2012 22.04.2015 09:16

Цитата:

Сообщение от laimas (Сообщение 367705)
Не понятно что вы хотите сделать.

Мы перезвоним вам через 11 часов 18 мин

Почему через 11:18?

Например, сервер работает по московскому времени и рабочий день операторов сервиса с 9 утра до 6 вечера. Вам заказывают звонок с Камчатки, у которой 9 утра по Москве, это 16:00, а 6 вечера по Москве уже следующий день. Отрывать человека от подушки звонком, это непорядочно. И если считать, что он ложится в 9 вечера по местному времени, то ответить Камчатке у вас в распоряжении 5 часов из 8 рабочих. А может и ранее спать ложится, или с утра по Москве для него звонок будет неудобен.

Может лучше при заказе звонка получать часовой пояс клиента. На сервере по нему можно рассчитать промежуток времени для ответа (по времени сервера), чтобы клиенту было удобно. Этот интервал от и до, и уже как UTC метки отдать клиенту, где они будут отображать локальное время.

Ну в принципе да, только позвонить-то ему всё равно смогут только в рабочее время. Да и как это реализовать мне непонятно.

laimas 22.04.2015 15:53

Конечно в рабочее время, поэтому и важно знать смещение часового пояса клиента. Для этого его нужно передать серверу:
Date.prototype.getTimezoneOffset()
//или
(new Date()).getTimezoneOffset()

На сервере опираясь на разницу смещений часовых поясов сервера и клиента можно вести расчет, например:
$z = -300; //смещение клиента в минутах 
$z = date('Z')/60 + $z; //разница смещений сервера и клиента в минутах
$i = DateInterval::createFromDateString(-$z . ' minute'); //по смещению задан интервал, заданный отрицательным значением - восточнее сервера интервал будет добавляться, западнее вычитаться
$date = new DateTime('now');
echo 'Текущее время сервера ' . $date->format('Y-m-d H:i') . '<br>';
$date->add($i);
echo 'Текущее время у клиента ' . $date->format('Y-m-d H:i');

Зная часы работы клиента, можно рассчитать крайние значения времени, которые относительно времени сервера для клиента будут находиться в диапазоне от 9 утра до 9 вечера. Соответственно и сервер будет знать по какому его локальному времени можно звонить клиенту.

PS. Если расчеты проводить на клиенте, то тогда с целью указать диапазон времени работы сервера по времени клиента, в котором клиент может выбрать время для ответного звонка.

Sigizmund2012 22.04.2015 18:02

Цитата:

Сообщение от laimas (Сообщение 367769)
Конечно в рабочее время, поэтому и важно знать смещение часового пояса клиента. Для этого его нужно передать серверу:
Date.prototype.getTimezoneOffset()
//или
(new Date()).getTimezoneOffset()

На сервере опираясь на разницу смещений часовых поясов сервера и клиента можно вести расчет, например:
$z = -300; //смещение клиента в минутах 
$z = date('Z')/60 + $z; //разница смещений сервера и клиента в минутах
$i = DateInterval::createFromDateString(-$z . ' minute'); //по смещению задан интервал, заданный отрицательным значением - восточнее сервера интервал будет добавляться, западнее вычитаться
$date = new DateTime('now');
echo 'Текущее время сервера ' . $date->format('Y-m-d H:i') . '<br>';
$date->add($i);
echo 'Текущее время у клиента ' . $date->format('Y-m-d H:i');

Зная часы работы клиента, можно рассчитать крайние значения времени, которые относительно времени сервера для клиента будут находиться в диапазоне от 9 утра до 9 вечера. Соответственно и сервер будет знать по какому его локальному времени можно звонить клиенту.

PS. Если расчеты проводить на клиенте, то тогда с целью указать диапазон времени работы сервера по времени клиента, в котором клиент может выбрать время для ответного звонка.

Сложновато это для меня, я ведь php вообще не знаю. Тут нужно время пользователя в базу писать, бекэнд, чтобы можно было в админке посмотреть и позвонить. Лучше я на клиенте что-нибудь попроще запилю.

laimas 22.04.2015 18:09

А если вы не будете хранить заказ на сервере и информацию о клиенте, то каким образом вы будете знать когда звонить? Ну покажите вы на клиенте, что позвоните через N времени, и что это даст?

Sigizmund2012 23.04.2015 08:27

Цитата:

Сообщение от laimas (Сообщение 367795)
А если вы не будете хранить заказ на сервере и информацию о клиенте, то каким образом вы будете знать когда звонить? Ну покажите вы на клиенте, что позвоните через N времени, и что это даст?

Письмо админу высылается с телефоном и именем клиента. В общем не стал я мудрить и запилил так:
var sTime,
		hours,
		minutes;
		$.ajax({
			url: "/sendmailforms/time.php",
			cache: false,
			success: function(data){
				sTime = new Date(data);
				hours = sTime.getHours();
				minutes = sTime.getMinutes();
				if(hours >= 19 || hours <= 9 ){
					$('#click-to-call-message' ).html('Вы заказываете звонок в нерабочее время, мы перезвоним вам с 10:00 до 19:00 по Москве');
				}
			}
		});

Буду очень благодарен, если научите рассчитывать правильно оставшееся время в часах и минутах, это для меня стало основной проблемой.

laimas 23.04.2015 11:29

Письмо админу высылается с телефоном и именем клиента.
Вы заказываете звонок в нерабочее время, мы перезвоним вам с 10:00 до 19:00 по Москве

А где в письме указано что надо звонить пусть с 10:00?

Нужно не мудрить, а думать.
Для примера пусть сервер находится в Екатеринбурге (для примера только нашу страну берем).

Те кто западнее сервера в рабочее время 8:00 сервера еще спят, а те что восточнее давно проснулись. Откуда администратор будет знать, что звоня в 8:00 или даже 10:00 по местному времени он не подымет с постели клиента?

Я вам показывал как это нужно делать - считать на севере, запоминать его (ну или в письме отправлять), а клиенту в ответе сообщать результат. Если нужно рассчитать время только относительно начала работы, то:

1) заказ на звонок отправляет скрытым полем и смещение временной зоны клиента - (new Date()).getTimezoneOffset()/60, пусть будет в часах, хотя это будет неудобно, так как есть смещения и в 30 минут, и часов:минут. Но для простоты понятия пусть так.

2) смещение временной зоны клиента, это отрицательное к востоку и положительное к западу от Гринвича значение. РНР же наоборот возвращает к востоку положительные а к западу отрицательные значения.
Жителей по московскому их клиент вернет -3, а сервер 3 (date('Z')/60/60 также получаем в часах). Разница смещений для клиента и сервера при этом будет равна - (date('Z')/60/60) + $z = 3 + (-3) = 0.
Для клиента восточнее Москвы, например -5, будет 3 + (-5) = -2,
а для западнее Москвы, например -1, будет 3 + (-1) = 2.
Зная, что для жителей московского часового пояса разница смещений равна 0, несложно понять, что если разница больше 0, то это клиент западнее Москвы, и ему нужно звонить по московскому времени не в 9 часов, а в 9 + 2 = 11, так как в 9 по Москве у них будет только 7, и он еще может спать. А для сообщения этому клиенту отправляем, что позвоним начиная с 9 утра местного времени.
Если разница смещений меньше нуля, то это восточный клиент и он уже проснулся, и можно звонить по московскому времени начиная с 9, а ему сообщаем, что будем звонить начиная с 9 + 2 = 11 по местному времени.
Для западных окончание периода звонка для сервера равно 18 часов, а сообщаем клиенту 18 - 2 = 16 о местном времени.
Для восточных сервер должен позвонить также до 18 часов, но у клиента местное время будет 18 + 2 = 20. Это время и нужно проверить более ли оно 21 часов.

В общем простая арифметика, без всяких сложностей.


Часовой пояс GMT +3, время: 16:02.