web-dev-qa-db-ja.com

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の2番目のパラメーター)を渡そうとしましたが、問題は値が既に処理されていることです。

また、日付オブジェクトでtoString()toUTCString()を使用してみましたが、これらは私が望むものを提供しません。

誰も私を助けることができますか?

87
mark smith

最近、同じ問題に遭遇しました。そして、次のコードを使用して解決されました。

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

JSONはローカル時間を表さないDate.prototype.toISOString関数を使用します-変更されていないUTCで時刻を表します-日付出力を見ると、UTC + 2時間であることがわかります。 2時間変化しますが、これにより、同じ時間を複数のタイムゾーンで正しく表すことができます。

37
olliej

記録のために、「2009-09-28T08:00:00Z」の最後の「Z」は、時刻が実際にUTCであることを意味することに注意してください。

詳細については、 http://en.wikipedia.org/wiki/ISO_8601 を参照してください。

15
Locoluis

ここに別の答えがあります(個人的にはより適切だと思います)

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

私は少し遅れていますが、次のようにPrototypeを使用して日付の場合にtoJson関数をいつでも上書きできます:

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

私の場合、Util.getDateTimeString(this)は次のような文字列を返します: "2017-01-19T00:00:00Z"

date.toJSON()は、UTC-Dateを書式設定された文字列に出力します(JSON形式に変換するときにオフセットを追加します)。

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

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オブジェクトの時刻は、日付ピッカーではなく提供された現地時刻と一致します。

2
Paul

moment.js を使用して、現地時間でフォーマットできます。

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

通常、各ユーザーに自分の現地時間で日付を表示する必要があります。

これがGMT(UTC)を使用する理由です。

Date.parse(jsondatestring)を使用してローカル時間文字列を取得し、

want各訪問者に表示される現地時間でない限り。

その場合は、アナトリーの方法を使用してください。

2
kennebec

これは、米国東海岸でのみ動作し、UTCで日付を保存せず、すべてESTであるレガシーなもので少し動作します。ブラウザーでのユーザー入力に基づいて日付をフィルター処理する必要があるため、日付を現地時間でJSON形式で渡す必要があります。

すでに投稿されたこのソリューションについて詳しく説明するために、これが私が使用しているものです:

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

したがって、私の理解では、これは先に進み、タイムゾーンオフセットに基づいて開始日からミリ秒単位で(したがって60000)減算します(分を返します)-toJSON()が追加される時間の追加を見込んでいます。

1
MrRobboto

すぐに使用できるソリューションJSON.stringifyタイムゾーンを無視:

  • 純粋なjavascript(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);

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>
1
Benjamin Caure

これは本当にすてきでシンプルなものです(少なくとも私はそう信じています:))、日付を複製したり、toJSONのようなブラウザのネイティブ関数をオーバーロードしたりする必要はありません(参照: JavaScriptの日付をJSON文字列化してタイムゾーンを保持する方法 、丁寧なショーソン)

置換関数をJSON.stringifyに渡して、内容を文字列に変換します!!!これにより、時間と分の差分やその他の操作を行う必要がなくなります。

中間結果を確認するためにconsole.logsに書き込みましたので、何が起こっているのか、再帰がどのように機能しているのかが明確です。これは、注目に値する何かを明らかにします:replacerへのvalue paramは、すでに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.
*/
1
Atul Lohiya

サーバーのバックエンドがタイムゾーンに依存しないかどうかによって決まります。そうでない場合は、サーバーのタイムゾーンがクライアントと同じであると想定するか、クライアントのタイムゾーンに関する情報を転送して計算に含める必要があります。

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'

タイムゾーンロジックを適切に実装しない場合は、おそらく最後のものがデータベースで使用するものです。

0
korc

toJSONの代わりに、常に正しい日付と時刻を提供する format 関数を使用できます+ GMT

これは最も堅牢な表示オプションです。トークンの文字列を受け取り、対応する値に置き換えます。

0
Asqan