Я создаю приложение node.js, в котором пользователь создает запись с полем с именем даты и времени тура. Я использую плагин дата для отображения раскрывающегося окна даты и времени. Как только пользователь сохраняет запись, она сохраняется в таблице MySQL как поле datetime.
Затем я использую fullcalendar для отображения всех дат тура для данного месяца-года.
Но вот в чем проблема. Допустим, я выбрал 28/11/2018 18:30 в качестве даты и времени тура. В средстве выбора диапазона дат он сохраняется как
2018-11-28 18:30
$('input#tour_date').daterangepicker({
singleDatePicker: true,
showDropdowns: true,
timePicker: true,
timePickerIncrement: 30,
locale: {
format: 'DD/MM/YYYY hh:mm A'
}
}, function (chosendate) {
$('input[name = "tour_date"]').val(moment(chosendate).format('YYYY-MM-DD hh:mm'));
//the value for input becomes 2018-11-28 18:30
});
Я не установил часовой пояс для daterangepicker или momentjs. Дата и время, которые я получаю из формы (перед сохранением в базу данных), одинаковы. то есть он приходит как 2018-11-28 18:30.
Однако при сохранении в базу данных он сохраняется как
2018-11-28 01:00:00
Он добавляет +06: 30 (IST, значение индийского стандартного времени) к входящему полю даты и времени.
Поэтому, когда я открываю свой календарь, дата правильная (28/11/2018), но время неверное. Пользователь сохранил поле, ожидая, что время будет 18:30, но вместо этого видит 01:00.
Я сохраняю дату и время как
var tourDate = new Date(req.body.tour_date).toISOString();
Я использую Sequelize ORM, и я не указал конкретный часовой пояс.
const sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, {
host: process.env.DB_HOST,
port: 3306,
dialect: 'mysql',
pool: {
max: 10,
min: 0,
acquire: 30000,
idle: 10000
},
logging: false
});
Что я хочу сделать, так это вне зависимости от того, в каком часовом поясе находится пользователь. Я хочу сохранить данные дату и время, как они есть в базе данных, и получить их как есть, чтобы они отображались в календаре.
Как мне этого добиться?
Я изменил строку формата на «ГГГГ-ММ-ДД чч: мм» в формате momentjs, поэтому проблема дополнительных 11 минут была решена. Однако он по-прежнему сохраняет дату и время, добавляя к нему значение IST.
вы установили часовой пояс в momentJS или fullCalendar? А как насчет самого веб-сервера? Как вы разбираете дату, когда она туда приходит? Вы отлаживали, чтобы увидеть, есть ли еще желаемое время, когда оно прибывает на сервер (но до того, как оно будет записано в базу данных)? Установлен ли часовой пояс на самом сервере mySQL (а не в подключении sequelize)? Здесь много недостающей информации.
Я обновил информацию по своему вопросу. Я не устанавливаю часовой пояс для momentjs, fullcalendar и daterangepicker. Когда дата и время поступают на сервер, оно имеет тот же формат, что и в поле ввода.
Так что насчет веб-сервера и сервера mysql? Есть какие-нибудь настройки времени на тех? Вы не упомянули, что нашли там.
(new Date()).toISOString() вернет дату и время в формате UTC (путем добавления / вычитания смещения часового пояса к местному времени ... 18:30 - 05:30 = 01:00). Остальные детали вы не опубликовали. Но вы, вероятно, могли бы использовать момент js для преобразования локального datetime в формат, который ожидает MySQL.






Если вы сохраняете дату через sequelize, она сохранит дату как UTC,
Итак, с передней стороны просто передайте дату в формате UTC, чтобы она была сохранена и если вы используете средство выбора даты и времени, оно автоматически преобразует UTC в ваш часовой пояс, просто передайте данные UTC в свой плагин.
Просто используйте UTC при прохождении, и все готово.
Это то, что я пытаюсь сделать. Я хочу прочитать значение datetime, выбранное пользователем как есть, и сохранить его как есть, независимо от того, в каком часовом поясе находится пользователь. Пока единственный успех - это возможность получить выбранное значение datetime на стороне сервера целиком, но как только Sequelize сохраняет его в таблицу, он конвертируется :(
Итак, вы были правы. Кажется, мне снова нужно преобразовать дату на стороне сервера в utc, используя момент.
Это не работает даже с опцией UTC. Как-то есть несколько настроек, которые не работают. Node js действительно нужен встроенный, sequelize плохо поддерживается. Похоже, сиквелиз ничего не знает о часовых поясах.
mysql возвращает разные значения для некоторых функций в зависимости от переменной системы time_zone. Например:
SET time_zone='+00:00';
SELECT now(); //2018-11-30 17-52-00
SET time_zone='+03:00';
SELECT now(); //2018-11-30 20-52-00
Вы можете передать параметр часового пояса в продолжение соединения с БД. По умолчанию это '+00: 00'. Прежде всего, Sequelize использует это значение для установки time_zone опция для каждого соединения (вы можете увидеть это, если запустить Sequelize с Переменная DEBUG). Также Sequelize (или пакет mysql2, я не знаю) использует параметр часового пояса для преобразования результатов, возвращаемых mysql, в объекты Date js. Так:
const sequelize = new Sequelize('database', 'user', 'password', {timezone: "+00:00"});
sequelize.query('SELECT now() AS now;', {type: sequelize.QueryTypes.SELECT})
//2018-11-30T17:52:00.000Z
sequelize.query('SELECT createdAt FROM users WHERE userId = 1;', {type: sequelize.QueryTypes.SELECT})
//2017-09-05T13:43:00.000Z
const sequelize = new Sequelize('database', 'user', 'password', {timezone: "+03:00"});
sequelize.query('SELECT now() AS now;', {type: sequelize.QueryTypes.SELECT})
//2018-11-30T17:52:00.000Z
sequelize.query('SELECT createdAt FROM users WHERE userId = 1;', {type: sequelize.QueryTypes.SELECT})
//2017-09-05T10:43:00.000Z
Объяснять:
Для now:
+-----------+---------------------+----------------------------+--------------------------+
| time_zone | mysql return | sequelize read result as | sequelize return |
+-----------+---------------------+----------------------------+--------------------------+
| +00:00 | 2018-11-30 17-52-00 | 2018-11-30 17-52-00 +00:00 | 2018-11-30T17:52:00.000Z |
+-----------+---------------------+----------------------------+--------------------------+
| +03:00 | 2018-11-30 20-52-00 | 2018-11-30 20-52-00 +03:00 | 2018-11-30T17:52:00.000Z |
+-----------+---------------------+----------------------------+--------------------------+
Для createdAt:
+-----------+---------------------+----------------------------+--------------------------+
| time_zone | mysql return | sequelize read result as | sequelize return |
+-----------+---------------------+----------------------------+--------------------------+
| +00:00 | 2017-09-05 13-43-00 | 2017-09-05 13-43-00 +00:00 | 2017-09-05T13:43:00.000Z |
+-----------+---------------------+----------------------------+--------------------------+
| +03:00 | 2017-09-05 13-43-00 | 2017-09-05 13-43-00 +03:00 | 2017-09-05T10:43:00.000Z |
+-----------+---------------------+----------------------------+--------------------------+
Поэтому будьте осторожны при установке параметра часового пояса при использовании типа данных DATETIME. Если вы вставляете / выбираете свои данные только с помощью sequelize, вам не нужно менять параметр часового пояса.
Для корректной работы с datetime в своей работе я использую следующие правила:
2017-09-05T13:43:00.000Z);Наконец, браузеры используют настройку часового пояса на вашем компьютере. Проверяйте значения на всех этапах и устраняйте неопределенности, связанные с неправильной интерпретацией часового пояса.
Итак, вот что происходит. В своем продолжении я установил значение часового пояса на +00: 00. Если я выбрал 05/12/2018 9:00 AM в своем календаре, на моем сервере будет указано 2018-12-05T09: 00: 00 (до сохранения). Но после вставки даты она становится 2018-12-05 03:30:00.
@codeinprogress Какой формат вы используете для передачи между клиентом и сервером? Простое решение - отправить результат dateString = date.toISOString() от клиента и использовать Date.parse(dateString) на сервере nodejs. Обратите внимание, что вы должны использовать часовой пояс в этом формате для определенного результата, в ISO 8601 «Z» - это часовой пояс «+00: 00».
Хорошо, после долгой неразберихи вот как это было решено. Мне пришлось преобразовать дату на моей стороне клиента в utc, а затем, когда дело доходит до моего сервера node.js, мне нужно снова преобразовать ее в UTC, прежде чем сохранять в базе данных.
На стороне клиента я устанавливаю дату в скрытом поле ввода (это то, что я отправляю на сервер), используя
$('input#tour_date').daterangepicker({
singleDatePicker: true,
showDropdowns: true,
timePicker: true,
timePickerIncrement: 30,
locale: {
format: 'DD/MM/YYYY hh:mm A'
}
}, function (chosendate) {
//this is the hidden input where the set date is being sent
$('input[name = "tour_date"]').val(moment(chosendate).format('YYYY-MM-DDTHH:mm:ss'));
});
Итак, один сервер входит как
2018-12-31T10:30:00.000Z
Что затем мне нужно обработать снова, используя такой момент:
moment.utc(req.body.tour_date); //this is saved to db
Когда я читаю запись и показываю ее пользователю, я обрабатываю дату как
moment.utc(act.tour_date).format('DD/MM/YYYY hh:mm A')
Таким образом, пользователь видит 31/12/2018 10:30 в указателе даты.
Я также передаю moment.utc(act.tour_date).format('YYYY-MM-DDTHH:mm:ss') обратно на скрытый ввод, на случай, если пользователь обновит запись
Спасибо всем, кто помог мне разобраться в этом. Цените свое время и усилия.
Вы внимательно прочитали руководство по моменту js? Вы даже не задумывались, почему всегда 11? А какое число ноябрь?