ユーザーによって作成された日付オブジェクトがあり、タイムゾーンはブラウザによって入力されます。
_var date = new Date(2011, 05, 07, 04, 0, 0);
> Tue Jun 07 2011 04:00:00 GMT+1000 (E. Australia Standard Time)
_
ただし、文字列化すると、タイムゾーンはさようなら
_JSON.stringify(date);
> "2011-06-06T18:00:00.000Z"
_
ブラウザのタイムゾーンを維持しながらISO8601文字列を取得する最良の方法は、moment.jsを使用し、moment.format()
を使用することですが、もちろん、 _JSON.stringify
_内部(この場合、AngularJS)
_var command = { time: date, contents: 'foo' };
$http.post('/Notes/Add', command);
_
完全を期すために、私のドメインdoesにはローカル時間とオフセットの両方が必要です。
Date
を含む何らかの種類のオブジェクトがあると仮定します。
var o = { d : new Date() };
toJSON
プロトタイプのDate
関数をオーバーライドできます。ここでは、moment.jsを使用して日付からmoment
オブジェクトを作成し、パラメーターなしでモーメントのformat
関数を使用します。これにより、オフセットを含むISO8601拡張形式が生成されます。
Date.prototype.toJSON = function(){ return moment(this).format(); }
これで、オブジェクトをシリアル化するときに、要求した日付形式が使用されます。
var json = JSON.stringify(o); // '{"d":"2015-06-28T13:51:13-07:00"}'
もちろん、それはallDate
オブジェクトに影響します。特定の日付オブジェクトのみの動作を変更する場合は、次のように、特定のオブジェクトのtoJSON
関数のみをオーバーライドできます。
o.d.toJSON = function(){ return moment(this).format(); }
Matt Johnsonsの answer に基づいて、toJSON
に依存せずにmoment
を再実装しました(これは素晴らしいライブラリであると思いますが、 toJSON
のような低レベルのメソッドが気になります)。
Date.prototype.toJSON = function () {
var timezoneOffsetInHours = -(this.getTimezoneOffset() / 60); //UTC minus local time
var sign = timezoneOffsetInHours >= 0 ? '+' : '-';
var leadingZero = (Math.abs(timezoneOffsetInHours) < 10) ? '0' : '';
//It's a bit unfortunate that we need to construct a new Date instance
//(we don't want _this_ Date instance to be modified)
var correctedDate = new Date(this.getFullYear(), this.getMonth(),
this.getDate(), this.getHours(), this.getMinutes(), this.getSeconds(),
this.getMilliseconds());
correctedDate.setHours(this.getHours() + timezoneOffsetInHours);
var iso = correctedDate.toISOString().replace('Z', '');
return iso + sign + leadingZero + Math.abs(timezoneOffsetInHours).toString() + ':00';
}
setHours
メソッドは、指定された値が「オーバーフロー」するときに、日付オブジェクトの他の部分を調整します。 [〜#〜] mdn [〜#〜] から:
指定したパラメーターが予想範囲外の場合、setHours()は、それに応じてDateオブジェクトの日付情報を更新しようとします。たとえば、secondsValueに100を使用すると、分は1だけ増加し(minutesValue + 1)、40は秒に使用されます。
ただし、文字列化すると、タイムゾーンはさようなら
Tue Jun 07 2011 04:00:00 GMT+1000 (E. Australia Standard Time)
は実際にはtoString
オブジェクトのDate
メソッドの結果であるのに対し、stringify
はtoISOString
メソッドを呼び出すようだからです代わりに。
したがって、toString
形式が必要な場合は、単に文字列化してくださいthat:
JSON.stringify(date.toString());
または、後で「コマンド」を文字列化するため、最初にthat valueをそこに入れます。
var command = { time: date.toString(), contents: 'foo' };
日付のようなシステムオブジェクトのプロトタイプ内の関数を混乱させないように常に気を配ります。コードで後で予期しない方法でそれがいつ噛み付くかはわかりません。
代わりに、JSON.stringifyメソッドは「replacer」関数を受け入れます( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter )提供でき、JSON.stringifyがその「文字列化」を実行する方法の内部をオーバーライドできます。したがって、このようなことを行うことができます。
var replacer = function(key, value) {
if (this[key] instanceof Date) {
return this[key].toUTCString();
}
return value;
}
console.log(JSON.stringify(new Date(), replacer));
console.log(JSON.stringify({ myProperty: new Date()}, replacer));
let date = new Date(JSON.parse(JSON.stringify(new Date(2011、05、07、04、0、0))));