Странное смещение дат в NodeJS

151
17 апреля 2018, 03:33

Проблема 1: Одна и та же версия ноды, и там и там системное время задано правильно, временная зона Europe/Moscow с двух сторон, DST настроено правильно. Проблема 2: Дата на фронте преобразуется в UTC -> отправляется на сервер -> сохраняется в MySQL. Возвращается с сервера -> преобразуется в локальное время -> выводится.

В момент возврата с сервера старое доброе смещение на 1 час, а при преобразовании в локальное — на 1 день(!!!).

При этом, если бекэнд запущен под виндой(Windows 10 Pro, x64) — никакого смещения вообще нет, если под дебианом(Debian 9.4 stretch, x64) — 1 час -> 1 день

Из-за чего может возникать подобная ошибка?

Фронтэнд (вырезано все то, что с ней не связано): Используется JQuery 3.3.1 и Vue 2.5.13 Используется заголовок

Content-Type: application/json

Получение:

$.ajax({
    type: "get",
    url: "/sns/getAccount",
    data: { id: id },
    success: function (result) {
        profileUI.vue.account = result;
        if (result.birthDate)
            Vue.nextTick(function () {
                if (!profileUI.birthDatePicker)
                    profileUI.birthDatePicker = $('#profileUI .editProfileContainer input.birthDateInput.datepicker-here').datepicker({
                        toggleSelected: false,
                        onSelect: function (formattedDate, date, inst) {
                            profileUI.vue.account.birthDate = date.toISOString();
                        }
                    }).data('datepicker');
                profileUI.birthDatePicker.selectDate(birthDate);
            })
    }
});

Отправка:

profileUI.saveProfile = function () {
    var account = profileUI.vue.account;
        $.ajax({
            url: '/sns/editAccount',
            type: 'post',
            data: profileUI.vue.account,
            success: function (result) {
                switchSubWindow('#profileUI', '.profileInfoContainer');
                profileUI.loadAccount(account.id);
            },
            error: function (err) {
                console.log(err);
            }
        });
}

Бекэнд(вырезано все, что не связано с датой) Используются пакеты NodeJS 9.11.1, express 4.16.2 и mysql 2.15.0 MySQL Community Server(в обоих случаях один и тот же, запущен на машине с дебианом(см выше))

Сохранение в БД:

router.post('/editAccount', (req, res) => {
                        connectionPool.query(sql.editAccountSQL,
                            req.body.birthDate?new Date(req.body.birthDate):null,
                            req.body.id],
                            err => {
                                if (!err) replyOk(res);
                                else replyError(res, err, 500);
                            });
})

Получение из БД:

queryDbAuthSensitive(req.cookies.token, sql.getAccountByIdSQL, [req.query.id], (err, rows) => {
                    replyOk(res, rows[0]);
        });

replyOk:

export function replyOk(res: Response, data: any = null) {
  if (!res.headersSent) res.writeHead(200);
  res.end(data ? JSON.stringify(data, null, 2) : '{}');
}

sql.getAccountByIdSQL =

SELECT * FROM Account WHERE id = ? LIMIT 2;

sql.editAccount =

UPDATE Account
SET birthDate = ?
WHERE id = ?;
Answer 1

Костыль, достаточно прочный, чтобы временно решить проблему:

Время по UTC получается на 1 день раньше нашего. Собственно, вырезал все дальше T(т.к. для даты рождения просто не нужно) -> распарсил как наше -> +1 день.

var birthDate = new Date(result.birthDate.split('T')[0]);
birthDate.setDate(birthDate.getDate()+1);

Внимание! Гарантированно работает только по Москве. Меня это пока устраивает. Для других временных зон - на свой страх и риск.

READ ALSO
Изменения библиотеки fingerprintjs2

Изменения библиотеки fingerprintjs2

Добрый деньВы наверно знаете библиотеку для создания browser fingerprint https://github

395
Доступ к API. PHP vs Python 3

Доступ к API. PHP vs Python 3

Всем добраПосоветуйте на чем лучше осуществлять доступ к API сайта

181