ブラウザからクライアントのタイムゾーンを取得する


138

クライアントブラウザからタイムゾーンを取得する信頼できる方法はありますか?次のリンクを見ましたが、より堅牢なソリューションが必要です。

JavaScriptでタイムゾーンを自動検出する

JavaScriptでのタイムゾーン検出



8
私はあなたが上記にリンクするjsTimezoneDetectを書きました、そして私の状況は私のそれは純粋なクロスブラウザjavascript(地理位置情報とIPルックアップなしで)を得ることができるのと同じくらい近いということです。
Jon Nylander

回答:


87

このリポジトリを見てpageloomそれは便利です

jstz.min.jsをダウンロードして、htmlページに関数を追加します

<script language="javascript">
    function getTimezoneName() {
        timezone = jstz.determine()
        return timezone.name();
    }
</script>

ディスプレイタグからこの関数を呼び出します


13
TL; DRこれでIntl.DateTimeFormat().resolvedOptions().timeZone、Wallaceの提案どおり(IE11 は使用できません)を使用できます。
Code4R7 2018

194

5年後、組み込みの方法があります。最近のブラウザでは、次を使用します。

const tz = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(tz);

これはIANAタイムゾーン文字列を返しますが、オフセットは返しません。MDNリファレンスで詳細をご覧ください。

互換性テーブル -2019年3月現在、世界的に使用されているブラウザの90%で機能します。Internet Explorerでは機能しません


4
Firefoxでは機能しません:Intl.DateTimeFormat().resolvedOptions().timeZone->undefined
Tomas Tomecek

3
FirefoxとIEは、プロパティに未対応のようです:( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/...
ウォレス

5
Intl.DateTimeFormat().resolvedOptions().timeZoneFirefoxの52から始まる期待値を返します。kangax.github.io/compat-table/esintl/...
ユーレン

これはフォームをどのように使用しますか?developer.mozilla.org/en-US/docs/Web/HTML/Element/input/…で提案されている非表示の値で?
ヘンドリー

4
Firefoxで動作します
ダスティンミシェル

74

多くの場合、人々が「タイムゾーン」を探しているときは、「UTCオフセット」で十分です。たとえば、サーバーがUTC + 5にあり、クライアントがUTC-8で実行されていることを知りたいとします


昔ながらのjavascriptでは(new Date()).getTimezoneOffset()/60、UTCからの現在のオフセット時間を返します。

(MDN docsからの)getTimezoneOffset()戻り値の符号にある「問題」に注意する価値があります。

タイムゾーンオフセットは、UTCと現地時間の差(分単位)です。これは、ローカルタイムゾーンがUTCより遅れている場合はオフセットが正であり、進んでいる場合は負であることを意味します。たとえば、タイムゾーンUTC + 10:00(オーストラリア東部標準時、ウラジオストク時間、チャモロ標準時)の場合、-600が返されます。


ただし、日時に関連するJavaScriptコードにはday.jsを使用することをお勧めします。この場合、次のコマンドを実行すると、ISO 8601形式のUTCオフセットを取得できます。

> dayjs().format("Z")
"-08:00"

おそらく、クライアントがこの情報を簡単に改ざんできることについて言及しておきます。

(注:この回答はもともとhttps://momentjs.com/を推奨していましたが、dayjsはよりモダンで小さな代替手段です。)


30
オフセットとタイムゾーンは必ずしも同じではないことに注意してください。
Dex

9
オフセットのみでDSTをどのように適用しますか?それらの地域では、オフセットは半年で間違っています。IMOタイムゾーンはより正確です。
Savageman、2015

4
DSTは常にオフセットの一部です。冬の中央ヨーロッパ時間はUTC + 01:00です。ただし、DSTを適用すると、CETはUTC + 02:00になり、現在デンマークにいるようになっています。
GertSønderby2015

1
これが、getTimezoneOffset()が機能するための日付を必要とする理由です。その時点で有効なDSTに追加されます。
OsamaBinLogin 2015年

2
夏時間を考慮した場合、オフセットは正確ではありません。
グレッグL.

48

現時点では、mbayloonの回答で提案されているように、おそらく最善の策はjstzです。

完全を期すために、その方法に標準があることを言及する必要があります:Intl。これはすでにChromeで確認できます。

> Intl.DateTimeFormat().resolvedOptions().timeZone
"America/Los_Angeles"

(これは実際には標準に準拠していません。これがライブラリに固執するもう1つの理由です)


1
IntlはSafari以外はすべて安定しているように見えます。 caniuse.com/#feat=internationalization
Michael Cole

2
@MichaelColeの適合実装は、の作成時に手動でタイムゾーンを指定しなかった場合、プロパティIntlに戻ることになっています。Chromeは、代わりにシステムのタイムゾーンを返すことにより、標準から逸脱しています。それがヨハネスの答えが悪用する理由ですが、彼が「実際には標準に従っていない」と言った理由もです。undefinedtimeZoneDateTimeFormat
Chris Jester-Young、

19
FYI-標準はIntl.DateTimeFormat()。resolvedOptions()。timeZone
Nederby


4

ここにjsfiddleがあります

現在のユーザーのタイムゾーンの略称を提供します。

ここにコードサンプルがあります

var tz = jstz.determine();
console.log(tz.name());
console.log(moment.tz.zone(tz.name()).abbr(new Date().getTime()));

1
日付を表示するには、 May 22 2015 03:45 PM CDT 私が使用 console.log(moment(now).format('MMM DD YYYY hh:mm A') + ' ' + moment.tz.zone(tz.name()).abbr(now.getTime()));
αƞjiβ

5
あなたのフィドルはもう機能しておらず、コンソールでエラーが発生しています。
サウミル2016年

2

私はJosh Fraserが採用たものと同様のアプローチを使用しました。これは、UTCからのブラウザー時間オフセットと、DSTを認識するかどうかを決定します(ただし、彼のコードから多少簡略化されています)。

var ClientTZ = {
    UTCoffset:  0,          // Browser time offset from UTC in minutes
    UTCoffsetT: '+0000S',   // Browser time offset from UTC in '±hhmmD' form
    hasDST:     false,      // Browser time observes DST

    // Determine browser's timezone and DST
    getBrowserTZ: function () {
        var self = ClientTZ;

        // Determine UTC time offset
        var now = new Date();
        var date1 = new Date(now.getFullYear(), 1-1, 1, 0, 0, 0, 0);    // Jan
        var diff1 = -date1.getTimezoneOffset();
        self.UTCoffset = diff1;

        // Determine DST use
        var date2 = new Date(now.getFullYear(), 6-1, 1, 0, 0, 0, 0);    // Jun
        var diff2 = -date2.getTimezoneOffset();
        if (diff1 != diff2) {
            self.hasDST = true;
            if (diff1 - diff2 >= 0)
                self.UTCoffset = diff2;     // East of GMT
        }

        // Convert UTC offset to ±hhmmD form
        diff2 = (diff1 < 0 ? -diff1 : diff1) / 60;
        var hr = Math.floor(diff2);
        var min = diff2 - hr;
        diff2 = hr * 100 + min * 60;
        self.UTCoffsetT = (diff1 < 0 ? '-' : '+') + (hr < 10 ? '0' : '') + diff2.toString() + (self.hasDST ? 'D' : 'S');

        return self.UTCoffset;
    }
};

// Onload
ClientTZ.getBrowserTZ();

ロードされると、ClientTZ.getBrowserTZ()関数が実行され、以下を設定します。

  • ClientTZ.UTCoffset UTCからのブラウザー時間オフセット(分単位)(たとえば、CSTは-360分、つまりUTCから-6.0時間)。
  • ClientTZ.UTCoffsetTフォームのオフセット'±hhmmD'(例:)。'-0600D'サフィックスはDDSTおよびS標準(非DST)用です。
  • ClientTZ.hasDST (真または偽に)。

ClientTZ.UTCoffsetいくつかのタイムゾーンは、分数の時間ごとのオフセット(例えば、0415)を持っているので、代わりに時間の数分で提供されています。

背後にClientTZ.UTCoffsetTある意図は、それをドロップダウン<select>リストなどのタイムゾーンのテーブル(ここでは提供されていません)へのキーとして使用することです。


夏時間が観察された場合は、常に「D」を返すように見えます。そして、なぜ5か月だけの違いなのか?確かに、1月と7月はより確実に機能しますか?
マット

@マット-はい、7-16月ではなく7月に使用できます。6月を含まない地域のDSTスキームがあるのではないかと思うので、それが本当に違いがあるかどうかはわかりません。
デビッドRトリブル

-13

いいえ。信頼できる方法は1つではなく、決してありません。クライアントを信頼できると本当に思いましたか?


23
明確にするために:クライアントのクロックが正しく設定されていないか、クライアントが実際とは異なるタイムゾーンにいると悪意を持って騙そうとしている可能性があります。クライアントのタイムゾーンを使用する場合は、重要なことには使用しないでください。
Ryan Kinal

7
-1は、誤解を招く可能性のある答えを与え、明確化しないこと。
Doug S

6
はい、私のアプリケーションではクライアントを信頼できます。クライアントが正しく構成されていないかバグがある場合、それは私のユーザーにあります。
Michael Cole

3
私は実際にフロリアンに同意します。信頼できる方法?やや。信頼できるデータ?間違いなくそうではありません。
2016年

4
問題は、データがどのように使用されるかについては述べていません。たとえば、検出されたタイムゾーンがサーバーに送信されることはありません。したがって、データが純粋にローカルで使用されている場合、信頼についての注意は関係ありません。
ドルメン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.