ツイートID→時刻変換
by
furyu-tei
2023-11-11 [2023/11/11 11:47:49]
Twitterの個別ツイート(https://twitter.com/<name>/status/<id>)のURL(<id>)からおおよその投稿時刻を取得(2010年11月4日22時(UTC)以降のもの)
@@ -5,6 +5,37 @@
* @license MIT License
* @javascript_url
*/
-// 追記: http://blog.hidekiy.com/2012/01/twitter-snowflake-id.html 経由 http://www.slideshare.net/pfi/id-15755280 で epoch が 記載されていたので自分のおおよその実測値から修正(1288834974000→1288834974657)
-(function(i,d){d=new Date(1288834974657+i/(1<<22));prompt(i,[d.getFullYear(),1+d.getMonth(),d.getDate()].join( '.' )+' '+d.toLocaleTimeString())})(location.href.replace(/^.*\//,''))
+(()=>{
+'use strict';
+const
+ twitter_epoch_time = 1288834974657n, // https://www.slideshare.net/pfi/id-15755280
+ threshold_tweet_id = 300000000000000n;
+
+let tweet_id = (new URL(location.href).pathname.match(/^\/[^/]+\/status\/(\d+)/)||[])[1];
+if (! tweet_id) {
+ alert('Unsupported page');
+ return;
+}
+tweet_id = BigInt(tweet_id);
+if (tweet_id < threshold_tweet_id) {
+ alert(`Unsupported Tweet ID: ${tweet_id} (< ${threshold_tweet_id})`);
+ return;
+}
+let timestamp_ms = Number(twitter_epoch_time + tweet_id/(1n<<22n)),
+ date_obj = new Date(timestamp_ms),
+ iso_timestring = date_obj.toISOString().replace(/\.\d+Z$/, 'Z');
+date_obj.setMinutes(date_obj.getMinutes() - date_obj.getTimezoneOffset());
+let timestring = date_obj.toISOString().replace(/T/, ' ').replace(/\.\d+Z$/, ''),
+ prompt_text = `
+[Tweet ID] ${tweet_id}
+[ISO 8601] ${iso_timestring}`,
+ result = prompt(prompt_text, timestring);
+if (result !== null) {
+ navigator.clipboard.writeText(result)
+ .catch(error => console.info(`Copy to clipboard failed. (${error})`))
+ // TODO: Firefox だとエラーになる (90.0.2)
+ // Uncaught (in promise) DOMException: Clipboard write was blocked due to lack of user activation.
+ .then(() => console.debug(`Copy to clipboard succeeded. (${result})`));
+}
+})();
/*
* @title ツイートID→時刻変換
* @description Twitterの個別ツイート(https://twitter.com/<name>/status/<id>)のURL(<id>)からおおよその投稿時刻を取得(2010年11月4日22時(UTC)以降のもの)
* @include https://twitter.com/*
* @license MIT License
* @javascript_url
*/
(()=>{
'use strict';
const
twitter_epoch_time = 1288834974657n, // https://www.slideshare.net/pfi/id-15755280
threshold_tweet_id = 300000000000000n;
let tweet_id = (new URL(location.href).pathname.match(/^\/[^/]+\/status\/(\d+)/)||[])[1];
if (! tweet_id) {
alert('Unsupported page');
return;
}
tweet_id = BigInt(tweet_id);
if (tweet_id < threshold_tweet_id) {
alert(`Unsupported Tweet ID: ${tweet_id} (< ${threshold_tweet_id})`);
return;
}
let timestamp_ms = Number(twitter_epoch_time + tweet_id/(1n<<22n)),
date_obj = new Date(timestamp_ms),
iso_timestring = date_obj.toISOString().replace(/\.\d+Z$/, 'Z');
date_obj.setMinutes(date_obj.getMinutes() - date_obj.getTimezoneOffset());
let timestring = date_obj.toISOString().replace(/T/, ' ').replace(/\.\d+Z$/, ''),
prompt_text = `
[Tweet ID] ${tweet_id}
[ISO 8601] ${iso_timestring}`,
result = prompt(prompt_text, timestring);
if (result !== null) {
navigator.clipboard.writeText(result)
.catch(error => console.info(`Copy to clipboard failed. (${error})`))
// TODO: Firefox だとエラーになる (90.0.2)
// Uncaught (in promise) DOMException: Clipboard write was blocked due to lack of user activation.
.then(() => console.debug(`Copy to clipboard succeeded. (${result})`));
}
})();
- Permalink
- このページへの個別リンクです。
- RAW
- 書かれたコードへの直接のリンクです。
- Packed
- 文字列が圧縮された書かれたコードへのリンクです。
- Userscript
- Greasemonkey 等で利用する場合の .user.js へのリンクです。
- Loader
- @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
- Metadata
- コード中にコメントで @xxx と書かれたメタデータの JSON です。