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-agent
dizenin bir bölümünden ?
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-agent
dizenin bir bölümünden ?
Yanıtlar:
-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.
>>> date.toTimeString() "15:46:04 GMT+1200 (New Zealand Standard Time)"
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.
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.
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.
İ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 getTimezoneOffset
bir örneği üzerinde Date
nesne, 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 . DateTimeFormat
Bö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
.
Intl
kullanı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 getTimezoneOffset
işlevini Date
zaman 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.
İş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
İşte daha eksiksiz bir yol.
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)
Africa/Johannesburg
veya Europe/Istanbul
. Bkz . Saat dilimi etiketi wiki .
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.
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/
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:
PHP date
iş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.
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 .
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!
Kolay, sadece JavaScript getTimezoneOffset
işlevini şu şekilde kullanın:
-new Date().getTimezoneOffset()/60;
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ı.
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):
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.
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.
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 users
alan 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/update
date_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 tzo
olarak $_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 first
zaman 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.
Bunu moment-zaman dilimi ile istemcide yapabilir ve değeri sunucuya gönderebilirsiniz; örnek kullanımı:
> moment.tz.guess()
"America/Asuncion"
PHP'de geçerli bir TZ Veritabanı saat dilimi adı almak iki adımlı bir işlemdir:
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.
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.
Intl.DateTimeFormat().resolvedOptions().timeZone
ve web sunucusuna göndermek. Referans: stackoverflow.com/questions/9772955/…
Bunu yapmanın basit bir yolu:
new Date().getTimezoneOffset();
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.
İş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
?>