Bir kullanıcının saat dilimini belirleme


610

Bir web sunucusunun, bir web sayfasındaki kullanıcının saat dilimini belirleyebilmesinin standart bir yolu var mı?

Belki bir HTTP üstbilgisinden veya user-agentdizenin bir bölümünden ?


6
Kullanıcıya sorun. Saat dilimini kullanıcının bilgisayarından alıyorsanız ve yanlış ayarlanmışsa ne olur?
Rob Williams

40
O zaman kullanıcı muhtemelen umursamıyor?
agnoster

2
Şunu mu demek istediniz: stackoverflow.com/q/1091372/218196 ?
Felix Kling

2
Maalesef, bu sorunun yanıtları kullanıcı profili oluşturma ve coğrafi sınırlamaya da izin vermektedir.
William Entriken

1
Neden kullanıcı saat dilimini bilmeniz gerekiyor?
Braiam

Yanıtlar:


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

Yöntem getTimezoneOffset(), zamanınızı GMT'den çıkaracak ve dakika sayısını döndürecektir. Eğer GMT-8'de yaşıyorsanız, 480 geri dönecektir.

Bunu saatlere ayırmak için 60'a bölün. Ayrıca, işaretin ihtiyacınız olanın tersi olduğuna dikkat edin - saat diliminizin GMT'den uzaklığını değil, GMT'nin ofsetini saat diliminizden hesaplar. Bunu düzeltmek için -1 ile çarpmanız yeterlidir.

Ayrıca w3school'un şunları söylediğine dikkat edin :

Yaz saati uygulaması uygulaması nedeniyle döndürülen değer sabit değildir.


5
Javascript desteği olmayan tarayıcıları olan cep telefonlarını kullanan kullanıcılar ne olacak? Soruyu beğendim, kullanıcı HTTP üstbilgileri, kullanıcı aracısı soruyor ... Bu iş sunucusu tarafını mümkün olduğunca doğru yapmanın bir yolu var mı?
Nischal

18
Bu her zaman DST için işe yaramaz. Saat dilimi ofsetini tam olarak ne diyorsa alın. Ofset olsun. Bir zaman dilimi aslında coğrafi bir alandır. Bu, kullanıcının hangi yarıkürede yaşadığını veya ülkelerinde gün ışığından yararlanma saati olup olmadığını bilmediğiniz için gün ışığından yararlanma için işe yaramaz. Bunu neden kullanmıyorsunuz:>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
Keyo

20
Keyo ile farklı olmaya yalvarıyorum. GetTimezoneOffset () tanımı (ECMA standardına göre ecma-international.org/ecma-262/5.1/#sec-15.9.5.26'ya göre ) "Yerel saat ile UTC saati arasındaki farkı dakika döndürür." - başka bir deyişle, gün ışığından tasarruf etmeyi hesaba katmalıdır. Mozilla'nın belgeleri "Yaz saati uygulaması, bu değerin belirli bir yerel ayar için bile sabit olmasını önler."
xgretsch

11
@xgretsch: Kullanıcının geçerli ofsetini GMT'den alır. Aynı gün içinde gerçekleşen başka bir saat sunuyorsanız sorun olmaz (geçerli tarih, yanlış olabileceği bir geçiş tarihi değilse). Bununla birlikte, GMT ile aynı ofsete sahip birçok zaman dilimi vardır ve farklı geçiş tarihlerine sahip olabilirler veya gün ışığından yararlanmalarını kullanamazlar.
Mike Dimmick

12
Burada dikkat edilmesi gereken bir nokta; bazı yerlerde (Kanada'daki Newfoundland gibi) yarım saat kapalı olan zaman dilimleri vardır, bu nedenle 60'a bölündükten sonra cevabınız bir tamsayı olmayabilir.
Jason Walton

193

Etrafımda gördüğüm saat dilimini belirlemenin en popüler (== standart?) Yolu , kullanıcılara sormaktır. Web siteniz abonelik gerektiriyorsa, bu kullanıcıların profil verilerine kaydedilebilir. Anon kullanıcıları için, tarihler UTC veya GMT veya benzeri olabilir.

Akıllı bir aleck olmaya çalışmıyorum. Sadece bazı problemlerin herhangi bir programlama bağlamının dışında daha ince çözümleri olabilir.


5
Bir kullanıcı, bulunduğu yere özgü bir başlangıç ​​zamanı olması gereken bir .ics dosyasını indirdiğinde (örneğin, ülke genelinde 9-11 arası)? Zaman dilimlerinin imo olduğunu söylememeli.
Marcy Sutton

33
@Ishmaeel: ancak kullanıcılar uluslararası seyahat ediyor ve yerli olmayan bir saat diliminden her giriş yaptıkları zaman saat dilimlerini söylemeleri gerekmiyor
Rajat Gupta

10
Bu, teknolojik bir çözüm aradığını açıkça ima eden soruyu cevaplamıyor.
G-Wiz

5
@gWiz OP standart bir çözüm istiyor. Bu oldukça standart.
Simon Bergot

4
En iyi çözüm muhtemelen kullanıcıya sormanın bir kombinasyonu olabilir (örneğin, raporun üstünde bir saat dilimi açılır listesi sağlayarak), kullanıcı bir mobil cihazdayken açılır seçimi GPS tarafından belirlenmiş bir saat dilimine varsayılan olarak ayarlar konum bilgisi sağlayan ve aksi takdirde varsayılan ayarı UTC olan cihaz.
Triynko

132

HTTP belirtimine dahil edilmesi önerilse de, istemcilerin saat dilimini raporlayacak hiçbir HTTP üstbilgisi yoktur.

Ben olsaydım, büyük olasılıkla, istemcinin JavaScript'ini kullanarak saat dilimini almaya ve sonra Ajax veya başka bir şey kullanarak sunucuya göndermeye çalışırdım.


16
Garip bir şekilde, bu sunucu tarafında nasıl yapılacağını soran sorunun tek doğru cevabıdır. Ben daha fazla oy ile başka cevaplar var şüpheli çünkü bir kez bunu müşteri tarafında yapmanız gerektiğini fark sonra diğer cevapları kullanarak sonunda. Ancak IMHO başka bir cevabı iptal eden herkes de bu cevabı iptal etmelidir.
TTT

En iyi yöntemin olası zaman dilimlerini sıralamak ve varsayılan olarak (yakın) kullanıcı aracısı zaman ofseti (JavaScript gerekli) ile eşleşen ilk birini seçmek için geo-ip konumu kullanmak olduğuna inanıyorum. Bundan sonra bile, bu yöntem yanlış olanı seçtikten sonra saat dilimini düzeltmek için bir yol sağlamanız gerekir.
Mikko Rantalainen

@MikkoRantalainen vekilleri kullanırken dikkatli olurlar, çünkü her zaman başlıklarda reklam vermezler.
Matthieu

@Matthieu günümüzde daha iyi bir yanıt var: stackoverflow.com/a/11836123/334451
Mikko Rantalainen

2
Gerçekten sorulan soruya cevap veren tek cevap budur.
lscoughlin

54

JavaScript, istemcinin yerel saatini almanın en kolay yoludur. Yerel saati geri göndermek için bir XMLHttpRequest kullanmanızı öneririm ve bu başarısız olursa, IP adreslerine göre belirlenen saat dilimine geri döner.

Coğrafi konum olarak, MaxMind GeoIP'i birkaç projede kullandım ve iyi çalışıyor, ancak saat dilimi verileri sağlayıp sağlamadıklarından emin değilim. Bu, ödediğiniz bir hizmettir ve veritabanınıza aylık güncellemeler sağlar. Çeşitli web dillerinde sarmalayıcılar sağlarlar.


Bu cevabı oyladım çünkü GeoIP (şu an için ücretsiz bir sürümü var) gibi veritabanlarından elde edilen enlem ve boylam, böyle bir koordinatı bir saat dilimine dönüştüren veritabanlarıyla birleştirilebilir. GeoNames böyle bir veritabanına sahip olduğunu düşünüyorum.
Peter O.

MaxMind GeoIP veritabanlarının / API'lerinin mevcut sürümleri (hem ücretsiz hem de ücretli), gerçekten de saat dilimi bilgileri sağlar (saat dilimim için "Europe / London" döndürür.) GeoIP sistemlerinin eski sürümünün olup olmadığını hatırlayamıyorum aynısını yaptı, ama şimdi çok iyi çalışıyor! MaxMind alanları "time_zone", "time_zone_name" olarak adlandırılır.
Matthew Slyman

51

İlk olarak, JavaScript'te saat dilimi algılamanın kusurlu olduğunu anlayın. Yerel alabilirsiniz ofset saat dilimini kullanarak belirli bir tarih ve saat için getTimezoneOffsetbir örneği üzerinde Datenesne, ama bu tam olarak aynı değil IANA saat diliminde gibi America/Los_Angeles.

Yine de çalışabilecek bazı seçenekler vardır:

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

Sonuç, kodun çalıştığı bilgisayarın IANA zaman dilimi ayarını içeren bir dizedir.

Desteklenen ortamlar Uluslararası uyumluluk tablosunda listelenir . DateTimeFormatBölümü genişletin ve adlı özelliğe bakın resolvedOptions().timeZone defaults to the host environment.

  • Luxon gibi bazı kütüphaneler, bu API'yi gibi işlevler aracılığıyla saat dilimini belirlemek için kullanır luxon.Settings.defaultZoneName.

    • Eski web tarayıcıları gibi daha geniş bir ortam kümesini desteklemeniz gerekiyorsa , saat diliminde eğitimli bir tahmin yapmak için bir kitaplık kullanabilirsiniz . İlk olarak, Intlkullanılabilir durumdaysa API'yı deneyerek çalışırlar ve kullanılabilir olmadığında, dahili bir veri kümesinden uygun bir saat dilimi seçmek için sonuçları kullanarak nesnenin getTimezoneOffsetişlevini Datezaman içinde birkaç farklı nokta için sorgularlar .

    Hem jsTimezoneDetect hem de moment-timezone bu işlevselliğe sahiptir.

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

    Her iki durumda da, sonuç sadece bir tahmin olarak düşünülebilir. Tahmin çoğu durumda doğru olabilir, ancak hepsi doğru olmayabilir.

    Ayrıca, bu kütüphanelerin periyodik olarak güncellenmesi gerekir ki, birçok eski JavaScript uygulaması yalnızca yerel saat dilimlerinin geçerli gün ışığından yararlanma saati kuralının farkındadır . Bununla ilgili daha fazla ayrıntı burada.

Sonuçta, daha iyi bir yaklaşım aslında kullanıcılarınızdan saat dilimlerini istemektir. Değiştirebilecekleri bir ayar sağlayın. Varsayılan bir ayar seçmek için yukarıdaki seçeneklerden birini kullanabilirsiniz , ancak uygulamanızda bu ayardan sapmayı imkansız hale getirmeyin.

Tamamen farklı bir yaklaşım da var değil hiç kullanıcının bilgisayarının saat dilimi ayarı güvenerek. Bunun yerine, enlem ve boylam koordinatlarını toplayabilirseniz , bu yöntemlerden birini kullanarak bunları bir saat dilimine çözümleyebilirsiniz . Bu, mobil cihazlarda iyi çalışır.


Zaman dilimini çıkarmak için kullanıcının coğrafi konumunu (yani yerel ayarlarını) kullanmak da kusurludur. Kullanıcılar, cihazlarında yerel saat dilimi olmayan belirli bir saat dilimini kullanmak isteyebilir, hatta aynı saati görüntüleyebileceğini (veya etmeyeceğini) düşünebilir. Örneğin yolcular, saat dilimlerini normal konumlarına ayarlı olarak cihazlarından sık sık ayrılırlar ve tarih ve saatlerin tavsiye edilmeden farklı bir ofset kullandığını görmeyi beklemezler. Burada kişisel deneyimlerimden bahsediyor olabilirim… ;-)
RobG

Bana troll atýp çalýţtýđýný söyleyemem Rob. ;) Ancak bu yaklaşımların hiçbiri yerel ayarlarını kullanmaz, daha ziyade cihazdaki ayarı kullanır, bu nedenle noktanızla hizalanır. (Yalnızca son paragrafta bahsedilen alternatif yaklaşım geçerli konumu kullanır.)
Matt Johnson-Pint

Bir terminoloji notu ile giriş Chiming: "locale" vurgulayarak olduğunu değil kullanıcının coğrafi konumu. "Yerel ayar", dil, sayı biçimi, takvim vb. Gibi bir ayar grubudur. Örneğin, de_DE yerel ayarı varsayılan dil olarak Almanca, varsayılan para birimi olarak euro, ondalık ayırıcı olarak virgül, binlik ayırıcı olarak nokta ve Gregorian takvim olarak. Bkz. Developer.mozilla.org/tr-TR/docs/Web/JavaScript/Reference/…
azernik

49

İşte tarayıcının bulunduğu saat dilimini belirlemek için sağlam bir JavaScript çözümü.

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

https://bitbucket.org/pellepim/jstimezonedetect

Ek 1: Şimdi bu proje GitHub'da bulunuyor: https://github.com/pellepim/jstimezonedetect


14
Bağlantı sadece cevaplardan vazgeçirilir, çünkü bağlantı kaybolursa, cevap yararlı olmaz; ve çünkü bağlantıyı takip etmeden, okuyucular iyi bir cevap verip vermediğini bilmiyorlar. Bu durumda, bu tanımlamaya veritabanı tabanlı bir yaklaşım alan ve belki de çalışma prensiplerinden bazılarını açıklayan 3. taraf bir kütüphane olduğunu açıklığa kavuşturabilirsiniz.
IMSoP

1
Bu! Bu yol. Basit kütüphane, DST'yi düzgün işler. Diğer cevaplar WTF ile doludur ve çoğu DST yapmaz.
Dirbaio

1
Bu kütüphane çok zekidir. Geçerli ofseti UTC olarak sorgulayıp, UTC'ye değişene kadar saniye ekleyerek veya çıkararak JavaScript Tarih nesnesi süresini ayarlayarak çalışır. Bu kütüphane kullanılarak bu kütüphane, saat dilimini benzersiz bir şekilde tanımlamak için yeterli sayıda DST değişikliği bulmaktadır. Bence doğrusal arama yerine ikili arama yaparsa kütüphane daha iyi bir performansa sahip olabilir. Dönen değer bir IANA bölge bilgisi anahtarıdır (Olson zaman dilimi veritabanı olarak da bilinir).
Mikko Rantalainen

3
Bu kütüphaneye artık gerek yok. Modern tarayıcılar, IANA saat dilimi dizesini döndüren Intl API'sini destekler. Bu cevaba bakınız .
Dan Dascalescu

42

İşte daha eksiksiz bir yol.

  1. Kullanıcı için saat dilimi farkını alma
  2. Gün ışığından yararlanma kullanan bir bölgede olup olmadıklarını belirlemek için gün ışığından yararlanma sınırlarında birkaç gün test edin.

Bir alıntı aşağıdadır:

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

JS'den TZ ve DST alma (Way Back Machine ile)


Bu benim için çalıştı! Birkaç kod güncellemesi için blog yazısının altındaki yorumları okuyun.
arlomedia

Bu yine de sadece saat dilimi için +02: 00 gibi standart ofseti döndürür . Kullanıcının saat dilimini belirlemenize yetecek kadar bilgi vermez , Africa/Johannesburgveya Europe/Istanbul. Bkz . Saat dilimi etiketi wiki .
Matt Johnson-Pint

32

Unkwntech'in yaklaşımını kullanarak jQuery ve PHP kullanarak bir fonksiyon yazdım. Bu test edildi ve işe yarıyor!

Saat dilimini değişken olarak kullanmak istediğiniz PHP sayfasında, bu kod snippet'ini sayfanın üst kısmına yakın bir yerde bulundurun:

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

Bu, şimdi oluşturmak üzere olduğumuz oturum değişkeni "time" ı okuyacaktır.

Aynı sayfada, <head> 'de, her şeyden önce jQuery'yi eklemeniz gerekir:

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

Ayrıca <head> içinde, jQuery'nin altına şunu yapıştırın:

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

Fark etmiş olabilir veya etmemiş olabilirsiniz, ancak URL'yi gerçek alan adınızla değiştirmeniz gerekir.

Son bir şey. Muhtemelen timezone.php'nin ne olduğunu merak ediyorsunuz. Eh, bu sadece: ( timezone.php adlı yeni bir dosya oluşturun ve yukarıdaki URL ile işaret edin)

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

Bu düzgün çalışırsa, önce sayfayı yükler, JavaScript'i yürütür ve sayfayı yeniden yükler. Daha sonra $ timezone değişkenini okuyabilir ve zevkinize göre kullanabilirsiniz! Geçerli UTC / GMT saat dilimi uzaklığını (GMT -7) veya içinde bulunduğunuz saat dilimini döndürür.


Bunu seviyorum, ama mevcut $ _SESSION ['zaman'] kontrol eden bir şey olabilir ve sadece farklı
Christopher Chase

1
Bunu yapmak için Çerez kullanmak bir Oturumdan daha kolaydır, çünkü PHP oturumunun kilitlenmesi ve serileştirilmesi uygulamanızda yavaşlamalara neden olabilir. Maksimum verimlilik için, değeri oturuma kopyalayabilir ve sonraki isteklerde gönderilmemesi için çerezi silebilirsiniz.
IMSoP

25

JQuery ile AJAX isteklerinde saat dilimi uzaklığını HTTP üstbilgisi olarak göndermek için

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

Ayrıca kullanarak gerçek zaman dilimi adını almak için benzer bir şey yapabilirsiniz moment.tz.guess();dan http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/


1
Bu yalnızca döner geçerli değil - ofset saat dilimini saat dilimi . Bkz . Saat dilimi etiketi wiki .
Matt Johnson-Pint

Saat dilimi adı için aynısını yapma hakkında bilgi içerecek şekilde düzenlendi.
philfreo

24

Burada hala saat dilimini alan ayrıntılı bir cevap görmedim. IP adresine göre coğrafi kod yazmanız veya PHP (lol) kullanmanız veya bir ofsetten yanlış tahmin etmeniz gerekmez.

İlk olarak bir zaman dilimi sadece GMT'nin ofseti değildir. Zaman kurallarının yerel standartlara göre belirlendiği bir arazi alanıdır. Bazı ülkeler gün ışığından yararlanma tasarrufuna sahiptir ve farklı zamanlarda DST'yi açacaktır. Sadece geçerli ofseti değil, gerçek bölgeyi elde etmek genellikle önemlidir.

Bu saat dilimini saklamak istiyorsanız, örneğin kullanıcı tercihlerinde yalnızca ofseti değil bölgeyi de istersiniz. Gerçek zamanlı dönüşümler için bunun bir önemi yoktur.

Şimdi, javascript ile saat dilimini almak için bunu kullanabilirsiniz:

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

Ancak Olsen formatlı saat dilimini döndüren bu sağlam eklentiyi kullanmayı daha kolay buldum:

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


22

PHP dateişlevi ile sitenin bulunduğu sunucunun tarih saatini alırsınız. Kullanıcının zamanını almanın tek yolu JavaScript kullanmaktır.

Ancak, sitenizde kayıt olması gerekiyorsa, en iyi yol, zorunlu alan olarak kayıt yaptırırken kullanıcıdan sormaktır. Kayıt sayfasında çeşitli saat dilimlerini listeleyebilir ve veritabanına kaydedebilirsiniz. Bundan sonra, kullanıcı siteye giriş yaparsa, o oturum için varsayılan saat dilimini kullanıcıların seçtiği saat dilimine göre ayarlayabilirsiniz.

PHP işlevini kullanarak belirli bir saat dilimini ayarlayabilirsiniz date_default_timezone_set. Bu, kullanıcılar için belirtilen saat dilimini ayarlar.

Temel olarak kullanıcıların saat dilimi istemci tarafına gider, bu nedenle bunun için JavaScript kullanmalıyız.

Aşağıda, kullanıcıların PHP ve JavaScript kullanarak saat dilimlerini alma komut dosyası bulunmaktadır.

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

Benim görüşüme göre, kullanıcılara projenizde kaydın zorunlu olup olmadığını sormak daha iyidir.


22

Konumu (ve dolayısıyla saat dilimini) kesin olarak belirlemek için IP adresini kullanmayın - bunun nedeni NAT, proxy'ler (giderek daha popüler) ve VPN'lerle IP adreslerinin kullanıcının gerçek konumunu değil, bu protokolleri uygulayan sunucular bulunur.

Numara taşınabilirliğinin popülaritesi göz önüne alındığında, ABD alan kodlarının artık bir telefon kullanıcısını bulmak için yararlı olmadığına benzer.

Yukarıda gösterilen IP adresi ve diğer teknikler , kullanıcının ayarlayabileceği / düzeltebileceği bir varsayılan önermek için kullanışlıdır .


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

Bu işleve zamanınızı Unix zaman damgası biçiminde sağlamanız yeterlidir; JavaScript kullanıcının saat dilimini zaten biliyor.

Bunun gibi:

PHP:

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

Bu, her zaman kişinin bilgisayar saatinde ayarladığı zaman dilimini temel alarak saatleri doğru bir şekilde gösterir. Kimseye bir şey sormaya ve yerlere kaydetmeye gerek yok, şükürler olsun!


$ unix_timestamp_ofshiz? Burada bir şey eksik ve iyi çalışmıyor, ancak bu iyi bir cevap olabilir gibi görünüyor.


19

Sihrin içinde olduğu anlaşılıyor

visitortime.getTimezoneOffset()

Güzel, bunu bilmiyordum. Internet Explorer'da çalışıyor mu, vb. Oradan JavaScript'i Ajax'a kullanabilmeniz, çerezleri ayarlayabilmeniz gerekir. Muhtemelen kurabiye yoluna kendim giderdim.

Yine de kullanıcının değiştirmesine izin vermeniz gerekir. Bir süre önce bunu yapmak için coğrafi konumu (maxmind aracılığıyla) kullanmaya çalıştık ve makul sıklıkta yanlıştı - yapmaya değmeyecek kadar yeterli, bu yüzden kullanıcının profilinde ayarlamasına izin veren ve henüz onlarınkini ayarlamadı.


15

ASP.NET (VB.NET, C #) uygulamasında yerelleştirilmiş sürenin nasıl belirleneceğini ve kullanılacağını açıklayan bir makale (kaynak kodlu):

Bu zamanla ilgili

Kısacası, açıklanan yaklaşım getTimezoneOffset, oturum çerezine kaydedilen ve GMT ile yerel saat arasındaki zaman değerlerini ayarlamak için arka planda kod tarafından kullanılan değeri döndüren JavaScript işlevine dayanır . Güzel olan şey, kullanıcının saat dilimini belirtmesine gerek olmamasıdır (kod otomatik olarak yapar). Daha fazla yer var (bu yüzden makaleye bağlantı veriyorum), ancak sağlanan kod kullanımı gerçekten kolaylaştırıyor. (ASP.NET anladığınız sürece) mantığı PHP ve diğer dillere dönüştürebileceğinizden şüpheleniyorum.


1
Bağlantı öldü. Bunun alternatif bir bağlantı olduğunu düşünüyorum: devproconnections.com/article/aspnet2/it-s-about-time-122778
Gan

1
Makale burada PDF formu olarak da mevcuttur: app.box.com/shared/bfvvmidtyg
Ivaylo Slavov

UTC sunucu saatini bu makalede açıklanan yerel istemci saatine dönüştürme yöntemi yanlış. Sunucuda UTC saatlerini ayarlamak için geçerli istemci ofsetini kullanmak, yaz saati uygulamalarını gözlemleyen istemci yerel ayarlar için yılın yarısında yanlış "yerel" saatlerle sonuçlanır. Şu senaryoyu inceleyin: 14 Ocak 2013 tarihinde İngiltere'de bir müşteri (GMT + 0000 Standart Saati) 21 Ağu 2015 14:00 (GMT + 0100 Yaz Saati) tarih ve saatini ayarlar. Bu sunucuda 21 Ağu 2015 13:00 UTC'ye normalleştirilir. Bu gerçekleştiği gün müşteri ofseti 0'dır, bu nedenle müşteriye geri gönderilen süre 21 Ağu 2015 13:00 olacaktır.
Stephen Blair

Geçerli nokta, ama bunun kurşun geçirmez bir çözüm olduğunu iddia etmedim. Gerçekten zamana duyarlı bir çözüm uygulamanız gerekiyorsa, bir tren bileti rezervasyon uygulaması söyleyin, o zaman daha kapsamlı (ve karmaşık bir çözüm) bulmanız gerekir. Ancak, birçok uygulama için bu bir sorun olmaz. Çünkü çoğu durumda GMT değerlerini mevcut oturum için yerelleştirmek istiyoruz. Şimdi, gelecekte bile bazıları için bir zaman damgası kaydetmesi gereken bir uygulamanız varsa ve DTS'yi tolere edemezseniz, doğrudan GMT'de zaman kazanmak için uygun bir yol sunmak olacaktır. Daha iyi bir seçenek biliyorsanız, lütfen paylaşın.
Alek Davis

14

Kimlik doğrulama için OpenID kullanıyorsanız , Basit Kayıt Uzantısı kimliği doğrulanmış kullanıcılar için sorunu çözer (tz'den nümana dönüştürmeniz gerekir).

Başka bir seçenek, saat dilimini kullanıcı aracısının ülke tercihinden çıkarmaktır. Bu biraz kaba bir yöntemdir (en-US için işe yaramaz), ancak iyi bir yaklaşım sağlar.


13

JavaScript ve PHP ile basit:

Kullanıcı dahili saati ve / veya saat dilimi ile uğraşabilse de, şimdiye kadar bulduğum en iyi yol, ofseti elde etmek için kalır new Date().getTimezoneOffset();. İnvaziv değildir, baş ağrısı vermez ve üçüncü taraflara güvenme ihtiyacını ortadan kaldırır.

Diyelim ki Unix zaman damgalarını depolamak için usersalan içeren bir date_created int(13)tablom var;

Bir müşteri varsayarsak creates a new account, veri tarafından alındığında post, ben gerek müşterinin Unix zaman damgası değil sunucunun ile.insert/updatedate_created column

TimezoneOffset, ekleme / güncelleme sırasında gerekli olduğundan, istemci formu gönderdiğinde fazladan bir $ _POST öğesi olarak geçirilir ve böylece oturumlarda ve / veya çerezlerde saklanması gereği ortadan kalkar ve ek sunucu isabet etmez.

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;

Sunucu alır ki tzoolarak $_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);

Ekle / güncelleme date_created=$user_timestamp .

Date_created öğesini alırken, zaman damgasını şu şekilde dönüştürebilirsiniz:

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

Şimdi, bu örnek bir firstzaman damgası eklemek söz konusu olduğunda kişinin ihtiyaçlarına uygun olabilir ... Ek bir zaman damgası veya tablo söz konusu olduğunda, ileride başvurmak için tzo değerini kullanıcılar tablosuna eklemeyi veya ayarlamayı düşünebilirsiniz. oturum olarak veya çerez olarak.

PS AMA kullanıcı zaman dilimleri seyahat ve geçiş yapar. GMT + 4'te oturum açar, GMT-1'e hızlı seyahat eder ve tekrar oturum açar. Son giriş gelecekte olacak.

Bence ... çok fazla düşünüyoruz.



11

PHP'de geçerli bir TZ Veritabanı saat dilimi adı almak iki adımlı bir işlemdir:

  1. JavaScript ile saat dilimini dakikalar içinde ofset edin getTimezoneOffset. Yerel saat dilimi UTC'nin arkasındaysa bu ofset pozitif, önde ise negatif olacaktır. Bu nedenle, ofsete zıt bir işaret eklemelisiniz.

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

    Bu ofseti PHP'ye geçirin.

  2. PHP'de bu ofseti, timezone_name_from_abbr işleviyle geçerli bir saat dilimi adına dönüştürün .

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

Üzerine bir blog yazısı yazdım: PHP'de Kullanıcı Saat Dilimi Nasıl Alınır . Ayrıca bir demo içerir.


1
Bence daha basit bir süreç aramak Intl.DateTimeFormat().resolvedOptions().timeZoneve web sunucusuna göndermek. Referans: stackoverflow.com/questions/9772955/…
Michael Tsang


8

Olası bir seçenek, RFC 7231'deDate tanımlanan ve saat dilimini içermesi gereken başlık alanını kullanmaktır . Tabii ki, değerin gerçekten müşterinin saat dilimi olduğu garanti edilmez, ancak uygun bir başlangıç ​​noktası olabilir.


1
Ne yazık ki, bu başlık genellikle yanıtlar için değil, yanıtlar için tasarlanmış gibi görünüyor: "Bir kullanıcı aracısı bir istekte bir Tarih başlığı alanı gönderebilir, ancak genellikle sunucuya yararlı bilgiler taşıdığına inanılmadığı sürece bunu yapmaz." Az önce kontrol ettim ve Firefox göndermiyor.
IMSoP

8

İşte böyle yapıyorum. Bu, PHP'nin varsayılan saat dilimini kullanıcının yerel saat dilimine ayarlar. Aşağıdakileri tüm sayfalarınızın üstüne yapıştırmanız yeterlidir:

<?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
Bu, "gün ışığından yararlanma" ayarlamalarını hesaba katmaz - Dublin'deki bir kullanıcı kışın 'Avrupa / Dublin'inizle, yaz aylarında' Avrupa / Belgrad'ınızla eşleşir. Geçerli ofseti kullanacaksanız, makul bir şekilde varsayabileceğiniz tek şey coğrafi bir tanımlayıcı değil, ofsettir.
IMSoP

8

Bu PHP kodunu deneyin:

<?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'];
?>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.