ツイートIDからsnowflakeを用いて投稿時刻のミリ秒を算出
Snowflakeとは?
SnowflakeはTwitter社がツイートを区別するIDを付与するときに使われるID生成器です。特徴としては
- 概ねIDが時系列になっている
- 高速な採番が可能
- OS内時刻の精度が重要
- IDとtimestamp値に相互互換がある
- 約69年で枯渇する
などがあります。APIにGET statuses/show/:idが存在するように、IDは世界で投稿される全てのツイート同士でユニークなものでなければいけません。そのため、同じtimestamp値のツイートが投稿されても違うIDが割り振られるように以下のような構造になっています。
これにより、採番全体としてはtimestampとmachine idで、生成器内ではsequenceでそれぞれ一意性を保っていることになります。
逆算してみよう
前項のような構造であることを踏まえれば、例えばIDが「978150333464559617」であった場合のtimestamp値は以下のように求めることができ、「233209212652」であると分かります。
このtimestamp値はsnowflakeの採番を開始した(と思われる)2010年11月4日 10時42分54.657秒からの経過ミリ秒なので、この時刻のUNIX時刻(ミリ秒)である「1288834974657」を足すとtimestamp値がUNIX時刻(ミリ秒)へと変換できます。ここまで来たら、あとは1000.000で除算すればtimestamp値からUNIX時刻への変換のフローは完了です。
UNIX時刻は広く知られている通り、1970年1月1日 0時0分0秒からの経過秒数で時刻を表現する規格なので、これを逆算するとIDから「2018年3月26日 15時3分7.309秒」に投稿(正確には採番?)されたということが逆算より求められます。
実装してみよう
PHPで実装してみます。過程で32bitよりも大きい数字を扱いますので、64bitコンピューター上での実行が必要です。
<?php echo milisec("978150333464559617")->format("Y-m-d H:i:s.u"); function milisec($id) { $timestamp = (($id >> 22) + 1288834974657) / 1000.000; $timestamp_format = DateTime::createFromFormat("U.u", $timestamp); $timestamp_format->setTimeZone(new DateTimeZone("Asia/Tokyo")); return $timestamp_format; }
上記コードでは算出されたUNIX時刻をDateTimeオブジェクトにして返すことで、手軽に任意のフォーマットに変換できるようになっています。
ここまで説明は省いていましたが、全ての時刻表現はUTCとなっているので、我々が普段目にする時刻と比較するには日本標準時JST(UTC+9)との時差を考慮する必要があります。(この場合はsetTimeZoneで時差は計算されているので、コードの出力はJSTになる。)
これが32bitコンピューターでの実行になるとGMP数を扱わないといけないので、凄く煩雑なコードになりますが、ここでは省きます。
参考文献
投稿者プロフィール
最新の投稿
- 2018.09.01AMD動画エンコードでGPUを活用する
- 2018.03.26phpツイートIDからsnowflakeを用いて投稿時刻のミリ秒を算出
- 2018.02.18phpphpMyAdminのインストール方法(Ubuntu)
- 2018.01.07未分類新聞を折らずに郵送する方法
最近のコメント