JSON Stringify изменяет время выполнения из-за UTC

Объекты моей даты в JavaScript всегда представлены UTC +2 из-за того, где я находится. Следовательно, как это

Mon Sep 28 10:00:00 UTC+0200 2009

Проблема делает JSON.stringify преобразует указанную дату в

2009-09-28T08:00:00Z  (notice 2 hours missing i.e. 8 instead of 10)

Мне нужно, чтобы дата и время выполнялись, но это не так, поэтому это должно быть

2009-09-28T10:00:00Z  (this is how it should be)

В основном я использую это:

var jsonData = JSON.stringify(jsonObject);

Я попытался передать параметр replacer (второй параметр в stringify), но проблема в том, что это значение уже обработано.

Я также попытался использовать toString() и toUTCString() в объекте даты, но они не дают мне того, что я хочу.

Кто-нибудь может мне помочь?

Ответ 1

Недавно я столкнулся с той же проблемой. И это было решено с помощью следующего кода:

x = new Date();
let hoursDiff = x.getHours() - x.getTimezoneOffset() / 60;
let minutesDiff = (x.getHours() - x.getTimezoneOffset()) % 60;
x.setHours(hoursDiff);
x.setMinutes(minutesDiff);

Ответ 2

JSON использует функцию Date.prototype.toISOString, которая не представляет собой локальное время - она ​​представляет время в немодифицированном UTC - если вы посмотрите на вывод даты, вы можете видеть, что вы в UTC + 2 часа, поэтому JSON строка изменяется на два часа, но если это позволяет правильно отображать одно и то же время в нескольких часовых поясах.

Ответ 3

Только для записи помните, что последний "Z" в "2009-09-28T08: 00: 00Z" означает, что время действительно в UTC.

Подробнее см. http://en.wikipedia.org/wiki/ISO_8601.

Ответ 4

Вот еще один ответ (и лично я считаю это более подходящим)

var currentDate = new Date(); 
currentDate = JSON.stringify(currentDate);

// Now currentDate is in a different format... oh gosh what do we do...

currentDate = new Date(JSON.parse(currentDate));

// Now currentDate is back to its original form :)

Ответ 5

date.toJSON() печатает UTC-Date в формате String (поэтому добавляет смещение с ним при преобразовании его в формат JSON).

date = new Date();
new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toJSON();

Ответ 6

Я немного опаздываю, но вы всегда можете перезаписать функцию toJson в случае использования Date с помощью прототипа:

Date.prototype.toJSON = function(){
    return Util.getDateTimeString(this);
};

В моем случае Util.getDateTimeString(this) возвращает строку вроде этого: "2017-01-19T00: 00: 00Z"

Ответ 7

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

поэтому мы используем GMT (UTC).

Используйте Date.parse(jsondatestring), чтобы получить локальную временную строку,

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

В этом случае используйте метод Anatoly.

Ответ 8

Обход этой проблемы с помощью библиотеки moment.js (версия, не относящаяся к часовому поясу).

var newMinDate = moment(datePicker.selectedDates[0]);
var newMaxDate = moment(datePicker.selectedDates[1]);

// Define the data to ask the server for
var dataToGet = {"ArduinoDeviceIdentifier":"Temperatures",
                "StartDate":newMinDate.format('YYYY-MM-DD HH:mm'),
                "EndDate":newMaxDate.format('YYYY-MM-DD HH:mm')
};

alert(JSON.stringify(dataToGet));

Я использовал библиотеку flatpickr.min.js. Время создания результирующего объекта JSON соответствует локальному времени, но не выбранному.

Ответ 9

вы можете использовать time.js для форматирования с местным временем:

Date.prototype.toISOString = function () {
    return moment(this).format("YYYY-MM-DDTHH:mm:ss");
};

Ответ 10

JSON.stringify решение, заставляющее JSON.stringify игнорировать часовые пояса:

  • Чистый javascript (на основании ответа Анатолия):

// Before: JSON.stringify apply timezone offset
const date =  new Date();
let string = JSON.stringify(date);
console.log(string);

// After: JSON.stringify keeps date as-is!
Date.prototype.toJSON = function(){
    const hoursDiff = this.getHours() - this.getTimezoneOffset() / 60;
    this.setHours(hoursDiff);
    return this.toISOString();
};
string = JSON.stringify(date);
console.log(string);

Ответ 11

Все сводится к тому, что ваш серверный сервер является часовым-агностиком или нет. Если это не так, то вам нужно предположить, что часовой пояс сервера такой же, как клиент, или передавать информацию о часовом поясе клиента и включать также в вычисления.

Пример на основе бэкэнд-сервера PostgreSQL:

select '2009-09-28T08:00:00Z'::timestamp -> '2009-09-28 08:00:00' (wrong for 10am)
select '2009-09-28T08:00:00Z'::timestamptz -> '2009-09-28 10:00:00+02'
select '2009-09-28T08:00:00Z'::timestamptz::timestamp -> '2009-09-28 10:00:00'

Последнее, вероятно, то, что вы хотите использовать в базе данных, если вы не хотите правильно использовать логику часового пояса.

Ответ 12

Вместо toJSON вы можете использовать format функцию, которая всегда дает правильную дату и время + GMT

Это самый надежный параметр отображения. Требуется строка токенов и заменяет их соответствующими значениями.

Ответ 13

Вот что-то действительно аккуратное и простое и не требующее клонирования манипуляции с датой (по крайней мере, я так считаю :)) (ссылка: Как JSON преобразовать дату в Javascript и сохранить часовой пояс, извилистый Шоусон)

Передайте в JSON.stringify функцию заменителя, которая преобразует содержимое в ваше сердце! Таким образом, вам не нужно делать часовые и минутные различия или любые другие манипуляции.

Я поместил в console.logs, чтобы увидеть промежуточные результаты, чтобы было ясно, что происходит и как работает рекурсия. Это показывает что-то, на что стоит обратить внимание: значение param для replacer уже преобразовано в формат даты ISO :). Используйте этот [ключ] для работы с исходными данными.

var replacer = function(key, value)
{
    var returnVal = value;
    if(this[key] instanceof Date)
    {
        console.log("replacer called with key - ", key, " value - ", value, this[key]); 

        returnVal = this[key].toString();

        /* Above line does not strictly speaking clone the date as in the cloned object 
         * it is a string in same format as the original but not a Date object. I tried 
         * multiple things but was unable to cause a Date object being created in the 
         * clone. 
         * Please Heeeeelp someone here!

        returnVal = new Date(JSON.parse(JSON.stringify(this[key])));   //OR
        returnVal = new Date(this[key]);   //OR
        returnVal = this[key];   //careful, returning original obj so may have potential side effect

*/
    }
    console.log("returning value: ", returnVal);

    /* if undefined is returned, the key is not at all added to the new object(i.e. clone), 
     * so return null. null !== undefined but both are falsy and can be used as such*/
    return this[key] === undefined ? null : returnVal;
};

ab = {prop1: "p1", prop2: [1, "str2", {p1: "p1inner", p2: undefined, p3: null, p4date: new Date()}]};
var abstr = JSON.stringify(ab, replacer);
var abcloned = JSON.parse(abstr);
console.log("ab is: ", ab);
console.log("abcloned is: ", abcloned);

/* abcloned is:
 * {
  "prop1": "p1",
  "prop2": [
    1,
    "str2",
    {
      "p1": "p1inner",
      "p2": null,
      "p3": null,
      "p4date": "Tue Jun 11 2019 18:47:50 GMT+0530 (India Standard Time)"
    }
  ]
}
Note p4date is string not Date object but format and timezone are completely preserved.
*/