Tentukan zona waktu pengguna

610

Apakah ada cara standar untuk server web untuk dapat menentukan zona waktu pengguna dalam halaman web?

Mungkin dari header HTTP atau bagian dari user-agentstring?

Kevin Dente
sumber
6
Tanyakan pada pengguna. Jika Anda mendapatkan zona waktu dari komputer pengguna, dan pengaturannya salah, lalu apa?
Rob Williams
40
Maka pengguna mungkin tidak peduli?
agnoster
2
Apakah maksud Anda stackoverflow.com/q/1091372/218196 ?
Felix Kling
2
Sayangnya, jawaban atas pertanyaan ini juga memungkinkan profil pengguna dan geofencing.
William Entriken
1
Mengapa Anda perlu mengetahui zona waktu pengguna?
Braiam

Jawaban:

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

Metode ini getTimezoneOffset()akan mengurangi waktu Anda dari GMT dan mengembalikan jumlah menit. Jadi jika Anda tinggal di GMT-8, itu akan mengembalikan 480.

Untuk menghitungnya menjadi berjam-jam, bagi dengan 60. Selain itu, perhatikan bahwa tandanya adalah kebalikan dari yang Anda butuhkan - itu menghitung offset GMT dari zona waktu Anda, bukan offset zona waktu Anda dari GMT. Untuk memperbaikinya, cukup kalikan dengan -1.

Perhatikan juga bahwa w3school mengatakan:

Nilai yang dikembalikan tidak konstan, karena praktik menggunakan Daylight Saving Time.

JD Isaacks
sumber
5
Bagaimana dengan pengguna yang menggunakan ponsel yang memiliki browser tanpa dukungan javascript? Saya suka pertanyaannya, pengguna bertanya tentang header HTTP, agen pengguna ... apakah ada cara untuk membuat sisi server ini bekerja, seakurat mungkin?
Nischal
19
Ini tidak selalu berhasil untuk DST. Dapatkan penggantian zona waktu sesuai dengan yang dikatakan. Itu bisa diimbangi. ZONA waktu sebenarnya adalah wilayah geografis. Ini tidak akan berfungsi untuk penghematan siang hari karena Anda tidak tahu di belahan mana pengguna tinggal, atau jika negara mereka bahkan memiliki penghematan siang hari. Mengapa tidak menggunakan ini sebagai gantinya:>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
Keyo
20
Saya mohon berbeda dengan Keyo. Definisi getTimezoneOffset () (sesuai dengan standar ECMA ecma-international.org/ecma-262/5.1/#sec-15.9.5.26 ) adalah "Mengembalikan perbedaan antara waktu lokal dan waktu UTC dalam menit." - dengan kata lain, harus memperhitungkan penghematan siang hari. Dokumentasi Mozilla mengatakan "Penghematan waktu siang hari mencegah nilai ini menjadi konstan bahkan untuk lokal tertentu."
xgretsch
12
@xgretsch: Ini mendapat offset pengguna saat ini dari GMT. Tidak apa-apa jika Anda menyajikan waktu lain yang terjadi pada hari yang sama (kecuali tanggal saat ini adalah tanggal penggantian, di mana itu bisa salah). Namun, ada banyak zona waktu yang memiliki offset yang sama dari GMT, dan mereka mungkin memiliki tanggal penggantian berbeda atau tidak menggunakan tabungan siang hari.
Mike Dimmick
13
Satu hal yang perlu diperhatikan di sini; beberapa tempat (seperti Newfoundland di Kanada) memiliki zona waktu mati setengah jam, jadi setelah membaginya dengan 60 jawaban Anda mungkin bukan bilangan bulat.
Jason Walton
193

Cara paling populer (== standar?) Untuk menentukan zona waktu yang pernah saya lihat adalah bertanya pada pengguna sendiri. Jika situs web Anda memerlukan berlangganan, ini dapat disimpan dalam data profil pengguna. Untuk pengguna lain, tanggal dapat ditampilkan sebagai UTC atau GMT atau semacamnya.

Saya tidak berusaha menjadi orang yang cerdas. Hanya saja kadang-kadang beberapa masalah memiliki solusi yang lebih baik di luar konteks pemrograman apa pun.

Ishmaeel
sumber
5
Bagaimana dengan saat pengguna mengunduh file .ics yang seharusnya memiliki waktu mulai khusus untuk lokasi mereka (mis. 9-11 pagi di seluruh negeri)? Mereka seharusnya tidak HARUS mengatakan apa zona waktu mereka.
Marcy Sutton
33
@Ishmaeel: tetapi pengguna melakukan perjalanan internasional dan mereka tidak perlu memberi tahu zona waktu mereka setiap kali mereka login dari zona waktu non-asli
Rajat Gupta
10
Ini tidak menjawab pertanyaan, yang jelas menyiratkan dia mencari solusi teknologi.
G-Wiz
5
@ gWiz OP meminta solusi standar. Ini cukup standar.
Simon Bergot
4
Solusi terbaik mungkin adalah kombinasi dari menanyakan pengguna (mis. Memberikan drop-down zona waktu di bagian atas laporan), sementara defaultkan pilihan drop down ke zona waktu yang ditentukan GPS ketika pengguna menggunakan ponsel perangkat yang menyediakan informasi lokasi, dan jika tidak default ke UTC.
Triynko
133

Tidak ada header HTTP yang akan melaporkan zona waktu klien sejauh ini meskipun telah disarankan untuk memasukkannya dalam spesifikasi HTTP.

Jika itu saya, saya mungkin akan mencoba mengambil zona waktu menggunakan JavaScript di sebelah klien dan kemudian mengirimkannya ke server menggunakan Ajax atau sesuatu.

Mads Kristiansen
sumber
16
Anehnya, ini adalah satu-satunya jawaban yang benar untuk pertanyaan itu, yang menanyakan bagaimana cara melakukannya di sisi server. Saya menduga alasan ada jawaban lain dengan lebih banyak suara adalah karena begitu Anda menyadari Anda perlu melakukannya sisi klien Anda akhirnya menggunakan jawaban lain. Tapi IMHO siapa pun yang memilih jawaban lain harus memilih jawaban ini juga.
TTT
Saya percaya metode terbaik adalah dengan menggunakan lokasi geo-ip untuk mengurutkan zona waktu yang mungkin dan secara default memilih yang pertama (tutup) cocok dengan offset waktu agen pengguna (diperlukan JavaScript). Bahkan setelah itu, Anda harus menyediakan cara untuk memperbaiki zona waktu setelah bahkan metode ini akan memilih yang salah.
Mikko Rantalainen
@MikkoRantalainen berhati-hati saat menggunakan proxy melalui, karena mereka tidak selalu mengiklankan diri mereka di header.
Matthieu
@Matthieu ada jawaban yang lebih baik saat ini: stackoverflow.com/a/11836123/334451
Mikko Rantalainen
2
Ini adalah satu-satunya jawaban yang benar-benar menjawab pertanyaan yang diajukan.
lscoughlin
54

JavaScript adalah cara termudah untuk mendapatkan waktu lokal klien. Saya akan menyarankan menggunakan XMLHttpRequest untuk mengirim kembali waktu setempat, dan jika itu gagal, kembali ke zona waktu yang terdeteksi berdasarkan alamat IP mereka.

Sejauh geolokasi, saya telah menggunakan MaxMind GeoIP pada beberapa proyek dan berfungsi dengan baik, meskipun saya tidak yakin apakah mereka menyediakan data zona waktu. Ini adalah layanan yang Anda bayar dan mereka memberikan pembaruan bulanan ke database Anda. Mereka menyediakan pembungkus dalam beberapa bahasa web.

pix0r
sumber
Saya telah memilih jawaban ini karena lintang dan bujur yang diperoleh dari basis data seperti GeoIP (yang memiliki versi gratis sekarang) dapat dikombinasikan dengan basis data yang mengubah koordinat seperti itu menjadi zona waktu. Saya pikir GeoNames memiliki basis data yang terakhir.
Peter O.
Versi saat ini (baik gratis maupun berbayar) dari database / API MaxMind GeoIP, memang menyediakan informasi zona waktu (mengembalikan "Eropa / London" untuk zona waktu saya.) Saya tidak dapat mengingat apakah versi lama sistem GeoIP mereka melakukan hal yang sama, tetapi berfungsi dengan sangat baik sekarang! Kolom MaxMind dinamai "time_zone", "time_zone_name".
Matius Slyman
51

Pertama, pahami bahwa deteksi zona waktu dalam JavaScript tidak sempurna. Anda bisa mendapatkan offset zona waktu lokal untuk tanggal dan waktu tertentu menggunakan getTimezoneOffsetinstance Dateobjek, tapi itu tidak sama dengan zona waktu IANA penuh seperti America/Los_Angeles.

Ada beberapa opsi yang dapat bekerja:

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

Hasilnya adalah string yang berisi pengaturan zona waktu IANA dari komputer tempat kode berjalan.

Lingkungan yang didukung tercantum dalam tabel kompatibilitas Intl . Buka DateTimeFormatbagian itu, dan lihat fitur yang dinamai resolvedOptions().timeZone defaults to the host environment.

  • Beberapa perpustakaan, seperti Luxon menggunakan API ini untuk menentukan zona waktu melalui fungsi-fungsi seperti luxon.Settings.defaultZoneName.

    • Jika Anda perlu mendukung serangkaian lingkungan yang lebih luas, seperti browser web yang lebih lama, Anda dapat menggunakan perpustakaan untuk membuat perkiraan yang berpendidikan di zona waktu. Mereka bekerja dengan terlebih dahulu mencoba IntlAPI jika tersedia, dan ketika itu tidak tersedia, mereka menginterogasi getTimezoneOffsetfungsi Dateobjek, untuk beberapa titik waktu yang berbeda, menggunakan hasil untuk memilih zona waktu yang sesuai dari set data internal.

    Baik jsTimezoneDetect dan moment-timezone memiliki fungsi ini.

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

    Dalam kedua kasus, hasilnya hanya dapat dianggap sebagai tebakan. Dugaan itu mungkin benar dalam banyak kasus, tetapi tidak semuanya.

    Selain itu, perpustakaan ini harus diperbarui secara berkala untuk melawan fakta bahwa banyak implementasi JavaScript yang lebih tua hanya menyadari saat daylight saving waktu aturan untuk zona waktu lokal mereka. Lebih detail tentang itu di sini.

Pada akhirnya, pendekatan yang lebih baik adalah menanyakan zona waktu mereka kepada pengguna Anda. Berikan pengaturan yang bisa diubah. Anda dapat menggunakan salah satu opsi di atas untuk memilih pengaturan default , tetapi jangan membuatnya mustahil untuk menyimpang dari itu di aplikasi Anda.

Ada juga pendekatan yang sama sekali berbeda dari tidak bergantung pada pengaturan zona waktu komputer pengguna sama sekali. Alih-alih, jika Anda bisa mengumpulkan koordinat garis lintang dan bujur, Anda bisa menyelesaikannya ke zona waktu menggunakan salah satu metode ini . Ini berfungsi baik di perangkat seluler.

Matt Johnson-Pint
sumber
Menggunakan lokasi geografis pengguna (yaitu lokal mereka) untuk menyimpulkan zona waktu juga cacat. Pengguna mungkin ingin menggunakan zona waktu tertentu pada perangkat mereka yang bukan zona waktu lokal, bahkan berpikir itu mungkin menampilkan waktu yang sama (atau tidak). Misalnya para pelancong sering meninggalkan perangkat mereka dengan zona waktu diatur ke lokasi biasanya dan tidak berharap untuk melihat tanggal dan waktu menggunakan offset berbeda tanpa disarankan. Saya mungkin berbicara dari pengalaman pribadi di sini ... ;-)
RobG
Tidak tahu apakah Anda menggangguku Rob. ;) Tetapi tidak satu pun dari pendekatan ini menggunakan lokal mereka, melainkan pengaturan pada perangkat, jadi selaras dengan poin Anda. (Hanya pendekatan alternatif yang disebutkan dalam paragraf terakhir yang akan menggunakan lokasi saat ini.)
Matt Johnson-Pint
Menyambung dengan catatan terminologi: "lokal" dengan tegas bukan lokasi geografis pengguna. "Lokal" adalah sekelompok pengaturan seperti bahasa, format angka, kalender, dll. Misalnya, lokal de_DE menentukan Jerman sebagai bahasa default, euro sebagai mata uang default, koma sebagai pemisah desimal, periode sebagai pemisah ribuan, dan Gregorian sebagai kalender. Lihat developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
azernik
49

Berikut ini adalah solusi JavaScript yang tangguh untuk menentukan zona waktu di mana browser berada.

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

https://bitbucket.org/pellepim/jstimezonedetect

Lampiran 1: Sekarang proyek ini terletak di GitHub: https://github.com/pellepim/jstimezonedetect

Adam
sumber
14
Jawaban hanya tautan tidak disarankan, karena jika tautan hilang, jawabannya tidak lagi berguna; dan karena tanpa mengikuti tautan, pembaca tidak tahu apakah itu memberikan jawaban yang baik. Dalam hal ini, Anda bisa mengklarifikasi bahwa ini adalah perpustakaan pihak ke-3 yang menggunakan pendekatan berbasis database untuk identifikasi, dan mungkin menjelaskan beberapa prinsip operasinya.
IMSoP
1
Ini! Ini cara untuk pergi. Pustaka sederhana, menangani DST dengan benar. Jawaban lain penuh dengan WTF dan banyak yang tidak melakukan DST.
Dirbaio
1
Perpustakaan ini sangat pintar. Ia bekerja dengan menanyakan offset saat ini ke UTC, kemudian menyesuaikan waktu objek Tanggal JavaScript dengan menambahkan atau mengurangi detik hingga offset ke perubahan UTC. Dengan menggunakan metode ini perpustakaan ini menemukan banyak perubahan DST yang cukup untuk mengidentifikasi zona waktu secara unik. Saya pikir perpustakaan bisa memiliki kinerja yang lebih baik jika melakukan pencarian biner daripada pencarian linear. Nilai kembali adalah kunci info zona IANA (alias basis data zona waktu Olson).
Mikko Rantalainen
3
Perpustakaan ini tidak lagi diperlukan. Browser modern mendukung API Internasional, yang mengembalikan string zona waktu IANA. Lihat jawaban ini .
Dan Dascalescu
42

Ini cara yang lebih lengkap.

  1. Dapatkan offset zona waktu untuk pengguna
  2. Tes beberapa hari pada batas daylight saving untuk menentukan apakah mereka berada di zona yang menggunakan daylight saving.

Kutipan di bawah ini:

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;
}

Mendapatkan TZ dan DST dari JS (via Way Back Machine)

Joseph Lust
sumber
Ini berhasil untuk saya! Baca komentar di bawah posting blog untuk pembaruan beberapa kode.
arlomedia
Ini hanya akan mengembalikan offset standar untuk zona waktu, seperti +02: 00. Itu tidak akan memberi Anda informasi yang cukup untuk menentukan zona waktu pengguna, seperti Africa/Johannesburgatau Europe/Istanbul. Lihat wiki tag zona waktu .
Matt Johnson-Pint
32

Menggunakan pendekatan Unkwntech, saya menulis sebuah fungsi menggunakan jQuery dan PHP. Ini diuji dan berhasil!

Pada halaman PHP tempat Anda ingin memiliki zona waktu sebagai variabel, minta potongan kode ini di suatu tempat dekat bagian atas halaman:

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

Ini akan membaca variabel sesi "waktu", yang sekarang akan kita buat.

Pada halaman yang sama, di <head>, Anda harus memasukkan jQuery:

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

Juga di <head>, di bawah jQuery, rekatkan ini:

<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>

Anda mungkin atau mungkin tidak memperhatikan, tetapi Anda perlu mengubah URL ke domain Anda yang sebenarnya.

Satu hal terakhir. Anda mungkin bertanya-tanya apa itu timezone.php. Ya begini saja: (buat file baru bernama timezone.php dan arahkan ke sana dengan URL di atas)

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

Jika ini berfungsi dengan benar, pertama-tama akan memuat halaman, menjalankan JavaScript, dan memuat kembali halaman. Anda kemudian dapat membaca variabel $ timezone dan menggunakannya untuk kesenangan Anda! Ini mengembalikan offset zona waktu UTC / GMT saat ini (GMT -7) atau zona waktu apa pun Anda berada.

Westy92
sumber
saya memang suka ini, tetapi saya mungkin memiliki sesuatu yang memeriksa $ _SESSION ['waktu'] saat ini dan hanya mendapatkan javascript untuk dimuat ulang jika berbeda
Christopher Chase
1
Mungkin lebih mudah menggunakan Cookie daripada Sesi untuk memindahkan ini, karena mengunci dan membatalkan pengunaan sesi PHP dapat menyebabkan pelambatan pada aplikasi Anda. Untuk efisiensi maksimum, Anda bisa menyalin nilai ke dalam sesi dan menghapus cookie sehingga tidak dikirim dalam permintaan berikutnya.
IMSoP
25

Untuk mengirim offset zona waktu sebagai header HTTP pada permintaan AJAX dengan jQuery

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

Anda juga dapat melakukan hal serupa untuk mendapatkan nama zona waktu yang sebenarnya dengan menggunakan moment.tz.guess(); dari http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/

philfreo
sumber
1
Ini hanya mengembalikan offset zona waktu saat ini - bukan zona waktu . Lihat wiki tag zona waktu .
Matt Johnson-Pint
Diedit untuk memasukkan info tentang melakukan hal yang sama untuk nama zona waktu.
philfreo
24

Saya masih belum melihat jawaban terperinci di sini yang mendapatkan zona waktu. Anda tidak perlu melakukan geocode berdasarkan alamat IP atau menggunakan PHP (lol) atau menebak secara salah dari offset.

Pertama, zona waktu bukan hanya offset dari GMT. Ini adalah area tanah di mana aturan waktu ditetapkan oleh standar lokal. Beberapa negara memiliki penghematan siang hari, dan akan mengaktifkan DST pada waktu yang berbeda. Biasanya penting untuk mendapatkan zona aktual, bukan hanya offset saat ini.

Jika Anda bermaksud menyimpan zona waktu ini, misalnya dalam preferensi pengguna, Anda menginginkan zona dan bukan hanya offset. Untuk konversi waktu nyata itu tidak masalah.

Sekarang, untuk mendapatkan zona waktu dengan javascript Anda dapat menggunakan ini:

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

Namun saya merasa lebih mudah untuk menggunakan plugin yang kuat ini yang mengembalikan zona waktu diformat Olsen:

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

Keyo
sumber
22

Dengan PHP date fungsi Anda akan mendapatkan tanggal waktu server tempat situs tersebut berada. Satu-satunya cara untuk mendapatkan waktu pengguna adalah menggunakan JavaScript.

Tetapi saya menyarankan Anda untuk, jika situs Anda memiliki pendaftaran yang diperlukan maka cara terbaik adalah meminta pengguna sementara untuk memiliki pendaftaran sebagai bidang wajib. Anda dapat membuat daftar berbagai zona waktu di halaman register dan menyimpannya dalam database. Setelah ini, jika pengguna masuk ke situs maka Anda dapat mengatur zona waktu default untuk sesi itu sesuai zona waktu yang dipilih pengguna.

Anda dapat mengatur zona waktu tertentu menggunakan fungsi PHP date_default_timezone_set. Ini menetapkan zona waktu yang ditentukan untuk pengguna.

Pada dasarnya zona waktu pengguna adalah ke sisi klien, jadi kita harus menggunakan JavaScript untuk ini.

Di bawah ini adalah skrip untuk mendapatkan zona waktu pengguna menggunakan PHP dan 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();
?>

Tetapi sesuai dengan sudut pandang saya, lebih baik bertanya kepada pengguna apakah pendaftaran wajib untuk proyek Anda.

Sanjay Khatri
sumber
22

Jangan gunakan alamat IP untuk menentukan lokasi secara definitif (dan karenanya zona waktu) - itu karena dengan NAT, proksi (semakin populer), dan VPN, alamat IP tidak selalu secara realistis mencerminkan lokasi sebenarnya pengguna, tetapi lokasi di mana server yang mengimplementasikan protokol tersebut berada.

Mirip dengan bagaimana kode area AS tidak lagi berguna untuk mencari pengguna telepon, mengingat popularitas portabilitas angka.

Alamat IP dan teknik lain yang ditunjukkan di atas berguna untuk menyarankan default yang dapat disesuaikan / diperbaiki pengguna.

Jaime G
sumber
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;
}

Cukup sediakan waktu Anda dalam format cap waktu Unix untuk fungsi ini; JavaScript sudah mengetahui zona waktu pengguna.

Seperti ini:

PHP:

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

Ini akan selalu menunjukkan waktu dengan benar berdasarkan zona waktu yang telah ditetapkan pada jam komputernya. Tidak perlu meminta apa pun kepada siapa pun dan menyimpannya di tempat, terima kasih Tuhan!

Envis
sumber
$ unix_timestamp_ofshiz? Ada yang hilang di sini dan tidak berfungsi, meskipun sepertinya ini bisa menjadi jawaban yang bagus.
20

Mudah, cukup gunakan getTimezoneOffsetfungsi JavaScript seperti ini:

-new Date().getTimezoneOffset()/60;
JoeyFur62
sumber
1
Ini adalah fungsi Javascript, bukan fungsi PHP.
cincodenada
Selain itu, ini hanya mengembalikan offset zona waktu saat ini - bukan zona waktu . Lihat wiki tag zona waktu .
Matt Johnson-Pint
3
Ini hanya salinan jawaban yang diterima, mengapa Anda memilihnya.
Rambatino
19

Tampaknya semua keajaiban ada di

visitortime.getTimezoneOffset()

Itu keren, saya tidak tahu tentang itu. Apakah itu berfungsi di Internet Explorer, dll? Dari sana Anda harus dapat menggunakan JavaScript untuk Ajax, mengatur cookie, apa pun. Saya mungkin akan pergi rute cookie sendiri.

Anda harus mengizinkan pengguna untuk mengubahnya. Kami mencoba menggunakan geolokasi (melalui maxmind) untuk melakukan ini beberapa waktu yang lalu, dan itu cukup sering salah - cukup untuk membuatnya tidak layak dilakukan, jadi kami hanya membiarkan pengguna mengaturnya di profil mereka, dan menunjukkan pemberitahuan kepada pengguna yang belum mengaturnya.

Orion Edwards
sumber
15

Berikut ini adalah artikel (dengan kode sumber) yang menjelaskan cara menentukan dan menggunakan waktu lokal dalam aplikasi ASP.NET (VB.NET, C #):

Ini tentang waktu

Singkatnya, pendekatan yang dijelaskan bergantung pada getTimezoneOffsetfungsi JavaScript , yang mengembalikan nilai yang disimpan dalam cookie sesi dan digunakan oleh kode-belakang untuk menyesuaikan nilai waktu antara GMT dan waktu lokal. Yang menyenangkan adalah bahwa pengguna tidak perlu menentukan zona waktu (kode melakukannya secara otomatis). Ada yang lebih terlibat (ini sebabnya saya menautkan ke artikel), tetapi kode yang disediakan membuatnya sangat mudah digunakan. Saya menduga Anda dapat mengonversi logika ke PHP dan bahasa lain (selama Anda memahami ASP.NET).

Alek Davis
sumber
1
Tautannya sudah mati. Saya pikir ini adalah tautan alternatif: devproconnections.com/article/aspnet2/it-s-about-time-122778
Gan
1
Artikel ini juga tersedia dalam bentuk PDF di sini: app.box.com/shared/bfvvmidtyg
Ivaylo Slavov
Metode mengubah waktu server UTC ke waktu klien lokal yang dijelaskan dalam artikel ini salah. Menggunakan offset klien saat ini untuk menyesuaikan waktu UTC di server akan menghasilkan waktu "lokal" yang salah selama setengah tahun untuk lokal klien yang mengamati waktu musim panas. Pertimbangkan skenario ini: klien di Inggris pada 14 Jan 2013 (GMT + 0000 Waktu Standar) menetapkan tanggal dan waktu 21 Agustus 2015 14:00 (GMT + 0100 Waktu Siang Hari). Ini dinormalisasi di server hingga 21 Agustus 2015 13:00 UTC. Pada hari ini terjadi, offset klien adalah 0 sehingga waktu yang dikirim kembali ke klien adalah 21 Agustus 2015 13:00.
Stephen Blair
Poin yang benar, tapi saya tidak mengklaim ini sebagai solusi anti peluru. Jika Anda perlu menerapkan solusi yang sangat sensitif terhadap waktu, katakanlah aplikasi pemesanan tiket kereta api, maka Anda perlu mencari solusi yang lebih komprehensif (dan kompleks). Namun, untuk banyak aplikasi ini tidak akan menjadi masalah. Karena dalam banyak kasus kami ingin melokalkan nilai GMT untuk sesi saat ini. Sekarang, jika Anda memiliki aplikasi yang perlu menghemat cap waktu untuk beberapa bahkan di masa depan dan itu tidak dapat mentolerir DTS, maka cara yang tepat adalah menyajikan opsi untuk menghemat waktu secara langsung dalam GMT. Jika Anda tahu opsi yang lebih baik, silakan bagikan.
Alek Davis
14

Jika Anda menggunakan OpenID untuk otentikasi, Ekstensi Pendaftaran Sederhana akan menyelesaikan masalah bagi pengguna yang diautentikasi (Anda harus mengonversi dari tz ke numerik).

Pilihan lain adalah menyimpulkan zona waktu dari preferensi negara agen pengguna. Ini adalah metode yang agak kasar (tidak akan bekerja untuk en-AS), tetapi membuat perkiraan yang baik.

Dmitry Shechtman
sumber
13

Sederhana dengan JavaScript dan PHP:

Meskipun pengguna dapat mengacaukan jam internal dan / atau zona waktu, cara terbaik yang saya temukan sejauh ini, untuk mendapatkan offset, tetap ada new Date().getTimezoneOffset();. Ini non-invasif, tidak membuat kepala pusing dan menghilangkan kebutuhan untuk mengandalkan pihak ketiga.

Katakanlah saya punya tabel users,, yang berisi bidang date_created int(13), untuk menyimpan cap waktu Unix;

Dengan asumsi klien creates a new account, data yang diterima oleh post, dan saya perlu insert/updateyang date_created columndengan klien Unix timestamp, bukan server.

Karena timezoneOffset diperlukan pada saat memasukkan / memperbarui, ia dilewatkan sebagai elemen $ _POST tambahan ketika klien mengirimkan formulir, sehingga menghilangkan kebutuhan untuk menyimpannya dalam sesi dan / atau cookie, dan tidak ada tambahan server yang memukul.

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;

Katakanlah server menerima tzosebagai $_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);

Sisipkan / perbarui date_created=$user_timestamp .

Saat mengambil date_created, Anda dapat mengonversi timestamp seperti:

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

Sekarang, contoh ini mungkin sesuai dengan kebutuhan seseorang, ketika harus memasukkan firststempel waktu ... Ketika datang ke stempel waktu tambahan, atau tabel, Anda mungkin ingin mempertimbangkan memasukkan nilai tzo ke dalam tabel pengguna untuk referensi di masa mendatang, atau mengaturnya sebagai sesi atau sebagai cookie.

PS TAPI bagaimana jika pengguna melakukan perjalanan dan mengganti zona waktu. Masuk pada GMT + 4, bergerak cepat ke GMT-1 dan masuk lagi. Login terakhir akan di masa depan.

Saya pikir ... kami terlalu banyak berpikir.

pria
sumber
13

Anda bisa melakukannya pada klien dengan moment-timezone dan mengirim nilai ke server; penggunaan sampel:

> moment.tz.guess()
"America/Asuncion"
Tomas Tomecek
sumber
5
Nama fungsinya menceritakan segalanya tentang akurasinya ;-)
Legends
Saat ini, moment.js saya tidak lagi direkomendasikan. Ada alternatif yang jauh lebih kecil saat ini ( dayjs , date-fns ). Momen sangat besar .
Dan Dascalescu
11

Mendapatkan nama zona waktu TZ Database yang valid dalam PHP adalah proses dua langkah:

  1. Dengan JavaScript, dapatkan offset zona waktu dalam beberapa menit getTimezoneOffset. Offset ini akan positif jika zona waktu lokal di belakang UTC dan negatif jika berada di depan. Jadi, Anda harus menambahkan tanda berlawanan dengan offset.

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

    Berikan offset ini ke PHP.

  2. Dalam PHP, ubah offset ini menjadi nama zona waktu yang valid dengan fungsi 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>

Saya telah menulis posting blog di atasnya: Cara Mendeteksi Zona Waktu Pengguna di PHP . Ini juga mengandung demo.

Sudut yang berguna
sumber
1
Saya pikir proses yang lebih sederhana adalah menelepon Intl.DateTimeFormat().resolvedOptions().timeZonedan mengirimkannya ke server web. Ref: stackoverflow.com/questions/9772955/…
Michael Tsang
9

Cara mudah untuk melakukannya adalah dengan menggunakan:

new Date().getTimezoneOffset();
Naeem Ul Wahhab
sumber
8
Mengapa Anda mengirim ulang jawaban yang identik (oleh John Isaacks) dari 2 tahun yang lalu: stackoverflow.com/a/1809974/836407 ?
chown
2
Selain itu, ini hanya mengembalikan offset zona waktu saat ini - bukan zona waktu . Lihat wiki tag zona waktu .
Matt Johnson-Pint
8

Salah satu opsi yang mungkin adalah dengan menggunakan Datebidang header, yang didefinisikan dalam RFC 7231 dan seharusnya mencakup zona waktu. Tentu saja, tidak dijamin bahwa nilainya benar-benar zona waktu klien, tetapi itu bisa menjadi titik awal yang nyaman.

Berislav Lopac
sumber
1
Sayangnya, tajuk itu tampaknya dirancang terutama untuk tanggapan, bukan permintaan: "Agen pengguna DAPAT mengirim bidang tajuk Tanggal dalam permintaan, meskipun umumnya tidak akan melakukannya kecuali jika diyakini akan menyampaikan informasi yang berguna ke server." Saya baru saja memeriksa, dan Firefox tidak mengirimkannya.
IMSoP
8

Begini cara saya melakukannya. Ini akan mengatur zona waktu default PHP ke zona waktu lokal pengguna. Cukup rekatkan yang berikut di atas semua halaman Anda:

<?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
?>
Dane Iracleous
sumber
1
Ini tidak memperhitungkan penyesuaian "penghematan siang hari" - pengguna di Dublin akan cocok dengan 'Eropa / Dublin' Anda di musim dingin, tetapi 'Eropa / Beograd' di musim panas. Jika Anda akan menggunakan offset saat ini, yang dapat Anda anggap wajar adalah offset itu, bukan pengidentifikasi geografis.
IMSoP
8

Coba kode PHP ini:

<?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'];
?>
pckabeer
sumber