ツイートID
特定のツイートをブラウザで表示した際、以下のようなURL1になるのですが、この数字の部分(以下の例では1488865376611950387
)を ツイートID と呼ぶことにします。
https://twitter.com/{ユーザー名}/status/1488865376611950387
ツイートIDからタイムスタンプを取得するプログラム
細かい話は後にして、ツイートIDからタイムスタンプを取得するプログラム(C#)を掲載します。
- 定数
// Twitterエポック(2010-11-04 01:42:54.657)
long twitterEpoch = 1288834974657L;
// UNIXエポック(1970/01/01 00:00:00.000)
long unixEpoch = 62135596800000L;
// タイムスタンプのビット数
int timestampBits = 41;
// タイムスタンプのシフト数
int timestampShift = 22;
// タイムスタンプのマスク
long timestampMask = -1L ^ (-1L << timestampBits);
- ツイートIDからタイムスタンプを算出してDateTime型で返すメソッド
DateTime GetDateTime(long id)
{
// 0001/01/01 00:00:00.000 からの経過ミリ秒
var timestamp =
((id >> timestampShift) & timestampMask)
+ twitterEpoch
+ unixEpoch;
return new DateTime(
timestamp * TimeSpan.TicksPerMillisecond,
DateTimeKind.Utc
);
}
使い方
ツイートIDを GetDateTimeメソッド に引数で渡せば、DateTime型でタイムスタンプが返されます。
このメソッドが返すタイムスタンプはUTCになっていますので、必要に応じてローカル時刻に変換して使用します。
var date = GetDateTime(1488865376611950387L);
Console.WriteLine($"{date.ToLocalTime():yyyy-MM-dd HH:mm:ss.fff}");
// -> 2022-02-02 22:22:22.222
ツイートIDの仕様について
Twitterでは snowflake という仕組みを利用して、IDの採番を行っているようです。
snowflake はGitHubでソース(scala)が公開されていますので、これを元にツイートIDの仕様を確認しました。2 3
ツイートIDの構成
READMEファイル や IdWorkerクラス からツイートIDの構成を整理すると、以下のようになります。
- 64bit整数(long値) 4
- 上位のビットから、以下の通りの構成
- 0固定 - 1ビット
- タイムスタンプ(ミリ秒単位) - 41ビット
- マシンID 5 - 10ビット
- シーケンス番号 - 12ビット
- タイムスタンプは任意の基準時刻(カスタムエポック)からの経過ミリ秒
- Twitterでは 2010-11-04 01:42:54.657 を基準としている。
- これは、UNIXエポック(1970/01/01)から 1288834974657ミリ秒 6 経過した時刻。
ツイートIDからタイムスタンプを取得する
今回はタイムスタンプにのみ興味があるので、以下のようにしてタイムスタンプを取得しました(先述のGetDateTimeメソッド)。
- ツイートIDの下位22ビットを切り捨てる(右シフト)
- 41ビット分を抽出(マスク処理)
- これが基準時刻からの経過ミリ秒になっているので、C#のDateTimeの仕様に合わせて0001/01/01 00:00:00.000 からの経過ミリ秒に変換する
- Twitterエポック(1970/01/01からの経過ミリ秒) を加算
- UNIXエポック(0001/01/01から1970/01/01までのミリ秒) を加算
- ミリ秒からTickに変換して、DateTimeインスタンスを作成する
注意点
Twitterは2006年の公開以来、sonwflake を採用する以前はシーケンスと思われる採番方法を取っていました。
snowflake は2010年11月ごろから利用されているようなので、それより古いツイートのツイートIDは今回の方法でタイムスタンプに変換することはできません。
具体的な切り替え時刻は分かりませんが、
- 2010/11/04 20時ごろ → 古い方式
- 2010/11/05 9時ごろ → snowflakeを利用
のようです(日本時間)。
Twitter風のIDを採番するプログラムをC#で書いてみました
ツイートIDの仕組みを調べる過程で snowflake のID採番処理を C# に移植していましたので、そのソース全文を公開しました。
参考になれば幸いです。
どうしてこんなこと調べたの?
ここからは完全に余談です。
Twitterでクイズ大会をした時に、ほぼ同時に回答が投稿されてどっちが先かが分からなくなったということがありました。
Twitterのウェブ画面では 分 までしか表示されないので困ったなぁ、という時に、ツイートIDから順序が分からないものかと調べたのがきっかけです。
ツイートIDの大小だけで、どちらが先かは分かるのですが、せっかくなので「何秒差で投稿されたのか」が気になって、ここまでやってみたという話です。
ちなみに、0.3秒差くらいでした。
-
例示したURLに対応するツイートは存在しません。 ↩
-
現時点ではプロジェクトは公開されていませんが、tagから当時のソースが取得可能です。 ↩
-
厳密には今でもこのプログラムでTwitterがID採番を行っているかは不明なのですが、この記事の執筆時に動作確認をした時点では、タイムスタンプについては確からしい結果になることを確認できました。 ↩
-
先頭ビットが0固定なので、符号の有無(signed/unsigned)は考慮不要。 ↩
-
IdWorkerクラスでは、ワーカーID と データセンターID にそれぞれ5ビットずつ割り当てている。 ↩
-
IdWorkerクラス の twepoch で定義されている。 ↩