Pergunta

Os meus objetos data em JavaScript são sempre representados por UTC +2 por causa de onde estou localizado. Assim como esta

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

Problema está fazendo um JSON.stringify converte a data acima para

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

O que eu preciso é que a data e hora para ser honrado, mas não é, portanto, deve ser

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

Basicamente eu uso isso:

var jsonData = JSON.stringify(jsonObject);

Eu tentei passar um parâmetro substituto (segundo parâmetro na stringify), mas o problema é que o valor já foi processado.

Eu também tentei usar toString() e toUTCString() no objeto data, mas estes não me dê o que eu quero quer ..

Alguém pode me ajudar?

Foi útil?

Solução

Recentemente eu tenho que correr para o mesmo problema. E isso foi resolvido usando o seguinte código:

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

Outras dicas

JSON usa a função Date.prototype.toISOString que não representa a hora local - que representa o tempo em UTC não modificada - se você olhar para a sua saída data, você pode ver que você está no UTC + 2 horas, razão pela qual as mudanças string JSON por duas horas, mas se isso permite ao mesmo tempo para ser representada corretamente em vários fusos horários.

Apenas para o registro, lembre-se que a última "Z" em "2009-09-28T08: 00: 00Z". Significa que o tempo é de fato em UTC

Consulte http://en.wikipedia.org/wiki/ISO_8601 para mais detalhes.

Aqui está outra resposta (e pessoalmente eu acho que é mais apropriado)

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 :)

Eu sou um pouco tarde, mas você sempre pode substituir a função toJson em caso de uma data usando Prototype assim:

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

No meu caso, Util.getDateTimeString (this) retornar uma string como esta: "2017-01-19T00: 00: 00Z"

date.toJSON () imprime a UTC-Data em uma String formatada (Então adiciona o deslocamento com ele quando converte em formato JSON).

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

Normalmente deseja que as datas a serem apresentados para cada usuário em sua própria hora local -

é por isso que usar GMT (UTC).

Use Date.parse (jsondatestring) para obter a seqüência hora local,

a menos que você deseja a sua hora local mostrada para cada visitante.

Nesse caso, use o método de Anatoly.

Got contornar esse problema usando a biblioteca moment.js (a versão não-fuso horário).

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));

Eu estava usando a biblioteca flatpickr.min.js. O tempo dos resultantes partidas criadas JSON objeto a hora local fornecido, mas o selecionador de data.

Você pode usar moment.js para o formato com hora local:

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

Out-of-the-box solução para força JSON.stringify ignorar fusos horários:

  • javascript Pure (com base na resposta Anatoliy):

// 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);

Usando biblioteca moment.js:

const date =  new Date();
let string = JSON.stringify(date);
console.log(string);

Date.prototype.toJSON = function(){
    return moment(this).format("YYYY-MM-DDTHH:mm:ss:ms");;
};
string = JSON.stringify(date);
console.log(string);
<html>
  <header>
    <script src="https://momentjs.com/downloads/moment.min.js"></script>
    <script src="https://momentjs.com/downloads/moment-timezone-with-data-10-year-range.min.js"></script>
</header>
</html>

Aqui está algo realmente puro e simples (pelo menos eu acredito que sim :)) e não exige nenhuma manipulação da data a ser clonada ou sobrecarregar nenhuma das funções nativas do navegador como toJSON (referência: como JSON stringify uma data javascript e preservar fuso horário , courtsy Shawson)

Passe uma função substituto para JSON.stringify que stringifies encher para o conteúdo do seu coração !!! Desta forma, você não tem que fazer hora e minuto diffs ou quaisquer outras manipulações.

tenho posto na console.logs para ver os resultados intermediários para que fique claro o que está acontecendo e como recursão está funcionando. Isso revela algo digno de nota: valor param para substituto já é convertido para o formato de data ISO :). Utilize este [key] para trabalhar com dados originais.

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.
*/

eu me deparo com isso um pouco a trabalhar com o material legado onde eles só funcionam na costa leste dos Estados Unidos e não armazenam datas em UTC, é tudo EST. Tenho de filtro sobre as datas com base na entrada do usuário no navegador assim deve passar a data na hora local no formato JSON.

Apenas para a reflexão sobre esta solução já publicado - isto é o que eu uso:

// Could be picked by user in date picker - local JS date
date = new Date();

// Create new Date from milliseconds of user input date (date.getTime() returns milliseconds)
// Subtract milliseconds that will be offset by toJSON before calling it
new Date(date.getTime() - (date.getTimezoneOffset() * 60000)).toJSON();

Assim, a minha compreensão é isso vá em frente e tempo de subtração (em milissegundos (daí 60000) a partir da data de início com base no deslocamento de fuso horário (retornos minutos) - em antecipação para a adição de tempo toJSON () vai adicionar.

Tudo se resume a se o seu servidor back-end é fuso horário agnóstico ou não. Se não for, então você precisa assumir que fuso horário do servidor é o mesmo que o cliente, ou informações de transferência sobre o fuso horário do cliente e que incluem também nos cálculos.

exemplo

a backend PostgreSQL base:

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'

O último é provavelmente o que você deseja usar no banco de dados, se você não está disposto implementar adequadamente lógica fuso horário.

Em vez de toJSON, você pode usar função formato que dá sempre a data correta e tempo de + GMT

Esta é a opção de exibição mais robusto. É preciso uma seqüência de tokens e substitui-los com seus valores correspondentes.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top