web-dev-qa-db-ja.com

JavaScriptでタイムゾーンオフセット付きの日付をISO 8601形式にするにはどうすればよいですか?

目標:local timeおよびUTC time offsetを見つけて、次の形式でURLを構築します。

URLの例:/ Actions/Sleep?duration = 2002-10-10T12:00:00−05:00

この形式は、W3C勧告に基づいています: http://www.w3.org/TR/xmlschema11-2/#dateTime

ドキュメントには次のように書かれています:

たとえば、2002-10-10T12:00:00-05:00(2002年10月10日正午、米国中部夏時間および東部標準時)は2002-10-10T17:00:00Zに等しく、 2002-10-10T12:00:00Zより5時間後。

したがって、私の理解に基づいて、新しいDate()でローカル時間を見つけ、getTimezoneOffset()関数を使用して差を計算し、それを文字列の末尾に付加する必要があります。

1.フォーマットで現地時間を取得する

var local = new Date().format("yyyy-MM-ddThh:mm:ss"); //today (local time)

output

2013-07-02T09:00:00

2.時間単位のUTC時間オフセットを取得する

var offset = local.getTimezoneOffset() / 60;

output

7

3.URLの構築(時間部分のみ)

var duration = local + "-" + offset + ":00";

output:

2013-07-02T09:00:00-7:00

上記の出力は、現地時間が2013/07/02午前9時であり、UTCとの差が7時間であることを意味します(UTCは現地時間の7時間先です)

これまでは動作しているようですが、getTimezoneOffset()が-120のような負の値を返すとどうなりますか?

私はW3C文書から理解できないので、そのような場合にフォーマットがどのように見えるべきか疑問に思っています。前もって感謝します。

83
masato-san

以下は適切に動作し、すべてのブラウザで動作するはずです(ヒントを提供してくれた@MattJohnsonに感謝)

Date.prototype.toIsoString = function() {
    var tzo = -this.getTimezoneOffset(),
        dif = tzo >= 0 ? '+' : '-',
        pad = function(num) {
            var norm = Math.floor(Math.abs(num));
            return (norm < 10 ? '0' : '') + norm;
        };
    return this.getFullYear() +
        '-' + pad(this.getMonth() + 1) +
        '-' + pad(this.getDate()) +
        'T' + pad(this.getHours()) +
        ':' + pad(this.getMinutes()) +
        ':' + pad(this.getSeconds()) +
        dif + pad(tzo / 60) +
        ':' + pad(tzo % 60);
}

var dt = new Date();
console.log(dt.toIsoString());
149
Steven Moseley

getTimezoneOffset()は、参照した仕様に必要な形式の反対符号を返します。

この形式は、 ISO8601 、またはより正確には RFC3339 とも呼ばれます。

この形式では、UTCはZで表されますが、他のすべての形式はUTCからのオフセットで表されます。意味はJavaScriptと同じですが、減算の順序が逆になっているため、結果には逆の符号が付きます。

また、Dateと呼ばれるネイティブformatオブジェクトにはメソッドがないため、これを実現するためにライブラリを使用していない限り、#1の関数は失敗します。 このドキュメント を参照してください。

この形式で直接動作できるライブラリを探している場合は、 moment.js を試すことをお勧めします。実際、これはデフォルトの形式なので、次のように簡単に実行できます。

var m = moment();    // get "now" as a moment
var s = m.format();  // the ISO format is the default so no parameters are needed

// sample output:   2013-07-01T17:55:13-07:00

これは十分にテストされたクロスブラウザソリューションであり、他にも多くの便利な機能があります。

62

これはクライアントのタイムゾーンに対する私の機能であり、軽量でシンプルです

  function getCurrentDateTimeMySql() {        
      var tzoffset = (new Date()).getTimezoneOffset() * 60000; //offset in milliseconds
      var localISOTime = (new Date(Date.now() - tzoffset)).toISOString().slice(0, 19).replace('T', ' ');
      var mySqlDT = localISOTime;
      return mySqlDT;
  }
2
Bbb

これをチェックして:

function dateToLocalISO(date) {
    const off    = date.getTimezoneOffset()
    const absoff = Math.abs(off)
    return (new Date(date.getTime() - off*60*1000).toISOString().substr(0,23) +
            (off > 0 ? '-' : '+') + 
            (absoff / 60).toFixed(0).padStart(2,'0') + ':' + 
            (absoff % 60).toString().padStart(2,'0'))
}

// Test it:
d = new Date()

dateToLocalISO(d)
// ==> '2019-06-21T16:07:22.181-03:00'

// Is similar to:

moment = require('moment')
moment(d).format('YYYY-MM-DDTHH:mm:ss.SSSZ') 
// ==> '2019-06-21T16:07:22.181-03:00'
0
Nahuel Greco

ちょうど私の2人がここに送ります

私は日時でこの問題に直面していたので、私がしたことはこれです:

const moment = require('moment-timezone')

const date = moment.tz('America/Bogota').format()

次に、日付をdbに保存して、クエリから日付を比較できるようにします。


moment-timezoneをインストールするには

npm i moment-timezone
0