NodeJS: Почему в новой дате () разница в два часа? - PullRequest
0 голосов
/ 02 сентября 2018

Я делаю

console.log(process.env.TZ);
console.log(new Date());

выводит

Europe/Amsterdam
2018-09-02T08:07:03.842Z

Но текущее время 10:07, а не 08:07.

Реальная проблема заключается в том, что когда я сохраняю модель в БД, она как-то конвертируется в UTC, а это не то, что мне нужно. Это как order.delivery_date = 2018-08-06 10:00:00; order.save (). когда я смотрю в БД, там написано 08:00:00. Как я могу предотвратить это?

Я использую Loopback 3 и MySQL.

Ответы [ 3 ]

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

Отвечая на заглавный вопрос: new Date() вернет вам значение времени UTC, которое имеет Z индикатор часового пояса и значение часового пояса (2 в вашем случае) в конце строки.

Отвечая на вопрос о db save(), позвоните: Это зависит от уровня доступа к данным и типа столбца данных.

Может быть два основных подхода:

  • для сохранения UTC и отображения местного времени (из-за дня, когда у вас будут пользователи с 2+ часовыми поясами)

так что ваш save() работает правильно для этого подхода, вам просто нужно добавить местный преобразователь времени (обычно лучший способ - добавить его на внешней стороне)

  • сохранить значение по местному времени как есть (не рекомендуется, но может быть полезно)

поэтому вы должны либо сделать конвертеры при записи / чтении, либо изменить тип столбца, чтобы он не использовал формат UTC (например, один из простых, но хакерских способов - сохранить его как строковое значение)

Если вы выберете путь с конвертером, я рекомендую вам использовать moment.js (как для передней, так и для задней части). Это может сэкономить время, когда вам потребуются какие-либо временные манипуляции, но это может быть накладные расходы.

Вы также можете сделать это вручную (например, чтобы уменьшить размер пакета), вы можете использовать подход из this answer:

const options = {
    timeZone: "America/New_York",
    year: 'numeric', month: 'numeric', day: 'numeric',
    hour: 'numeric', minute: 'numeric', second: 'numeric'
};

const formatter = new Intl.DateTimeFormat([], options);

const UTCTime = "2017-09-03T02:00:00Z";
const localTime = formatter.format(new Date(UTCTime));
const currentTime = formatter.format(new Date()); 
console.log(currentTime, localTime);
0 голосов
/ 15 ноября 2018

У меня нет полной картины ваших настроек, но да, при сохранении дат петлевое преобразование конвертируется в UTC из местного времени. Если вы заглянете в коннектор mysql, то обнаружите следующую функцию, которая создает строку datetime из значений UTC на указанную дату:

function dateToMysql(val) {
  return val.getUTCFullYear() + '-' +
    fillZeros(val.getUTCMonth() + 1) + '-' +
    fillZeros(val.getUTCDate()) + ' ' +
    fillZeros(val.getUTCHours()) + ':' +
    fillZeros(val.getUTCMinutes()) + ':' +
    fillZeros(val.getUTCSeconds());

  function fillZeros(v) {
    return v < 10 ? '0' + v : v;
  }
}

Однако следует восстановить дату по местному времени при загрузке, поскольку он инициализирует объект javascript Date из сохраненной строки, которая преобразуется в местное время:

val = new Date(val.toString().replace(/GMT.*$/, 'GMT'));

Наилучшим вариантом, вероятно, является использование ловушек операций и манипулирование данными при их поступлении в / из вашей модели. Например, вы можете отформатировать дату по своему усмотрению, так как данные загружаются из хранилища данных:

Order.observe("loaded", (ctx, next) => {
    if (ctx.data) {
      ctx.data.delivery_date_formatted = tzFormat(ctx.data.delivery_date);
    }

    next();
  });

Вы также можете подойти к этому с другой стороны и манипулировать данными, которые сохраняются. Вы не можете на самом деле запретить циклическому сохранению даты в формате UTC, но вы можете добавить или удалить смещение часового пояса, чтобы, как только оно было удалено с помощью разъема обратной связи, оно сохраняло строку с вашим местным временем (ОЧЕНЬ хак, я бы не стал рекомендовать его). Пример:

Order.observe("before save", (ctx, next) => {
    if (ctx.instance) {
      ctx.instance.delivery_date = new Date(
        Date.UTC(
          ctx.instance.delivery_date.getFullYear(),
          ctx.instance.delivery_date.getMonth(),
          ctx.instance.delivery_date.getDate(),
          ctx.instance.delivery_date.getHours(),
          ctx.instance.delivery_date.getMinutes(),
          ctx.instance.delivery_date.getSeconds()
        )
      );
    }

    next();
  });
0 голосов
/ 02 сентября 2018

выводит

Europe/Amsterdam
2018-09-02T08:07:03.842Z

Но текущее время 10:07, а не 08: 07.

Z в строке указывает, что время указано в UTC, а не в местном времени. Это просто строка, выводимая консолью Node.js, когда вы передаете ей строку (она из toUTCString). Объекты JavaScript Date работают по местному времени, но также имеют функции для доступа к времени UTC (getUTCHours, getUTCMinutes и т. Д.); toUTCString является одним из них.

Вы можете использовать различные функции местного времени для объекта Date (getHours, getMinutes и т. Д.), И вы получите от него информацию о местном времени. (Например, toString, вероятно, даст вам строку местного времени.)

...