lấy múi giờ của khách hàng từ trình duyệt


138

Có cách nào đáng tin cậy để lấy múi giờ từ trình duyệt của khách hàng không? Tôi thấy các liên kết sau đây nhưng tôi muốn một giải pháp mạnh mẽ hơn.

Tự động phát hiện múi giờ bằng JavaScript

Phát hiện múi giờ trong JavaScript



8
Tôi đã viết jsTimezoneDetect mà bạn liên kết đến ở trên, và tôi nhận thấy tình huống là nó gần giống như bạn có thể có với javascript trình duyệt chéo thuần túy (không có định vị địa lý và tra cứu IP).
Jon Nylander

Câu trả lời:


87

Nhìn vào kho lưu trữ này pageloom nó là hữu ích

tải xuống jstz.min.js và thêm chức năng vào trang html của bạn

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

và gọi chức năng này từ thẻ hiển thị của bạn


13
TL; DR Bây giờ chúng tôi có thể sử dụng Intl.DateTimeFormat().resolvedOptions().timeZone(không có IE11) theo đề xuất của Wallace.
Code4R7

194

Nửa thập kỷ sau, chúng tôi có cách tích hợp sẵn cho nó! Đối với các trình duyệt hiện đại, tôi sẽ sử dụng:

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

Điều này trả về chuỗi múi giờ IANA, nhưng không phải là phần bù . Tìm hiểu thêm tại tài liệu tham khảo MDN .

Bảng tương thích - tính đến tháng 3 năm 2019, hoạt động cho 90% trình duyệt được sử dụng trên toàn cầu. Không hoạt động trên Internet Explorer .


4
không hoạt động trong firefox: Intl.DateTimeFormat().resolvedOptions().timeZone->undefined
Tomas Tomecek

3
Firefox và IE dường như không hỗ trợ tài sản :( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/
Wallace

5
Intl.DateTimeFormat().resolvedOptions().timeZonesẽ trả về giá trị mong đợi bắt đầu từ Firefox 52: kangax.github.io/compat-table/esintl/ mẹo
julen

Làm thế nào để một người sử dụng đây là một hình thức? Trong một giá trị ẩn như được đề xuất theo developer.mozilla.org/en-US/docs/Web/HTML/Euity/input/ ,?
Hendry

4
Hoạt động trong Firefox ngay bây giờ
Dustin Michels

74

Thông thường khi mọi người đang tìm kiếm "múi giờ", cái sẽ đủ chỉ là "bù UTC". ví dụ: máy chủ của họ ở trong UTC + 5 và họ muốn biết rằng máy khách của họ đang chạy trong UTC-8 .


Trong javascript cũ đơn giản (new Date()).getTimezoneOffset()/60sẽ trả về số giờ hiện tại được bù từ UTC.

Đáng chú ý là một "gotcha" có thể có trong dấu hiệu của getTimezoneOffset()giá trị trả về (từ tài liệu MDN) :

Độ lệch múi giờ là chênh lệch, tính bằng phút, giữa UTC và giờ địa phương. Lưu ý rằng điều này có nghĩa là phần bù là dương nếu múi giờ địa phương đứng sau UTC và âm nếu nó ở phía trước. Ví dụ: đối với múi giờ UTC + 10: 00 (Giờ chuẩn miền đông Úc, Giờ Vladivostok, Giờ chuẩn Chamorro), -600 sẽ được trả về.


Tuy nhiên, tôi khuyên bạn nên sử dụng day.js cho mã Javascript liên quan đến thời gian / ngày. Trong trường hợp đó, bạn có thể nhận được bù UTC được định dạng ISO 8601 bằng cách chạy:

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

Có lẽ gấu đề cập rằng khách hàng có thể dễ dàng làm sai lệch thông tin này.

(Lưu ý: câu trả lời này ban đầu được đề xuất https://momentjs.com/ , nhưng dayjs là một lựa chọn hiện đại hơn, nhỏ hơn.)


30
Có thể đáng lưu ý rằng bù và múi giờ không nhất thiết phải giống nhau.
Dex

9
Làm thế nào bạn sẽ áp dụng DST chỉ với phần bù? Trong những khu vực đó, bù là nửa năm. IMO múi giờ chính xác hơn.
Savageman

4
DST là một phần của phần bù tại bất kỳ thời điểm nào. Giờ Trung Âu vào mùa đông là UTC + 01: 00. Tuy nhiên, khi DST được áp dụng CET là UTC + 02: 00, giống như bây giờ ở Đan Mạch nơi tôi đang ở.
Gert Sønderby

1
đây là lý do tại sao getTimezone Offerset () cần một ngày để giải quyết - nó sẽ thêm vào DST có hiệu lực tại thời điểm đó.
OsamaBinLogin

2
bù đắp không chính xác khi xem xét Tiết kiệm ánh sáng ban ngày.
Greg L.

48

Hiện tại, đặt cược tốt nhất có lẽ là jstz như được đề xuất trong câu trả lời của mbayloon .

Để hoàn thiện, cần đề cập rằng có một tiêu chuẩn theo cách của nó: Intl . Bạn có thể thấy điều này trong Chrome rồi:

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

(Điều này không thực sự tuân theo tiêu chuẩn, đó là một lý do nữa để gắn bó với thư viện)


1
Intl có vẻ ổn định trong mọi thứ trừ Safari. caniuse.com/#feat=i quốc tế hóa
Michael Cole

2
@MichaelCole Conformant triển khai của Intlcó nghĩa vụ phải trả undefinedcho các timeZonethuộc tính nếu bạn không tự xác định một múi giờ trong xây dựng DateTimeFormat. Thay vào đó, Chrome lệch khỏi tiêu chuẩn bằng cách trả lại múi giờ của hệ thống; đó là những gì câu trả lời của Julian khai thác, nhưng cũng là lý do tại sao ông nói "không thực sự tuân theo tiêu chuẩn".
Chris Jester-Young

19
FYI - tiêu chuẩn hiện là Intl.DateTimeFormat (). Đã giải quyếtOptions (). TimeZone
Nederby


4

Đây là một jsfiddle

Nó cung cấp tên viết tắt của múi giờ người dùng hiện tại.

Đây là mẫu mã

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

1
Để hiển thị ngày như May 22 2015 03:45 PM CDT tôi đã sử dụng console.log(moment(now).format('MMM DD YYYY hh:mm A') + ' ' + moment.tz.zone(tz.name()).abbr(now.getTime()));
αjiβ

5
Fiddle của bạn không hoạt động nữa và đang đưa ra lỗi trong giao diện điều khiển.
Saumil

2

Tôi đã sử dụng một cách tiếp cận tương tự như phương pháp của Josh Fraser , phương pháp này xác định thời gian bù của trình duyệt từ UTC và liệu nó có nhận ra DST hay không (nhưng phần nào được đơn giản hóa từ mã của anh ấy):

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

Khi tải, ClientTZ.getBrowserTZ()hàm được thực thi, sẽ thiết lập:

  • ClientTZ.UTCoffset để bù thời gian của trình duyệt từ UTC tính bằng phút (ví dụ: CST là −360 phút, tức là −6,0 giờ so với UTC);
  • ClientTZ.UTCoffsetTđến phần bù ở dạng '±hhmmD'(ví dụ '-0600D':), trong đó hậu tố Ddành cho DST và Scho tiêu chuẩn (không phải DST);
  • ClientTZ.hasDST (thành đúng hoặc sai).

Việc ClientTZ.UTCoffsetnày được cung cấp trong vài phút thay vì hàng giờ, bởi vì một số múi giờ có độ lệch hàng giờ (ví dụ: +0415).

Mục đích đằng sau ClientTZ.UTCoffsetTlà sử dụng nó làm chìa khóa vào bảng múi giờ (không được cung cấp ở đây), chẳng hạn như cho <select>danh sách thả xuống .


Có vẻ như nó sẽ luôn trả về 'D' nếu quan sát thấy tiết kiệm ánh sáng ban ngày. Và tại sao chỉ chênh lệch năm tháng? Chắc chắn, tháng một và tháng bảy sẽ làm việc đáng tin cậy hơn?
Matt

@Matt - Có, bạn có thể sử dụng 7-1cho tháng 7 thay vì tháng 6. Tôi không chắc liệu nó có thực sự tạo nên sự khác biệt hay không, vì tôi nghi ngờ có những kế hoạch DST khu vực không bao gồm tháng Sáu.
David R Tribble

-13

Không. Không có cách đáng tin cậy duy nhất và sẽ không bao giờ có. Bạn có thực sự nghĩ rằng bạn có thể tin tưởng khách hàng?


23
Để làm rõ: Đồng hồ của khách hàng có thể không được đặt chính xác hoặc họ có thể đang cố gắng lừa bạn nghĩ rằng họ đang ở một múi giờ khác với thực tế. Nếu bạn sẽ sử dụng múi giờ của khách hàng, đừng làm điều đó cho bất cứ điều gì quan trọng.
Ryan Kinal

7
-1 vì đã đưa ra một câu trả lời có khả năng gây hiểu lầm và không làm rõ.
Doug S

6
Có, đối với ứng dụng của tôi, tôi có thể tin tưởng khách hàng. Nếu máy khách bị cấu hình sai hoặc có lỗi, đó là trên người dùng của tôi.
Michael Cole

3
Tôi thực sự đồng ý với Florian. Phương pháp đáng tin cậy? Loại. Dữ liệu đáng tin cậy? Chắc chắn là không.
Cướp

4
Câu hỏi không cho biết dữ liệu sẽ được sử dụng như thế nào. Ví dụ, nó không nói rằng múi giờ được phát hiện sẽ được gửi đến máy chủ. Vì vậy, nhận xét về niềm tin là không liên quan nếu dữ liệu được sử dụng hoàn toàn cục bộ.
heo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.