Xác định múi giờ của người dùng


610

Có cách nào chuẩn để máy chủ web có thể xác định múi giờ của người dùng trong trang web không?

Có lẽ từ một tiêu đề HTTP hoặc một phần của user-agentchuỗi?


6
Hỏi người dùng. Nếu bạn lấy múi giờ từ máy tính của người dùng và nó được đặt sai, thì sao?
Rob Williams

40
Sau đó, người dùng có thể không quan tâm?
agnoster


2
Thật không may, các câu trả lời cho câu hỏi này cũng cho phép người dùng lập hồ sơ và định vị địa lý.
William Entriken

1
Tại sao bạn cần biết múi giờ người dùng?
Braiam

Câu trả lời:


326
-new Date().getTimezoneOffset()/60;

Phương pháp getTimezoneOffset()sẽ trừ thời gian của bạn khỏi GMT và trả về số phút. Vì vậy, nếu bạn sống trong GMT-8, nó sẽ trả về 480.

Để tính số này thành giờ, chia cho 60. Ngoài ra, hãy lưu ý rằng dấu hiệu ngược lại với những gì bạn cần - đó là tính toán bù giờ của GMT từ múi giờ của bạn chứ không phải bù giờ của GMT từ GMT. Để khắc phục điều này, chỉ cần nhân với -1.

Cũng lưu ý rằng w3school nói:

Giá trị trả về không phải là hằng số, do thực tế sử dụng Giờ tiết kiệm ánh sáng ban ngày.


5
Còn người dùng sử dụng điện thoại di động có trình duyệt không hỗ trợ javascript thì sao? Tôi thích câu hỏi, người dùng hỏi về tiêu đề HTTP, tác nhân người dùng ... có cách nào để làm cho phía máy chủ hoạt động này, chính xác nhất có thể không?
Nischal

18
Điều này không phải lúc nào cũng hoạt động cho DST. Nhận bù múi giờ thực hiện chính xác những gì nó nói. Nó nhận được sự bù đắp. Một thời gian thực sự là một khu vực địa lý. Điều này sẽ không hoạt động để tiết kiệm ánh sáng ban ngày vì bạn không biết người dùng sống ở bán cầu nào, hoặc nếu quốc gia của họ thậm chí có tiết kiệm ánh sáng ban ngày. Tại sao không sử dụng cái này thay thế:>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
Keyo

20
Tôi cầu xin khác với Keyo. Định nghĩa của getTimezone Offerset () (theo tiêu chuẩn ECMA ecma-i Intl.org/ecma-262/5.1/#sec-15.9.5.26 ) là "Trả về sự khác biệt giữa thời gian địa phương và thời gian UTC tính bằng phút." - nói cách khác, cần tính đến tiết kiệm ánh sáng ban ngày. Tài liệu của Mozilla cho biết "Thời gian tiết kiệm ánh sáng ban ngày ngăn giá trị này không đổi ngay cả đối với một miền địa phương nhất định."
xgretsch

11
@xgretsch: Nó được bù hiện tại của người dùng từ GMT. Điều đó tốt nếu bạn trình bày một thời điểm khác xảy ra trong cùng một ngày (trừ khi ngày hiện tại là ngày thay đổi, nơi có thể sai). Tuy nhiên, có nhiều múi giờ có cùng độ lệch so với GMT và chúng có thể có các ngày thay đổi khác nhau hoặc không sử dụng tiết kiệm ánh sáng ban ngày.
Mike Dimmick

12
Một điều cần lưu ý ở đây; một số nơi (chẳng hạn như Newfoundland ở Canada) có các múi giờ tắt sau nửa giờ, vì vậy sau khi chia cho 60 câu trả lời của bạn có thể không phải là số nguyên.
Jason Walton

193

Cách phổ biến nhất (== tiêu chuẩn?) Để xác định múi giờ tôi thấy xung quanh chỉ đơn giản là tự hỏi người dùng. Nếu trang web của bạn yêu cầu đăng ký, điều này có thể được lưu trong dữ liệu hồ sơ của người dùng. Đối với người dùng anon, ngày có thể được hiển thị dưới dạng UTC hoặc GMT hoặc một số như vậy.

Tôi không cố gắng trở thành một người thông minh. Chỉ là đôi khi một số vấn đề có giải pháp tốt hơn bên ngoài bất kỳ bối cảnh lập trình nào.


5
Còn khi người dùng đang tải xuống tệp .ics cần có thời gian bắt đầu cụ thể cho vị trí của họ (ví dụ: 9-11 giờ sáng trên toàn quốc) thì sao? Họ không nên nói múi giờ của họ là imo.
Marcy Sutton

33
@Ishmaeel: nhưng người dùng đi du lịch quốc tế và họ không cần phải nói múi giờ của họ mỗi lần họ đăng nhập từ một số múi giờ không phải người bản địa
Rajat Gupta

10
Điều này không trả lời câu hỏi, trong đó ngụ ý rõ ràng anh ta đang tìm kiếm một giải pháp công nghệ.
G-Wiz

5
@gWiz OP đang yêu cầu một giải pháp tiêu chuẩn. Đây là tiêu chuẩn khá.
Simon Bergot

4
Giải pháp tốt nhất có lẽ là kết hợp hỏi người dùng (ví dụ: cung cấp thả xuống múi giờ ở đầu báo cáo), trong khi mặc định lựa chọn thả xuống thành múi giờ do GPS xác định khi người dùng sử dụng điện thoại di động thiết bị cung cấp thông tin vị trí và mặc định là UTC.
Triynko

132

Cho đến nay, không có tiêu đề HTTP nào sẽ báo cáo múi giờ của máy khách mặc dù nó đã được đề xuất đưa nó vào đặc tả HTTP.

Nếu là tôi, có lẽ tôi sẽ cố gắng tìm nạp múi giờ bằng cách sử dụng JavaScript của máy khách và sau đó gửi nó đến máy chủ bằng Ajax hoặc một cái gì đó.


16
Kỳ lạ thay, đây là câu trả lời đúng duy nhất cho câu hỏi, trong đó hỏi làm thế nào để làm điều đó phía máy chủ. Tôi nghi ngờ lý do có những câu trả lời khác với nhiều phiếu bầu hơn là bởi vì một khi bạn nhận ra rằng bạn cần phải làm điều đó phía khách hàng, cuối cùng bạn sẽ sử dụng các câu trả lời khác. Nhưng bất cứ ai cũng ủng hộ câu trả lời khác cũng nên nâng cao câu trả lời này.
TTT

Tôi tin rằng phương pháp tốt nhất là sử dụng vị trí ip địa lý để sắp xếp các múi giờ có thể và theo mặc định, chọn vị trí đầu tiên phù hợp với thời gian của tác nhân người dùng (bắt buộc phải có JavaScript). Ngay cả sau đó, bạn phải cung cấp một cách để sửa múi giờ sau khi ngay cả phương pháp này sẽ chọn sai.
Mikko Rantalainen

@MikkoRantalainen cẩn thận khi sử dụng proxy qua, vì họ không luôn quảng cáo bản thân trong các tiêu đề.
Matthieu

@Matthieu tồn tại một câu trả lời tốt hơn hiện nay: stackoverflow.com/a/11836123/334451
Mikko Rantalainen

2
Đây thực sự là câu trả lời duy nhất thực sự giải quyết câu hỏi được đặt ra.
lscoughlin

54

JavaScript là cách dễ nhất để lấy giờ địa phương của khách hàng. Tôi sẽ đề nghị sử dụng XMLHttpRequest để gửi lại giờ địa phương và nếu thất bại, hãy quay lại múi giờ được phát hiện dựa trên địa chỉ IP của họ.

Theo định vị địa lý, tôi đã sử dụng MaxMind GeoIP trên một số dự án và nó hoạt động tốt, mặc dù tôi không chắc liệu chúng có cung cấp dữ liệu múi giờ hay không. Đó là một dịch vụ bạn trả tiền và họ cung cấp cập nhật hàng tháng cho cơ sở dữ liệu của bạn. Họ cung cấp trình bao bọc trong một số ngôn ngữ web.


Tôi đã bỏ phiếu cho câu trả lời này vì vĩ độ và kinh độ thu được từ các cơ sở dữ liệu như GeoIP (hiện có phiên bản miễn phí) có thể được kết hợp với cơ sở dữ liệu chuyển đổi tọa độ như vậy thành múi giờ. Tôi nghĩ GeoNames có cơ sở dữ liệu như vậy.
Peter O.

Các phiên bản hiện tại (cả miễn phí và trả phí) của cơ sở dữ liệu / API MaxMind GeoIP, thực sự cung cấp thông tin múi giờ (nó trả về "Châu Âu / Luân Đôn" cho múi giờ của tôi.) Tôi không thể nhớ liệu phiên bản cũ của hệ thống GeoIP của họ đã làm như vậy, nhưng nó hoạt động rất tốt bây giờ! Các trường MaxMind được đặt tên là "time_zone", "time_zone_name".
Matthew Slyman

51

Trước tiên, hãy hiểu rằng phát hiện múi giờ trong JavaScript là không hoàn hảo. Bạn có thể lấy phần bù múi giờ địa phương cho một ngày và thời gian cụ thể bằng cách sử dụng getTimezoneOffsetmột thể hiện của Dateđối tượng, nhưng nó không hoàn toàn giống với múi giờ IANA đầy đủ như thế nào America/Los_Angeles.

Có một số tùy chọn có thể làm việc mặc dù:

  • Hầu hết các trình duyệt hiện đại đều hỗ trợ múi giờ IANA trong việc triển khai API quốc tế hóa ECMAScript , vì vậy bạn có thể làm điều này:

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

Kết quả là một chuỗi chứa cài đặt múi giờ IANA của máy tính nơi mã đang chạy.

Các môi trường được hỗ trợ được liệt kê trong bảng tương thích Intl . Mở rộng DateTimeFormatphần, và nhìn vào tính năng được đặt tên resolvedOptions().timeZone defaults to the host environment.

  • Một số thư viện, chẳng hạn như Luxon sử dụng API này để xác định múi giờ thông qua các chức năng như luxon.Settings.defaultZoneName.

    • Nếu bạn cần hỗ trợ một tập hợp môi trường rộng hơn, chẳng hạn như các trình duyệt web cũ hơn, bạn có thể sử dụng thư viện để đưa ra phỏng đoán có giáo dục theo múi giờ. Chúng hoạt động bằng cách thử IntlAPI đầu tiên nếu có, và khi không có sẵn, chúng sẽ thẩm vấn getTimezoneOffsetchức năng của Dateđối tượng, trong một số thời điểm khác nhau, sử dụng kết quả để chọn múi giờ thích hợp từ bộ dữ liệu nội bộ.

    Cả jsTimezoneDetecttime -timezone đều có chức năng này.

    // using jsTimeZoneDetect
    var tzid = jstz.determine().name();
    
    // using moment-timezone
    var tzid = moment.tz.guess();

    Trong cả hai trường hợp, kết quả chỉ có thể được coi là phỏng đoán. Dự đoán có thể đúng trong nhiều trường hợp, nhưng không phải tất cả chúng.

    Ngoài ra, các thư viện này phải được cập nhật định kỳ để chống lại thực tế là nhiều triển khai JavaScript cũ hơn chỉ biết về quy tắc thời gian tiết kiệm ánh sáng ban ngày hiện tại cho múi giờ địa phương của chúng. Thêm chi tiết về điều đó ở đây.

Cuối cùng, một cách tiếp cận tốt hơn là thực sự hỏi người dùng của bạn về múi giờ của họ. Cung cấp một cài đặt mà họ có thể thay đổi. Bạn có thể sử dụng một trong các tùy chọn ở trên để chọn cài đặt mặc định , nhưng đừng làm cho nó không thể đi chệch khỏi đó trong ứng dụng của bạn.

Ngoài ra còn có cách tiếp cận hoàn toàn khác nhau về việc không dựa vào cài đặt múi giờ của máy tính người dùng. Thay vào đó, nếu bạn có thể thu thập các tọa độ kinh độ và vĩ độ, bạn có thể giải quyết chúng theo múi giờ bằng một trong các phương pháp này . Điều này hoạt động tốt trên các thiết bị di động.


Sử dụng vị trí địa lý của người dùng (tức là địa phương của họ) để suy ra múi giờ cũng là thiếu sót. Người dùng có thể muốn sử dụng một múi giờ cụ thể trên thiết bị của họ không phải là múi giờ địa phương, thậm chí còn nghĩ rằng nó có thể hiển thị cùng thời gian (hoặc không). Ví dụ: khách du lịch thường để các thiết bị của họ với múi giờ được đặt thành địa phương thông thường của họ và không mong đợi thấy ngày và giờ sử dụng một mức bù khác nhau mà không được thông báo. Tôi có thể nói từ kinh nghiệm cá nhân ở đây
;;)

Không thể biết nếu bạn đang troll tôi Rob. ;) Nhưng không có cách tiếp cận nào trong số này sử dụng ngôn ngữ của họ, mà là cài đặt trên thiết bị, do đó, phù hợp với quan điểm của bạn. (Chỉ cách tiếp cận thay thế được đề cập trong đoạn cuối mới sử dụng vị trí hiện tại.)
Matt Johnson-Pint

Đi sâu vào với một lưu ý thuật ngữ: "miền địa phương" rõ ràng không phải là vị trí địa lý của người dùng. "Địa điểm" là một nhóm các cài đặt, chẳng hạn như ngôn ngữ, định dạng số, lịch, v.v. như lịch Xem developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/iêu
azernik

49

Đây là một giải pháp JavaScript mạnh mẽ để xác định múi giờ của trình duyệt.

>>> var timezone = jstz.determine();
>>> timezone.name(); 
"Europe/London"

https://bitbucket.org/pellepim/jstimezencedetect

Phụ lục 1: Bây giờ dự án này nằm trên GitHub: https://github.com/pellepim/jstimezencedetect


14
Câu trả lời chỉ liên kết không được khuyến khích, bởi vì nếu liên kết biến mất, câu trả lời không còn hữu ích; và bởi vì không theo liên kết, độc giả không biết liệu nó có cho câu trả lời hay không. Trong trường hợp này, bạn có thể làm rõ rằng đây là thư viện của bên thứ 3 sử dụng cách tiếp cận dựa trên cơ sở dữ liệu để nhận dạng và có thể giải thích một số nguyên tắc hoạt động của nó.
IMSoP 2/2/2015

1
Điều này! Đây là con đường để đi. Thư viện đơn giản, xử lý DST đúng cách. Các câu trả lời khác chứa đầy WTF và nhiều người không làm DST.
Dirbaio

1
Thư viện này rất thông minh. Nó hoạt động bằng cách truy vấn offset hiện tại vào UTC, sau đó điều chỉnh thời gian đối tượng Ngày JavaScript bằng cách thêm hoặc trừ giây cho đến khi bù vào thay đổi UTC. Sử dụng phương pháp này thư viện này chỉ ra nhiều thay đổi DST đủ để xác định duy nhất múi giờ. Tôi nghĩ rằng thư viện có thể có hiệu suất thậm chí tốt hơn nếu nó đã tìm kiếm nhị phân thay vì tìm kiếm tuyến tính. Giá trị trả về là khóa thông tin vùng IANA (còn gọi là cơ sở dữ liệu múi giờ Olson).
Mikko Rantalainen

3
Thư viện này không còn cần thiết. Các trình duyệt hiện đại hỗ trợ API Intl, trả về chuỗi múi giờ IANA. Xem câu trả lời này .
Dan Dascalescu 17/03/19

42

Đây là một cách đầy đủ hơn.

  1. Lấy phần bù múi giờ cho người dùng
  2. Kiểm tra một số ngày trên ranh giới tiết kiệm ánh sáng ban ngày để xác định xem chúng có ở trong khu vực sử dụng tiết kiệm ánh sáng ban ngày không.

Một đoạn trích dưới đây:

function TimezoneDetect(){
    var dtDate = new Date('1/1/' + (new Date()).getUTCFullYear());
    var intOffset = 10000; //set initial offset high so it is adjusted on the first attempt
    var intMonth;
    var intHoursUtc;
    var intHours;
    var intDaysMultiplyBy;

    // Go through each month to find the lowest offset to account for DST
    for (intMonth=0;intMonth < 12;intMonth++){
        //go to the next month
        dtDate.setUTCMonth(dtDate.getUTCMonth() + 1);

        // To ignore daylight saving time look for the lowest offset.
        // Since, during DST, the clock moves forward, it'll be a bigger number.
        if (intOffset > (dtDate.getTimezoneOffset() * (-1))){
            intOffset = (dtDate.getTimezoneOffset() * (-1));
        }
    }

    return intOffset;
}

Nhận TZ và DST từ JS (thông qua Way Back Machine)


Điều này làm việc cho tôi! Đọc các bình luận dưới bài viết trên blog để biết một vài cập nhật về mã.
arlomedia

Điều này sẽ vẫn chỉ trả về độ lệch chuẩn cho múi giờ, chẳng hạn như +02: 00. Nó sẽ không cung cấp cho bạn đủ thông tin để xác định múi giờ của người dùng, chẳng hạn như Africa/Johannesburghoặc Europe/Istanbul. Xem wiki thẻ thời gian .
Matt Johnson-Pint

32

Sử dụng cách tiếp cận của Unkwntech, tôi đã viết một hàm bằng jQuery và PHP. Điều này đã được thử nghiệm và không hoạt động!

Trên trang PHP nơi bạn muốn có múi giờ dưới dạng biến, hãy đặt đoạn mã này ở đâu đó gần đầu trang:

<?php
    session_start();
    $timezone = $_SESSION['time'];
?>

Điều này sẽ đọc biến phiên "thời gian" mà chúng ta sắp tạo.

Trên cùng một trang, trong <head>, trước hết bạn cần bao gồm jQuery:

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>

Ngoài ra trong <head>, bên dưới jQuery, hãy dán cái này:

<script type="text/javascript">
    $(document).ready(function() {
        if("<?php echo $timezone; ?>".length==0){
            var visitortime = new Date();
            var visitortimezone = "GMT " + -visitortime.getTimezoneOffset()/60;
            $.ajax({
                type: "GET",
                url: "http://example.org/timezone.php",
                data: 'time='+ visitortimezone,
                success: function(){
                    location.reload();
                }
            });
        }
    });
</script>

Bạn có thể hoặc không thể nhận thấy, nhưng bạn cần thay đổi URL thành tên miền thực của bạn.

Một điều cuối cùng. Có lẽ bạn đang tự hỏi timezone.php là cái quái gì. Vâng, nó chỉ đơn giản là thế này: (tạo một tệp mới gọi là timezone.php và trỏ đến nó bằng URL ở trên)

<?php
    session_start();
    $_SESSION['time'] = $_GET['time'];
?>

Nếu điều này hoạt động chính xác, trước tiên nó sẽ tải trang, thực thi JavaScript và tải lại trang. Sau đó, bạn sẽ có thể đọc biến $ timezone và sử dụng nó để bạn hài lòng! Nó trả về độ lệch múi giờ UTC / GMT hiện tại (GMT -7) hoặc bất kỳ múi giờ nào bạn đang ở.


Tôi thích điều này, nhưng tôi có thể có thứ gì đó kiểm tra $ _SESSION ['time'] hiện tại và chỉ lấy javascript để tải lại nếu nó khác
Christopher Chase

1
Có thể sử dụng Cookie dễ dàng hơn Phiên để vận chuyển điều này, vì việc khóa và hủy kích hoạt phiên PHP có thể gây ra sự chậm chạp trong ứng dụng của bạn. Để đạt hiệu quả tối đa, bạn có thể sao chép giá trị vào phiên và xóa cookie để nó không được gửi trong các yêu cầu tiếp theo.
IMSoP 2/2/2015

25

Để gửi phần bù múi giờ dưới dạng tiêu đề HTTP trên các yêu cầu AJAX với jQuery

$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        xhr.setRequestHeader("X-TZ-Offset", -new Date().getTimezoneOffset()/60);
    }
});

Bạn cũng có thể làm điều gì đó tương tự để lấy tên múi giờ thực tế bằng cách sử dụng moment.tz.guess();từ http://momentjs.com/timezone/docs/#/USE-timezones/guessing-user-timezone/


1
Điều này chỉ trả về phần bù múi giờ hiện tại - không phải múi giờ . Xem wiki thẻ thời gian .
Matt Johnson-Pint

Đã chỉnh sửa để bao gồm thông tin về cách thực hiện tương tự cho tên múi giờ.
philfreo

24

Tôi vẫn chưa thấy một câu trả lời chi tiết ở đây có được múi giờ. Bạn không cần mã hóa địa chỉ theo địa chỉ IP hoặc sử dụng PHP (lol) hoặc đoán không chính xác từ phần bù.

Thứ nhất, múi giờ không chỉ là phần bù từ GMT. Đây là một diện tích đất trong đó các quy tắc thời gian được thiết lập theo tiêu chuẩn địa phương. Một số quốc gia có tiết kiệm ánh sáng ban ngày và sẽ bật DST vào các thời điểm khác nhau. Điều quan trọng là phải có được vùng thực tế, không chỉ là phần bù hiện tại.

Nếu bạn có ý định lưu trữ múi giờ này, ví dụ như trong tùy chọn người dùng, bạn muốn vùng đó chứ không chỉ là phần bù. Đối với chuyển đổi thời gian thực, nó sẽ không quan trọng nhiều.

Bây giờ, để có được múi giờ với javascript, bạn có thể sử dụng điều này:

>> new Date().toTimeString();
"15:46:04 GMT+1200 (New Zealand Standard Time)"
//Use some regular expression to extract the time.

Tuy nhiên, tôi thấy dễ dàng hơn khi sử dụng plugin mạnh mẽ này trả về múi giờ được định dạng Olsen:

https://github.com/scottwater/jquery.detect_timezone


22

Với datechức năng PHP, bạn sẽ có được thời gian ngày của máy chủ mà trang web được đặt. Cách duy nhất để có được thời gian của người dùng là sử dụng JavaScript.

Nhưng tôi khuyên bạn nên, nếu trang web của bạn có yêu cầu đăng ký thì cách tốt nhất là yêu cầu người dùng trong khi phải đăng ký như một lĩnh vực bắt buộc. Bạn có thể liệt kê các múi giờ khác nhau trong trang đăng ký và lưu nó trong cơ sở dữ liệu. Sau này, nếu người dùng đăng nhập vào trang thì bạn có thể đặt múi giờ mặc định cho phiên đó theo múi giờ đã chọn của người dùng.

Bạn có thể đặt bất kỳ múi giờ cụ thể bằng hàm PHP date_default_timezone_set. Điều này đặt múi giờ được chỉ định cho người dùng.

Về cơ bản múi giờ của người dùng được chuyển sang phía máy khách, vì vậy chúng ta phải sử dụng JavaScript cho việc này.

Dưới đây là tập lệnh để lấy múi giờ của người dùng bằng PHP và JavaScript.

<?php
    #http://www.php.net/manual/en/timezones.php List of Time Zones
    function showclienttime()
    {
        if(!isset($_COOKIE['GMT_bias']))
        {
?>

            <script type="text/javascript">
                var Cookies = {};
                Cookies.create = function (name, value, days) {
                    if (days) {
                        var date = new Date();
                        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
                        var expires = "; expires=" + date.toGMTString();
                    }
                    else {
                        var expires = "";
                    }
                    document.cookie = name + "=" + value + expires + "; path=/";
                    this[name] = value;
                }

                var now = new Date();
                Cookies.create("GMT_bias",now.getTimezoneOffset(),1);
                window.location = "<?php echo $_SERVER['PHP_SELF'];?>";
            </script>

            <?php

        }
        else {
          $fct_clientbias = $_COOKIE['GMT_bias'];
        }

        $fct_servertimedata = gettimeofday();
        $fct_servertime = $fct_servertimedata['sec'];
        $fct_serverbias = $fct_servertimedata['minuteswest'];
        $fct_totalbias = $fct_serverbias  $fct_clientbias;
        $fct_totalbias = $fct_totalbias * 60;
        $fct_clienttimestamp = $fct_servertime + $fct_totalbias;
        $fct_time = time();
        $fct_year = strftime("%Y", $fct_clienttimestamp);
        $fct_month = strftime("%B", $fct_clienttimestamp);
        $fct_day = strftime("%d", $fct_clienttimestamp);
        $fct_hour = strftime("%I", $fct_clienttimestamp);
        $fct_minute = strftime("%M", $fct_clienttimestamp);
        $fct_second = strftime("%S", $fct_clienttimestamp);
        $fct_am_pm = strftime("%p", $fct_clienttimestamp);
        echo $fct_day.", ".$fct_month." ".$fct_year." ( ".$fct_hour.":".$fct_minute.":".$fct_second." ".$fct_am_pm." )";
    }

    showclienttime();
?>

Nhưng theo quan điểm của tôi, tốt hơn là hỏi người dùng nếu đăng ký là bắt buộc trong dự án của bạn.


22

Không sử dụng địa chỉ IP để xác định chính xác vị trí (và do đó là múi giờ) - đó là vì với NAT, proxy (ngày càng phổ biến) và VPN, địa chỉ IP không nhất thiết phản ánh thực tế vị trí thực tế của người dùng, nhưng vị trí mà tại đó máy chủ thực hiện các giao thức cư trú.

Tương tự như cách mã vùng của Hoa Kỳ không còn hữu ích cho việc định vị người dùng điện thoại, do tính phổ biến của tính di động số.

Địa chỉ IP và các kỹ thuật khác được hiển thị ở trên rất hữu ích để đề xuất một mặc định mà người dùng có thể điều chỉnh / sửa.


21

JavaScript:

function maketimus(timestampz)
{
    var linktime = new Date(timestampz * 1000);
    var linkday = linktime.getDate();
    var freakingmonths = new Array();

    freakingmonths[0]  = "jan";
    freakingmonths[1]  = "feb";
    freakingmonths[2]  = "mar";
    freakingmonths[3]  = "apr";
    freakingmonths[4]  = "may";
    freakingmonths[5]  = "jun";
    freakingmonths[6]  = "jul";
    freakingmonths[7]  = "aug";
    freakingmonths[8]  = "sep";
    freakingmonths[9]  = "oct";
    freakingmonths[10] = "nov";
    freakingmonths[11] = "dec";

    var linkmonthnum = linktime.getMonth();
    var linkmonth = freakingmonths[linkmonthnum];
    var linkyear = linktime.getFullYear();
    var linkhour = linktime.getHours();
    var linkminute = linktime.getMinutes();

    if (linkminute < 10)
    {
        linkminute = "0" + linkminute;
    }

    var fomratedtime = linkday + linkmonth + linkyear + " " +
                       linkhour + ":" + linkminute + "h";
    return fomratedtime;
}

Đơn giản chỉ cần cung cấp thời gian của bạn ở định dạng dấu thời gian Unix cho chức năng này; JavaScript đã biết múi giờ của người dùng.

Như thế này:

PHP:

echo '<script type="text/javascript">
var eltimio = maketimus('.$unix_timestamp_ofshiz.');
document.write(eltimio);
</script><noscript>pls enable javascript</noscript>';

Điều này sẽ luôn hiển thị thời gian chính xác dựa trên múi giờ mà người đó đã đặt trên đồng hồ máy tính của anh ấy / cô ấy. Không cần phải hỏi bất cứ ai và lưu nó vào nơi, cảm ơn chúa!


$ unix_timestamp_ofshiz? Một cái gì đó bị thiếu ở đây và không hoạt động tốt, mặc dù điều này có vẻ như nó có thể là một câu trả lời tốt.

20

Dễ dàng, chỉ cần sử dụng getTimezoneOffsetchức năng JavaScript như vậy:

-new Date().getTimezoneOffset()/60;

1
Đây là một chức năng Javascript, không phải là một chức năng PHP.
cincodenada

Ngoài ra, nó chỉ trả về phần bù múi giờ hiện tại - không phải múi giờ . Xem wiki thẻ thời gian .
Matt Johnson-Pint

3
Đây chỉ là một bản sao của câu trả lời được chấp nhận, tại sao bạn thậm chí bỏ phiếu cho nó.
Rambatino

19

Tất cả các phép thuật dường như có trong

visitortime.getTimezoneOffset()

Thật tuyệt, tôi không biết về điều đó. Nó có hoạt động trong Internet Explorer, v.v.? Từ đó bạn sẽ có thể sử dụng JavaScript thành Ajax, đặt cookie, bất cứ điều gì. Có lẽ tôi sẽ tự đi theo con đường cookie.

Bạn sẽ cần phải cho phép người dùng thay đổi nó mặc dù. Chúng tôi đã cố gắng sử dụng định vị địa lý (thông qua maxmind) để thực hiện việc này một thời gian trước và điều đó thường sai một cách hợp lý - đủ để làm cho nó không đáng làm, vì vậy chúng tôi chỉ để người dùng đặt nó trong hồ sơ của họ và hiển thị thông báo cho người dùng vẫn chưa đặt chúng.


15

Dưới đây là một bài viết (với mã nguồn) giải thích cách xác định và sử dụng thời gian địa phương hóa trong ứng dụng ASP.NET (VB.NET, C #):

Đên luc rôi đây

Nói tóm lại, cách tiếp cận được mô tả dựa trên getTimezoneOffsethàm JavaScript , trả về giá trị được lưu trong cookie phiên và được sử dụng bởi mã phía sau để điều chỉnh giá trị thời gian giữa GMT và giờ địa phương. Điều tuyệt vời là người dùng không cần chỉ định múi giờ (mã tự động thực hiện). Có nhiều liên quan hơn (đây là lý do tại sao tôi liên kết đến bài viết), nhưng mã được cung cấp làm cho nó thực sự dễ sử dụng. Tôi nghi ngờ rằng bạn có thể chuyển đổi logic sang PHP và các ngôn ngữ khác (miễn là bạn hiểu ASP.NET).


1
Liên kết đã chết. Tôi nghĩ rằng đây là liên kết thay thế: devproconnections.com/article/aspnet2/it-s-about-time-122778
Gan

1
Bài viết cũng có sẵn dưới dạng PDF ở đây: app.box.com/ Shared / bfvvmidtyg
Ivaylo Slavov

Phương pháp chuyển đổi thời gian máy chủ UTC sang thời gian máy khách cục bộ được mô tả trong bài viết này là sai. Sử dụng bù máy khách hiện tại để điều chỉnh thời gian UTC trên máy chủ sẽ dẫn đến thời gian "cục bộ" không chính xác trong nửa năm đối với các địa điểm khách hàng quan sát thời gian tiết kiệm ánh sáng ban ngày. Hãy xem xét kịch bản này: một khách hàng ở Anh vào ngày 14 tháng 1 năm 2013 (GMT + 0000 Giờ chuẩn) đặt ngày và giờ là 21 tháng 8 năm 2015 14:00 (GMT + 0100 Giờ ban ngày). Điều này được chuẩn hóa trên máy chủ đến ngày 21 tháng 8 năm 2015 13:00 UTC. Vào ngày điều này xảy ra, độ lệch của máy khách là 0 nên thời gian gửi lại cho máy khách sẽ là ngày 21 tháng 8 năm 2015 13:00.
Stephen Blair

Điểm hợp lệ, nhưng tôi không khẳng định đây là một giải pháp chống đạn. Nếu bạn cần thực hiện một giải pháp thực sự nhạy cảm với thời gian, giả sử ứng dụng đặt vé tàu, thì bạn cần tìm một giải pháp toàn diện hơn (và phức tạp hơn). Tuy nhiên, đối với nhiều ứng dụng, điều này sẽ không thành vấn đề. Bởi vì trong nhiều trường hợp, chúng tôi muốn bản địa hóa các giá trị GMT cho phiên hiện tại. Bây giờ, nếu bạn có một ứng dụng cần lưu dấu thời gian cho một số ngay cả trong tương lai và nó không thể chịu đựng được DTS, thì một cách thích hợp sẽ là trình bày một tùy chọn để tiết kiệm thời gian trực tiếp trong GMT. Nếu bạn biết một lựa chọn tốt hơn, xin vui lòng chia sẻ.
Davis

14

Nếu bạn tình cờ sử dụng OpenID để xác thực, Tiện ích mở rộng đăng ký đơn giản sẽ giải quyết vấn đề cho người dùng được xác thực (Bạn sẽ cần chuyển đổi từ tz sang số).

Một lựa chọn khác là suy ra múi giờ từ tùy chọn quốc gia của tác nhân người dùng. Đây là một phương pháp hơi thô sơ (sẽ không hiệu quả với en-US), nhưng làm cho một xấp xỉ tốt.


13

Nó đơn giản với JavaScript và PHP:

Mặc dù người dùng có thể gây rối với đồng hồ bên trong và / hoặc múi giờ của mình, cách tốt nhất tôi tìm thấy cho đến nay, để lấy phần bù, vẫn còn new Date().getTimezoneOffset(); . Nó không xâm lấn, không gây đau đầu và loại bỏ sự cần thiết phải dựa vào bên thứ ba.

Nói rằng tôi có một bảng, userscó chứa một trườngdate_created int(13) , để lưu trữ dấu thời gian Unix;

Giả sử một khách hàng creates a new account, dữ liệu được nhận post, và tôi cần phải insert/updatesựdate_created column với timestamp Unix của khách hàng, không phải là máy chủ.

Vì timezone Offerset là cần thiết tại thời điểm chèn / cập nhật, nên nó được chuyển dưới dạng phần tử $ _POST bổ sung khi máy khách gửi biểu mẫu, do đó loại bỏ nhu cầu lưu trữ nó trong phiên và / hoặc cookie và không có máy chủ nào thêm vào.

var off = (-new Date().getTimezoneOffset()/60).toString();//note the '-' in front which makes it return positive for negative offsets and negative for positive offsets
var tzo = off == '0' ? 'GMT' : off.indexOf('-') > -1 ? 'GMT'+off : 'GMT+'+off;

Nói rằng máy chủ nhận được tzonhư $_POST['tzo'];

$ts = new DateTime('now', new DateTimeZone($_POST['tzo']);
$user_time = $ts->format("F j, Y, g:i a");//will return the users current time in readable format, regardless of whether date_default_timezone() is set or not.
$user_timestamp = strtotime($user_time);

Chèn / cập nhật date_created=$user_timestamp .

Khi truy xuất date_created, bạn có thể chuyển đổi dấu thời gian như vậy:

$date_created = // Get from the database
$created = date("F j, Y, g:i a",$date_created); // Return it to the user or whatever

Bây giờ, ví dụ này có thể phù hợp với nhu cầu của một người, khi nói đến việc chèn firstdấu thời gian ... Khi nói đến dấu thời gian bổ sung hoặc bảng, bạn có thể muốn xem xét chèn giá trị tzo vào bảng người dùng để tham khảo trong tương lai hoặc đặt nó như phiên hoặc dưới dạng cookie.

PS NHƯNG điều gì nếu người dùng di chuyển và chuyển đổi múi giờ. Đăng nhập vào GMT + 4, di chuyển nhanh đến GMT-1 và đăng nhập lại. Lần đăng nhập cuối cùng sẽ là trong tương lai.

Tôi nghĩ ... chúng tôi nghĩ quá nhiều.


13

Bạn có thể làm điều đó trên máy khách với múi giờ và gửi giá trị đến máy chủ; sử dụng mẫu:

> moment.tz.guess()
"America/Asuncion"

5
Tên hàm cho biết mọi thứ về độ chính xác của nó ;-)
Huyền thoại

Ngày nay, khoảnh khắc tôi không còn khuyến nghị nữa. Có những lựa chọn thay thế nhỏ hơn nhiều hiện nay ( dayjs , date-fns ). Khoảnh khắc thật lớn .
Dan Dascalescu 17/03/19

11

Lấy tên múi giờ của Cơ sở dữ liệu TZ hợp lệ trong PHP là một quá trình gồm hai bước:

  1. Với JavaScript, hãy bù thời gian trong vài phút getTimezoneOffset. Giá trị bù này sẽ dương nếu múi giờ địa phương đứng sau UTC và âm nếu đi trước. Vì vậy, bạn phải thêm một dấu hiệu ngược lại cho phần bù.

    var timezone_offset_minutes = new Date().getTimezoneOffset();
    timezone_offset_minutes = timezone_offset_minutes == 0 ? 0 : -timezone_offset_minutes;

    Truyền phần bù này cho PHP.

  2. Trong PHP chuyển đổi phần bù này thành tên múi giờ hợp lệ với hàm timezone_name_from_abbr .

    // Just an example.
    $timezone_offset_minutes = -360;  // $_GET['timezone_offset_minutes']
    
    // Convert minutes to seconds
    $timezone_name = timezone_name_from_abbr("", $timezone_offset_minutes*60, false);
    
    // America/Chicago
    echo $timezone_name;</code></pre>

Tôi đã viết một bài đăng trên blog: Cách phát hiện múi giờ người dùng trong PHP . Nó cũng chứa một bản demo.


1
Tôi nghĩ rằng một quy trình đơn giản hơn là gọi Intl.DateTimeFormat().resolvedOptions().timeZonevà gửi nó đến máy chủ web. Tham chiếu: stackoverflow.com/questions/9772955/ Mạnh
Michael Tsang


8

Một tùy chọn có thể là sử dụng trường Datetiêu đề, được xác định trong RFC 7231 và được cho là bao gồm múi giờ. Tất nhiên, không đảm bảo rằng giá trị thực sự là múi giờ của khách hàng, nhưng nó có thể là điểm khởi đầu thuận tiện.


1
Thật không may, tiêu đề đó dường như chủ yếu được thiết kế để trả lời, không phải yêu cầu: "Một tác nhân người dùng CÓ THỂ gửi trường tiêu đề Ngày trong một yêu cầu, mặc dù thường sẽ không làm như vậy trừ khi được cho là truyền thông tin hữu ích đến máy chủ." Tôi vừa kiểm tra, và Firefox không gửi nó.
IMSoP 2/2/2015

8

Đây là cách tôi làm điều đó. Điều này sẽ đặt múi giờ mặc định của PHP thành múi giờ cục bộ của người dùng. Chỉ cần dán phần sau vào đầu tất cả các trang của bạn:

<?php
session_start();

if(!isset($_SESSION['timezone']))
{
    if(!isset($_REQUEST['offset']))
    {
    ?>
        <script>
        var d = new Date()
        var offset= -d.getTimezoneOffset()/60;
        location.href = "<?php echo $_SERVER['PHP_SELF']; ?>?offset="+offset;
        </script>
        <?php   
    }
    else
    {
        $zonelist = array('Kwajalein' => -12.00, 'Pacific/Midway' => -11.00, 'Pacific/Honolulu' => -10.00, 'America/Anchorage' => -9.00, 'America/Los_Angeles' => -8.00, 'America/Denver' => -7.00, 'America/Tegucigalpa' => -6.00, 'America/New_York' => -5.00, 'America/Caracas' => -4.30, 'America/Halifax' => -4.00, 'America/St_Johns' => -3.30, 'America/Argentina/Buenos_Aires' => -3.00, 'America/Sao_Paulo' => -3.00, 'Atlantic/South_Georgia' => -2.00, 'Atlantic/Azores' => -1.00, 'Europe/Dublin' => 0, 'Europe/Belgrade' => 1.00, 'Europe/Minsk' => 2.00, 'Asia/Kuwait' => 3.00, 'Asia/Tehran' => 3.30, 'Asia/Muscat' => 4.00, 'Asia/Yekaterinburg' => 5.00, 'Asia/Kolkata' => 5.30, 'Asia/Katmandu' => 5.45, 'Asia/Dhaka' => 6.00, 'Asia/Rangoon' => 6.30, 'Asia/Krasnoyarsk' => 7.00, 'Asia/Brunei' => 8.00, 'Asia/Seoul' => 9.00, 'Australia/Darwin' => 9.30, 'Australia/Canberra' => 10.00, 'Asia/Magadan' => 11.00, 'Pacific/Fiji' => 12.00, 'Pacific/Tongatapu' => 13.00);
        $index = array_keys($zonelist, $_REQUEST['offset']);
        $_SESSION['timezone'] = $index[0];
    }
}

date_default_timezone_set($_SESSION['timezone']);

//rest of your code goes here
?>

1
Điều này không tính đến các điều chỉnh "tiết kiệm ánh sáng ban ngày" - một người dùng ở Dublin sẽ khớp với 'Châu Âu / Dublin' của bạn vào mùa đông, nhưng 'Châu Âu / Belgrade' vào mùa hè. Nếu bạn sẽ sử dụng phần bù hiện tại, tất cả những gì bạn có thể giả định một cách hợp lý là phần bù đó, không phải là định danh địa lý.
IMSoP 2/2/2015

8

Hãy thử mã PHP này:

<?php
    $ip = $_SERVER['REMOTE_ADDR'];
    $json = file_get_contents("http://api.easyjquery.com/ips/?ip=" . $ip . "&full=true");
    $json = json_decode($json,true);
    $timezone = $json['LocalTimeZone'];
?>
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.