如何按原样从javascript读取和存储datetime到mysql

8aqjt8rx  于 2021-06-18  发布在  Mysql
关注(0)|答案(3)|浏览(475)

我正在构建一个application node.js,其中用户使用名为tour date and time的字段创建一个记录。我使用daterangepicker插件来显示日期和时间下拉窗口。一旦用户保存了记录,它就作为datetime字段保存在mysql表中。
然后我使用fullcalendar来显示给定月份和年份的所有旅游日期。
但问题是。假设我选择2018年11月28日下午6:30作为巡演日期和时间。在daterange选取器中,它被保存为
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设置任何时区。我从表单中得到的日期时间(保存到数据库之前)是相同的。i、 2018年11月28日18:30。
但是,在保存到数据库时,它会保存为

2018-11-28 01:00:00

它将+06:30(ist,印度标准时间值)添加到传入日期时间字段。
所以当我打开日历时,日期是正确的(2018年11月28日),但时间是不正确的。用户保存了预期时间为下午6: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
});

我想做的是不管用户在哪个时区。我想将给定的日期和时间保存在数据库中,并按原样检索它,以显示在日历中。
我如何做到这一点?

zazmityj

zazmityj1#

如果您通过sequelize存储日期,则它将日期存储为utc,
因此,从前端只需传递utc的日期,所以它将得到存储,如果您使用的是日期时间选择器,它将自动转换成您的时区utc,只需传递utc数据到您的插件。
只要在传球时使用utc,你就可以出发了。

xpszyzbs

xpszyzbs2#

如果在mysql中使用datetime数据类型,那么值save as独立于mysql timezone系统变量。看看这里和这里。
mysql根据时区系统变量为某些函数返回不同的值。例如:

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

您可以在db connetion的sequelize中传递时区选项。默认为“+00:00”。首先,sequelize使用这个值在每个连接上设置时区选项(如果用debug变量启动sequelize,您可以看到它)。另外,sequelize(或者mysql2包,我不知道)使用timezone选项将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插入/选择数据,则不需要更改时区选项。
为了在工作中正确使用datetime,我使用以下规则:
对于客户端和服务器之间的传输日期时间,请使用唯一确定的格式:unix、iso 8601(类似字符串 2017-09-05T13:43:00.000Z );
mysql数据库存储区中所有时区为零的datetime值(+00:00);所以sequelize的时区选项是“+00:00”;
最后,浏览器在您的计算机上使用时区设置。检查所有步骤的值,并消除与时区错误解释相关的不确定性。

v6ylcynt

v6ylcynt3#

好吧,在经历了很多困惑之后,这里是如何解决这个问题的。我必须将客户端的日期转换为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')

因此,用户可以在datepicker中看到2018年12月31日上午10:30
我也通过了 moment.utc(act.tour_date).format('YYYY-MM-DDTHH:mm:ss') 返回隐藏输入,以防用户更新记录
谢谢所有帮助我解决这个问题的人。感谢你的时间和努力。

相关问题