Как запретить Sequelize преобразовывать объект Date в местное время - PullRequest
0 голосов
/ 26 мая 2018

Я использую sequelize для проекта узла.Он подключается к базе данных Postgres, которая содержит таблицу с полем DATE (в отличие от TIMESTAMP WITH TIMEZONE, DATE не имеет данных о времени).

В коде я моделирую дату, используя javascriptDate объект, который хранит время как полночь UTC.Когда я использую это для вставки записи в таблицу с использованием этого объекта Date, sequelize, по-видимому, сначала покрывает ее по местному времени, потому что записи всегда отстают на 1 день.Поэтому, если я хочу вставить 2000-10-31 в базу данных, я получу 2000-10-30.Я нахожусь в UTC-5.

Как мне сказать сиквелизу не преобразовывать дату в местное время перед вставкой в ​​базу данных?

Вот пример кода.Я также создал репозиторий , если вы хотите запустить его самостоятельно.

var Sequelize = require('sequelize');

const sequelize = new Sequelize('testdb', 'postgres', '???', {
    host: 'localhost',
    dialect: 'postgres'
});

TestTable = sequelize.define('date_test',
    {
        id: {
            primaryKey: true,
            type: Sequelize.INTEGER,
            autoIncrement: true
        },

        someDate: {
            field: 'some_date',
            type: Sequelize.DATEONLY
        }
    },
    {
        timestamps: false,
        freezeTableName: true
    }
);

// midnight UTC on Halloween ?
var date = new Date(Date.UTC(2000, 9, 31));

// converts to local time resulting in 2000-10-30
TestTable.create({ someDate: date })
    .then(function() {
        // also apparently converts to local time resulting in 2000-10-30
        return TestTable.create({ someDate: date.toUTCString() });
    })
    .then(function() {
        // convert to string, definitely works but seems unnecessary
        var strDate = date.getUTCFullYear() + '-' + pad2(date.getUTCMonth() + 1) + '-' + pad2(date.getUTCDate());
        return TestTable.create({ someDate: strDate });
    })
    .then(function() {
        // cerate a new local Date, also works but seems hacky
        var newDate = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate());
        return TestTable.create({ someDate: newDate });
    })
    .then(function() {
        process.exit(0);
    });


function pad2(n) {
    if (n.length === 1) {
        return '0' + n;
    }

    return n;
}

1 Ответ

0 голосов
/ 29 мая 2018

Проблема в том, что дата создается как время UTC, но поскольку DATEONLY не знает о часовом поясе, он форматирует объект Date «как есть» (по местному времени) в формате YYYY-MM-DD (используя момент.js - см. здесь в источнике ).

Для DATEONLY вы можете просто сделать это:

var date = new Date(2000, 9, 31);

Это правильно вставит дату.

Программисты редко говорят это, но на этот раз вы думали слишком много о часовых поясах!


СТАРЫЙ НЕПРАВИЛЬНЫЙ ОТВЕТ

Это зависит от того, как вы проверяетезначение, но javascript и postgresql преобразуют его для отображения в местном часовом поясе.

Sequelize использует тип TIMESTAMP WITH TIMEZONE для поля даты ( source ).

В postgresql документах он говорит:

Для метки времени с часовым поясом внутренне сохраненное значение всегда в UTC (универсальное координированное время, традиционно известное какСреднее время по Гринвичу, GMT).Входное значение с указанным явным часовым поясом преобразуется в UTC с использованием соответствующего смещения для этого часового пояса.Если во входной строке не указан часовой пояс, предполагается, что он находится в часовом поясе, указанном системным параметром часового пояса, и преобразуется в UTC с использованием смещения для часового пояса.

Когда отметка временикогда выводится значение часового пояса, оно всегда преобразуется из UTC в текущий часовой пояс и отображается как местное время в этом поясе.Чтобы увидеть время в другом часовом поясе, измените часовой пояс или используйте конструкцию AT TIME ZONE (см. Раздел 9.9.3).

Если вы выводите значение времени в postgresql, попробуйте преобразовать его вУНИВЕРСАЛЬНОЕ ГЛОБАЛЬНОЕ ВРЕМЯ.Если вы выводите его в javascript, попробуйте date.toUTCString().

. Причина, по которой ваши хаки работают, заключается в том, что они на самом деле хранят 2000-11-01 05:00, но когда вы проверяете значение, оно конвертируется в ваше местное время.зона. * 1 042 *

...