時間と価格が刻々と変化するサイトを構築しています。私が最も関心を持っているのは、すべてのクライアントで可能な限り正確になるように時間を同期することです。
現在、私は残りのミリ秒数をクライアントに送信しています。これはカウントダウンタイマーの燃料として使用されますが、転送とレンダリングの遅延により、同じコンピューター上に2つのブラウザーがある場合でも、数秒遅れることがあります。
クライアントのJavaScript時間とサーバー時間を同期する方法はありますか、それともこのわずかな遅延に対処する必要がありますか?
データを送信するサーバーと、クライアントが受信してレンダリングするデータとの間の時間差を正確に測定する方法があった場合のみです。
サーバーとクライアントの時間が異なる場合でも、時間の変化率は基本的に同じでなければなりません。残りの時間をクライアントに送信し、クライアントにその時間を現在の時間に追加させ、クライアントにその時間からカウントダウンを計算させる。例えば:
var timeRemaining = [rendered on page load or queried by ajax]; // in milliseconds
var endTime = new Date(new Date().getTime() + timeRemaining);
// Put this in a setInterval, or however you currently handle it
var countdown = (endTime.getTime() - new Date().getTime()) / 1000;
クライアントをサーバーの時刻と同期させる方法があります。これを行うライブラリを作成しました ServerDate 。
以下はREADMEの一部です。
ServerDate
関数またはそのインスタンスの1つを使用する場合と同様に、Date
を使用できます。例:
> ServerDate()
"Mon Aug 13 2012 20:26:34 GMT-0300 (ART)"
> ServerDate.now()
1344900478753
> ServerDate.getMilliseconds()
22
サーバーのクロック(ミリ秒単位)のServerDateの見積もりの精度を取得する新しいメソッドもあります。
> ServerDate.toLocaleString() + " ± " + ServerDate.getPrecision() + " ms"
"Tue Aug 14 01:01:49 2012 ± 108 ms"
サーバーのクロックとブラウザのクロックの違いをミリ秒単位で確認できます。
> ServerDate - new Date()
39
サーバー全体のラウンドトリップにかかる時間を測定し、2で除算して、時間差の適切な見積もりを取得できます。注意:IPパッケージが両方向で同じルートを取ることは保証されていませんが、その可能性は非常に高いです。
Millisesondsの解像度で十分な場合は、Date.getTime()
を使用できます。
これに対する解決策はJavascriptです。クライアントのタイムゾーン設定にアクセスできます。残念ながら、特定の日付のタイムゾーンオフセット(分単位で指定)しか取得できず、タイムゾーン名は取得できません。したがって、正しいタイムゾーンを特定するには、夏時間(DST)が採用されているかどうかも知る必要があります。これがクライアント側のソリューションの一部です。
var now = new Date();
var later = new Date();
// Set time for how long the cookie should be saved
later.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000);
// Set cookie for the time zone offset in minutes
setCookie("time_zone_offset", now.getTimezoneOffset(), later, "/");
// Create two new dates
var d1 = new Date();
var d2 = new Date();
// Date one is set to January 1st of this year
// Guaranteed not to be in DST for northern hemisphere,
// and guaranteed to be in DST for southern hemisphere
// (If DST exists on client PC)
d1.setDate(1);
d1.setMonth(1);
// Date two is set to July 1st of this year
// Guaranteed to be in DST for northern hemisphere,
// and guaranteed not to be in DST for southern hemisphere
// (If DST exists on client PC)
d2.setDate(1);
d2.setMonth(7);
// If time zone offsets match, no DST exists for this time zone
if(parseInt(d1.getTimezoneOffset())==parseInt(d2.getTimezoneOffset()))
{
setCookie("time_zone_dst", "0", later, "/");
}
// DST exists for this time zone – check if it is currently active
else {
// Find out if we are on northern or southern hemisphere
// Hemisphere is positive for northern, and negative for southern
var hemisphere = parseInt(d1.getTimezoneOffset())-parseInt(d2.getTimezoneOffset());
// Current date is still before or after DST, not containing DST
if((hemisphere>0 && parseInt(d1.getTimezoneOffset())==parseInt(now.getTimezoneOffset())) ||
(hemisphere<0 && parseInt(d2.getTimezoneOffset())==parseInt(now.getTimezoneOffset()))) { setCookie("time_zone_dst", "0", later, "/"); } // DST is active right now with the current date else { setCookie("time_zone_dst", "1", later, "/"); } }
PHPスクリプトからアクセスできるCookieとして結果を保存します。上記のコードは、少なくともユーザーがアクセスする最初のページに含める必要があります。認識できるようにすべてのページに含めます(セッションへの変更がありそうもない場合でも、変更に適応します。
PHPでは、timezone_name_from_abbrという名前の新しい関数を使用して有効なタイムゾーンを抽出できます。これは、PHP 5.1.3以降で利用可能です。タイムゾーンの省略形またはタイムゾーンオフセット(秒単位)と夏時間の組み合わせ。後者には次の組み合わせがあります。
$time_zone_name = timezone_name_from_abbr(", -$_COOKIE['time_zone_offset']*60, $_COOKIE['time_zone_dst']);
これにより、Cookieのデータが有効な場合、ユーザーの正しいタイムゾーン名が得られます。たとえば、「ヨーロッパ/ベルリン」や「ヨーロッパ/チューリッヒ」など、正確に一致する多くの「重複」名があることに注意してください。同じタイムゾーン設定(少なくとも今のところ)。適切なオフセットとDST変数について、どちらか一方を取得できます。タイムゾーン名のリストは、php.netのサポートされているタイムゾーンのリストにあります。
指定されたタイムゾーンで日付文字列を作成するユーザーのタイムゾーンの名前で、PHPクラスを使用できるようになりましたDateTimeZoneおよびDateTimeを使用して、最終的に正しいタイムゾーンの日付文字列を作成します。
// Create time zone class
$time_zone_class = new DateTimeZone($time_zone_name);
// Create new date class with a given date
// Notice that the provided date will be regarded as being in the
// default time zone and converted accordingly
$new_date = new DateTime(‘2007-02-14 15:30:00′, $time_zone_class);
// Print date with the user’s time zone echo $new_date->format(‘Y-m-d H:i:s’);
それでおしまい!