I'm KUITARIDER.

がりゅうさんのサイキックミラクルブログ

※(2015/12/19) WordPressから引っ越しました。前のURLには自動リンクを設定しています。

statusIDから投稿日時をデコードする

おはようギルガルド

きっかけは334Rankerです。ってここにはまだ334Rankerの記事書いてないのか(迫真)

334Rankerは、毎日3時34分に"334"と呟いた人を速い順にランキング化し、その結果を蓄積して世界ランクなんてものを計算するプログラムです。

こう書くと目的はあくまで334にまつわるランク付けってことになるですが、どうせなら、というかここまでやるならといった感じでやりたいことが一つ思い浮かぶワケです。

 

「334ツイートの正確な投稿時刻測定」

 

プログラムを作る最初の段階からこの機能は盛り込みたくて、色々考えたんですが結果的には秒未満の時刻を"正確に"記録するのは無理でした。

しかし、

これが過去のハナシになったというのが今日の記事内容。

 

[caption id="attachment_299" align="alignnone" width="241"]問題解決のカギはツイートのStatusIDだったんや また一つ賢くなったねん 問題解決のカギはツイートのStatusIDだったんや
また一つ賢くなったねん[/caption]

自慢したいんで問題解決の経緯を最初から書いていきます

ある日、334結果を保存したcsvファイルを開いて何気なくStatusIDを見ていました。

まあ当然というか直観的に矛盾はなくて、後に投稿されたツイートほど値が大きくなってるんですね。

そりゃあもちろん値が被っちゃまずいはずなので適当に間隔を空けてるんだと思ってたんですが、完全に適当(ランダム)っていうのもむしろ都合が悪いんじゃないか?という考えに至る。

そこで、何かを期待しながら投稿時刻(このときはとりあえず、UserStreamから流れてきた時刻を採用していた)とStatusIDをグラフにプロットしてみました。

graph

ああ^~~~ いいっすね~~~

この時点で、StatusIDの値がツイートの投稿時刻から生成されていることを確信しました。

別の日の結果についてもプロットしてみたらやっぱり直接の傾きは大体4200000000くらいだったので、もうこの値を採用してミリ秒単位で投稿時刻計算できるじゃんとか思いましたが

 

一応それらしい検索ワードでググってみた(前々からちょくちょく調べてはいたけど)

すると、

 

\おっ/

 

Twittersnowflakeについて

http://www.slideshare.net/moaikids/20130901-snowflake

 

神ポコなページを見つけました

引用すると、やはりTwitterのStatusIDはあるルールに基づいて生成されていて、

64bitのlong値でIDを表現 (※先頭1bitは0)

•3つの要素で構成

•timestamp (41 bit) : 現在のunixtime(ms)から、ある時点のunixtimeを引いた値

•machine id (10 bit): 生成器に割り当てられたID。datacenter id + worker id。

•sequence (12 bit): 生成器ごとに採番するsequence番号 17

という仕組みらしい(この仕組みでIDを生成するのがsnowflakeというもの)。

上位41bitがtimestampであるため、statusID全体も10進数に直せば近似的に投稿日時を表していることになるから、先ほどの実験結果も納得できるというわけ。

 

このページにある情報だけでお望みの「StatusID→投稿時刻」という変換ができて、

snowflake decoder

http://hidekiy.com/work/snowflake-decoder

というスクリプトも見つけました。

 

もちろん334Rankerにもこの計算を実装することに。よしやろう。

コードを書いてみると本当に単純なビット演算だけで投稿日時をデコードできて、面倒くさいのはむしろUnixTime→DateTimeの変換だった。

public static DateTime DecodeCreateDate(string statusID) { long unixtime = (long.Parse(statusID) >> 22) + 1288834974657; DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); return epoch.AddSeconds(unixtime * 0.001).AddHours(9); }

こんな感じ。

 

334結果を整形する部分もこのメソッドを使って正確な投稿時刻を取得するように変更して、長年の夢だったミリ秒単位での投稿時刻表示を実装できました。

[caption id="attachment_302" align="alignnone" width="359"]最低でもEカップ 最低でもEカップ[/caption]

(created_at パラメータの投稿時刻とは若干のズレがあるなんてことは内緒)

 

というわけで、

 

問☆題☆解☆決☆

[caption id="attachment_303" align="alignnone" width="599"]イェーイ イェーイ[/caption]