Как читать и хранить дату и время как есть от javascript до mysql - PullRequest
0 голосов
/ 30 ноября 2018

Я создаю приложение node.js, где пользователь создает запись с полем с именем даты и времени тура.Я использую плагин daterangepicker для отображения выпадающего окна даты и времени.Как только пользователь сохраняет запись, она сохраняется в таблице MySQL как поле даты и времени.

Затем я использую 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
});

Я не установил часовой пояс для устройства выбора даты или моментов.Дата и время, которое я получаю из формы (до сохранения в базе данных), совпадают.то есть он поступает как 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
});

То, что я хочу сделать, не имеет значения, в каком часовом поясе присутствует пользователь. Я хочу сохранить указанную дату и время, как есть, в базе данных и извлечь их как есть, чтобы они отображались вкалендарь.

Как мне этого добиться?

Ответы [ 3 ]

0 голосов
/ 30 ноября 2018
  1. Если вы используете тип данных DATETIME в mysql, то значение save as не зависит от системной переменной mysql time_zone.См. здесь и здесь .
  2. 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
    
  3. Вы можете передать опцию часового пояса в дальнейшем соединении с БД.По умолчанию это «+00: 00».Прежде всего, Sequelize использует это значение для установки опции time_zone для каждого соединения (это можно увидеть, если запустить Sequelize с переменной DEBUG).Также Sequelize (или пакет mysql2, я не знаю) использует параметр часового пояса для преобразования результатов, возвращаемых mysql, в объекты js Date.Итак:

    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, вам не нужно менять параметр часового пояса.

Для корректной работы с датой и временем в моей работе я использую следующие правила:

  • Для транспортной даты и времени между клиентом и сервером используйте уникально определенный формат: UNIX , ISO 8601 (строка как 2017-09-05T13:43:00.000Z);
  • Все значения DATETIME в хранилищах Mysql DBс нулевым часовым поясом (+00: 00);Таким образом, опция часового пояса для Sequelize - «+00: 00»;

Наконец, браузеры используют настройку часового пояса на вашем компьютере.Проверьте значения на всех этапах и устраните неопределенности, связанные с неверной интерпретацией часового пояса.

0 голосов
/ 02 декабря 2018

Хорошо, после большого замешательства, вот как это было решено.Мне пришлось преобразовать дату на моей клиентской стороне в 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 AM в указателе даты

Я также передаю moment.utc(act.tour_date).format('YYYY-MM-DDTHH:mm:ss') обратно на скрытый ввод, если пользователь обновляет запись

Спасибо всем, кто помог мне разобраться в этом.Цените свое время и усилия.

0 голосов
/ 30 ноября 2018

Если вы сохраняете дату с помощью sequelize, тогда она будет хранить дату как UTC,

Так что из внешнего интерфейса просто передайте дату в UTC, чтобы она была сохранена иесли вы используете средство выбора даты и времени, оно автоматически преобразует UTC в ваш часовой пояс, просто передайте данные UTC в свой плагин.

Просто используйте UTC во время прохождения, и вы готовы идти.

...