javascript للسعودية - تحديد المنطقة الزمنية للمستخدم




الرياض للمملكة (21)

لا توجد رؤوس HTTP يمكنها الإبلاغ عن المنطقة الزمنية للعملاء حتى الآن على الرغم من أنه قد تم اقتراح تضمينها في مواصفات HTTP.

إذا كنت أنا ، فقد أحاول على الأرجح إحضار المنطقة الزمنية باستخدام جافا سكريبت من جانب العميل ثم إرسالها إلى الخادم باستخدام Ajax أو أي شيء آخر.

هل هناك أي طريقة قياسية لكي يتمكن خادم الويب من تحديد المنطقة الزمنية للمستخدم داخل صفحة الويب؟ ربما من رأس HTTP أو جزء من سلسلة وكيل المستخدم؟


السحر يبدو أن كل شيء فيه

visitortime.getTimezoneOffset()

هذا رائع ، لم أكن أعرف ذلك. هل يعمل في IE ، وما إلى ذلك؟ من هناك يجب أن تكون قادرًا على استخدام JS في ajax ، تعيين ملفات تعريف الارتباط ، أيا كان. ربما سأذهب لطريق ملفات تعريف الارتباط بنفسي.

ستحتاج إلى السماح للمستخدم بتغييره على الرغم من ذلك. حاولنا استخدام تحديد الموقع الجغرافي (عبر maxmind) للقيام بذلك منذ فترة ، وكان ذلك خطأً معقولًا في كثير من الأحيان - وهو ما يكفي لجعله لا يستحق القيام به ، لذلك نحن فقط نسمح للمستخدم بتعيينه في ملفه الشخصي ، وإظهار إشعار للمستخدمين لم نضع ملكهم بعد


طريقة بسيطة للقيام بذلك هي باستخدام:

new Date().getTimezoneOffset();

هنا طريقة أكثر اكتمالا.

  1. احصل على إزاحة المنطقة الزمنية للمستخدم
  2. اختبار بعض الأيام على حدود DLS لتحديد ما إذا كانوا في منطقة تستخدم DLS.

باستثناء ما يلي:

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

الحصول على TZ و DST من JS (عبر الجهاز Back Machine)


ما زلت لم أر إجابة مفصلة هنا تحصل على المنطقة الزمنية. يجب ألا تحتاج إلى ترميز جغرافي حسب عنوان IP أو استخدام PHP (lol) أو تخمينه بشكل غير صحيح من الإزاحة.

أولاً ، لا تعد المنطقة الزمنية مجرد إزاحة من GMT. إنها مساحة من الأرض تحدد فيها القواعد الزمنية بالمعايير المحلية. لدى بعض البلدان توفير الصيفي ، وسيتم تشغيل التوقيت الصيفي في أوقات مختلفة. من المهم عادةً الحصول على المنطقة الفعلية ، وليس فقط الإزاحة الحالية.

إذا كنت تنوي تخزين هذه المنطقة الزمنية ، على سبيل المثال في تفضيلات المستخدم ، فأنت تريد المنطقة وليس فقط الإزاحة. بالنسبة للتحويلات في الوقت الفعلي ، لا يهم الكثير.

الآن ، للحصول على المنطقة الزمنية مع javascript ، يمكنك استخدام هذا:

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

ومع ذلك ، وجدت أنه من السهل استخدام هذا المكون الإضافي القوي الذي يؤدي إلى إرجاع المنطقة المنسقة في أولسن:

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


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

getTimezoneOffset() وقتك من GMT getTimezoneOffset() عدد الدقائق. إذا كنت تعيش في توقيت جرينتش -8 ، فسوف تعود 480. لوضع هذا في ساعات ، قسّم على 60. كذلك ، لاحظ أن العلامة هي عكس ما تحتاجه - إنها تحسب إزاحة GMT من منطقتك الزمنية ، وليس إزاحة المنطقة الزمنية من GMT. لإصلاح هذا ، ببساطة اضرب في -1.

تصحيح

لاحظ أيضًا أن w3school يقول:

القيمة التي تم إرجاعها ليست ثابتة ، بسبب ممارسة استخدام التوقيت الصيفي.


مع وظيفة تاريخ PHP سوف تحصل على تاريخ وقت الخادم على الموقع الذي يقع فيه. الطريقة الوحيدة للحصول على وقت المستخدم هي استخدام جافا سكريبت.

ولكن أقترح عليك ، إذا كان تسجيل موقعك مطلوبًا ، فإن أفضل طريقة هي أن تسأل المستخدم أثناء التسجيل كحقل إجباري. يمكنك سرد المناطق الزمنية المختلفة في صفحة التسجيل وحفظها في قاعدة البيانات. بعد ذلك ، إذا كان تسجيل دخول المستخدم إلى الموقع ، يمكنك تعيين المنطقة الزمنية الافتراضية لهذه الجلسة وفقًا للمنطقة الزمنية المحددة للمستخدمين. يمكنك تعيين أي منطقة زمنية محددة باستخدام وظيفة PHP date_default_timezone_set . هذا تعيين المنطقة الزمنية المحددة للمستخدمين.

أساسا المنطقة الزمنية للمستخدمين يذهب إلى جانب العميل ، لذلك يجب علينا استخدام جافا سكريبت لهذا.

في ما يلي النص البرمجي للحصول على المنطقة الزمنية للمستخدمين باستخدام PHP و 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();
?>

ولكن حسب وجهة نظري ، من الأفضل أن تسأل المستخدمين إذا كان التسجيل إلزاميًا في مشروعك.


Getting a valid TZ Database timezone name in PHP is a two step process :

1) With Javascript, get timezone offset in minutes through getTimezoneOffset . This offset will be positive if the local timezone is behind UTC and negative if it is ahead. So you must add an opposite sign to the offset.

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

Pass this offset to PHP.

2) In PHP convert this offset into a valid timezone name with timezone_name_from_abbr function.

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

I've written a blog post on it : http://usefulangle.com/post/31/detect-user-browser-timezone-name-in-php It contains a demo also.


لإرسال إزاحة المنطقة الزمنية كرأس HTTP على طلبات AJAX مع jQuery

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

يمكنك أيضًا القيام بشيء مماثل للحصول على اسم المنطقة الزمنية الفعلي باستخدام moment.tz.guess(); من http://momentjs.com/timezone/docs/#/using-timezones/guessing-user-timezone/


وإليك كيف أفعل ذلك. سيؤدي هذا إلى تعيين المنطقة الزمنية الافتراضية لـ PHP على المنطقة الزمنية المحلية للمستخدم. ما عليك سوى لصق ما يلي في أعلى جميع صفحاتك:

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

سهل ، فقط استخدم وظيفة getTimezoneOffset JavaScript مثل:

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

جرب كود php هذا

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

جافا سكريبت:

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

ببساطة توفير أوقاتك في تنسيق UNIX Timestamp لهذه الوظيفة ، جافا سكريبت يعرف بالفعل المنطقة الزمنية للمستخدم.

مثله:

فب:

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

سيظهر هذا دائمًا الأوقات بشكل صحيح استنادًا إلى التوقيت الزمني الذي حدده الشخص على ساعة جهاز الكمبيوتر ، ولا حاجة إلى طلب أي شيء لأي شخص وحفظه في أماكن يشكرها الله!


لا تستخدم عنوان IP لتحديد الموقع بشكل نهائي (المنطقة الزمنية المرهقة) - ذلك لأن NAT و Proxies (التي تزداد شعبية) والشبكات الظاهرية الخاصة (VPN) لا تعكس عناوين IP بالضرورة بالضرورة الموقع الفعلي للمستخدم ، ولكن الموقع الذي توجد فيه الخوادم تنفيذ هذه البروتوكولات الموجودة.

تشبه الطريقة التي لم تعد بها رموز المناطق مفيدة لتحديد موقع مستخدم الهاتف ، نظرًا لشعبية إمكانية نقل الأرقام.

تعد تقنيات IP والتقنيات الأخرى الموضحة أعلاه مفيدة في اقتراح الافتراضي الذي يمكن للمستخدم ضبطه / تصحيحه.


هنا مقال (مع شفرة المصدر) يشرح كيفية تحديد واستخدام الوقت المترجمة في تطبيق ASP.NET (VB.NET ، C #):

إنه بشأن الوقت

باختصار ، يعتمد الأسلوب الموصوف على وظيفة getTimezoneOffset لجافا سكريبت ، والتي تقوم بإرجاع القيمة التي تم حفظها في ملف تعريف ارتباط جلسة العمل واستخدامها من قبل رمز خلف لتعديل قيم الوقت بين توقيت جرينتش والتوقيت المحلي. الشيء الجميل هو أن المستخدم لا يحتاج إلى تحديد المنطقة الزمنية (رمز يفعل ذلك تلقائيا). هناك المزيد من المشاركة (وهذا هو سبب ارتباطي بهذه المقالة) ، ولكن التعليمات البرمجية المقدمة تجعل من السهل جدًا استخدامها. أظن أنه يمكنك تحويل المنطق إلى لغة PHP ولغات أخرى (طالما أنك تفهم ASP.NET).



في ما يلي حل جافا سكريبت قوي لتحديد المنطقة الزمنية التي يوجد بها المتصفح.

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

https://bitbucket.org/pellepim/jstimezonedetect


الطريقة الأكثر شيوعًا (== standard؟) لتحديد المنطقة الزمنية التي رأيتها حولها هي ببساطة مطالبة المستخدمين أنفسهم. إذا كان موقعك على الويب يتطلب اشتراكًا ، فيمكن حفظ هذا في بيانات الملف الشخصي للمستخدمين. بالنسبة لمستخدمي الإنترنت ، يمكن عرض التواريخ على أنها UTC أو GMT أو بعض هذه.

أنا لا أحاول أن أكون aleck ذكي. إنه في بعض الأحيان أن بعض المشاكل لها حلول أدق خارج أي سياق برمجة.


أولاً ، فهم أن اكتشاف المنطقة الزمنية في JavaScript غير مثالي. يمكنك الحصول على إزاحة المنطقة الزمنية المحلية لتاريخ ووقت getTimezoneOffset باستخدام getTimezoneOffset على مثيل كائن Date ، ولكن هذا ليس تماماً مثل المنطقة الزمنية الكاملة لـ IANA مثل America/Los_Angeles .

هناك بعض الخيارات التي يمكن أن تعمل على الرغم من:

  • تدعم معظم المتصفحات الحديثة مناطق IANA الزمنية في تنفيذها لواجهة برمجة تطبيقات ECMAScript Internationalization ، بحيث يمكنك القيام بذلك:

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

    اﻟﻨﺘﻴﺠﺔ هﻲ ﺳﻠﺴﻠﺔ ﺗﺤﺘﻮي ﻋﻠﻰ إﻋﺪاد ﻣﻨﻄﻘﺔ IANA اﻟﺨﺎص ﺑﺎﻟﻜﻤﺒﻴﻮﺗﺮ ﺣﻴﺚ ﻳﺘﻢ ﺗﺸﻐﻴﻞ اﻟﺮﻣﺰ.

    يتم سرد البيئات المدعومة في جدول التوافق Intl . قم بتوسيع المقطع DateTimeFormat ثم ابحث عن الميزة المسمى resolvedOptions().timeZone defaults to the host environment .

  • إذا كنت بحاجة إلى دعم مجموعة أوسع من البيئات ، مثل متصفحات الويب القديمة ، فيمكنك استخدام مكتبة لإجراء تخمين متعلم في المنطقة الزمنية. وهي تعمل أولاً باستخدام واجهة برمجة التطبيقات ( Intl API) إذا كانت متوفرة ، وعندما لا تكون متاحة ، فإنها تستجوب دالة getTimezoneOffset Date ، لعدة نقاط زمنية مختلفة ، باستخدام النتائج لاختيار منطقة زمنية مناسبة من مجموعة بيانات داخلية.

    https://bitbucket.org/pellepim/jstimezonedetect كل من https://bitbucket.org/pellepim/jstimezonedetect و https://bitbucket.org/pellepim/jstimezonedetect moment-timezone بهذه الوظيفة.

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

    في كلتا الحالتين ، يمكن اعتبار النتيجة فقط بمثابة تخمين. قد يكون التخمين الصحيح في كثير من الحالات ، ولكن ليس كلها.

    بالإضافة إلى ذلك ، يجب تحديث هذه المكتبات بشكل دوري لمقاومة حقيقة أن العديد من تطبيقات JavaScript القديمة لا تدرك سوى قاعدة التوقيت الصيفي الحالية للمنطقة الزمنية المحلية الخاصة بها. مزيد من التفاصيل حول ذلك هنا.

في نهاية المطاف ، يكون النهج الأفضل هو أن تسأل المستخدم فعليًا عن منطقته الزمنية. توفير الإعداد الذي يمكنهم تغييره. يمكنك استخدام أحد الخيارات المذكورة أعلاه لاختيار الإعداد الافتراضي ، ولكن لا تجعل من المستحيل أن تحيد عن ذلك في تطبيقك.

هناك أيضا نهج مختلف تماما عن الاعتماد على إعداد المنطقة الزمنية للكمبيوتر المستخدم على الإطلاق. بدلاً من ذلك ، إذا كان بإمكانك جمع إحداثيات خطوط العرض وخطوط الطول ، فيمكنك حلها إلى منطقة زمنية باستخدام إحدى هذه الطرق . هذا يعمل بشكل جيد على الأجهزة المحمولة.


بسيطة مع JS و PHP :

على الرغم من أنه يمكن للمستخدم الفوضى مع الساعة الداخلية و / أو المنطقة الزمنية ، فإن أفضل طريقة وجدت حتى الآن ، للحصول على الإزاحة ، لا تزال new Date().getTimezoneOffset(); . غير الغازية ، لا يعطي آلام الرأس ويقضي على الحاجة إلى الاعتماد على أطراف ثالثة.

لنفترض أن لدي users جداول يحتوي على حقل date_created int(13) ، لتخزين الطوابع الزمنية unix؛

بافتراض إنشاء عميل creates a new account ، يتم تلقي البيانات عن طريق post ، date_created column إلى insert/update date_created column مع الطابع الزمني unix للعميل ، وليس الخادم.

نظرًا لأنه يلزم توفير timezoneOffset في وقت الإدراج / التحديث ، يتم تمريره كعنصر $_POST إضافي عندما يرسل العميل النموذج ، وبالتالي يلغي الحاجة إلى تخزينه في الجلسات و / أو ملفات تعريف الارتباط ، وأي نتائج إضافية للخادم أيضًا.

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;

لنقل أن الخادم يتلقى tzo كـ $_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);

إدراج / تحديث date_created=$user_timestamp .

عند استرداد date_created ، يمكنك تحويل الطابع الزمني مثل:

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

الآن ، قد يلائم هذا المثال احتياجات المرء ، عندما يتعلق الأمر بإدخال طابع زمني first ... عندما يتعلق الأمر بطابع زمني إضافي ، أو جدول ، قد ترغب في التفكير في إدراج قيمة tzo في جدول المستخدمين للرجوع إليها في المستقبل ، أو الإعداد كجلسة أو كملف تعريف ارتباط.

PS ولكن ماذا لو كان المستخدم يسافر ويتحول المناطق الزمنية. تسجل الدخول في GMT + 4 ، وتنتقل بسرعة إلى GMT-1 وتسجيل الدخول مرة أخرى. آخر تسجيل دخول سيكون في المستقبل.

أعتقد ... نفكر أكثر من اللازم.


أنا أستخدم هذا

String.prototype.maybeBool = function(){

    if ( ["yes", "true", "1", "on"].indexOf( this.toLowerCase() ) !== -1 ) return true;
    if ( ["no", "false", "0", "off"].indexOf( this.toLowerCase() ) !== -1 ) return false;

    return this;

}

"on".maybeBool(); //returns true;
"off".maybeBool(); //returns false;
"I like js".maybeBool(); //returns "I like js"




javascript html browser timezone timezoneoffset