Twitter上の日時表示の場所をSnowFrakeを元にミリ秒単位の表示に修正します
// ==UserScript== // @name displayMillisecOnTwitter // @namespace https://twitter.com/kymn_ // @version 0.1.3 // @description Twitter上の日時表示の場所をSnowFrakeを元にミリ秒単位の表示に修正します // @author keymoon // @license MIT // @supportURL https://twitter.com/kymn_ // @match https://twitter.com/* // ==/UserScript== (function(){ //Body子要素更新の監視(急激なページレイアウトの変化、要するにユーザーページ等他ページとの遷移) (() => { const body = document.getElementsByTagName('body')[0]; const bodyobserver = new MutationObserver(records => {resetObserver()}); const bodyoptions = {childList:true,subtree:false} bodyobserver.observe(body,bodyoptions) var lastHref; var observers; //ページが更新されたらHrefが変わったか確認、変わってたらObserver張替え function resetObserver(){ if(location.href === lastHref) return; lastHref = location.href; if(observers){ console.dir(observers); observers.forEach(x => x.disconnect()); } observers = []; console.dir("update"); //タイムライン更新の監視 observers.push((() => { //始めに一回オーバーライドしてあげる OverrideToolTip(); const target = document.getElementById('stream-items-id'); const observer = new MutationObserver(records => {OverrideToolTip()}) const options = {childList: true}; observer.observe(target, options); return observer; //各ツイートのツールチップの書き換え function OverrideToolTip(){ $('.tweet-timestamp').each(function(index, element){ var date = getDateFromSnowFrake(element.getAttribute('data-conversation-id')); if(!date)return; element.setAttribute('title',formatDate(date)); }) } })()); //画像ツイート更新の監視 observers.push((() => { const target = document.getElementsByClassName('GalleryTweet')[0]; const observer = new MutationObserver(records => {OverrideTimeStamp()}) const options = {attributes: true}; observer.observe(target, options); return observer; //ツイートのメタデータ部の書き換え function OverrideTimeStamp(){ var timeStamp = target.getElementsByClassName('tweet-timestamp')[0]; if(!timeStamp)return; var date = getDateFromSnowFrake(timeStamp.getAttribute("data-conversation-id")); if(!date)return; timeStamp.setAttribute('title',formatDate(date)); } })()); //ツイート詳細ウィンドウの開閉の監視 observers.push((() => { const target = document.getElementsByClassName('PermalinkOverlay-modal')[0]; const observer = new MutationObserver(records => {OverrideMetaData()}) const options = {attributes: true,subtree:true}; observer.observe(target, options); return observer; //ツイートのメタデータ部の書き換え function OverrideMetaData(){ var tweetContainer = target.getElementsByClassName('permalink-tweet')[0]; if(!tweetContainer)return; var date = getDateFromSnowFrake(tweetContainer.getAttribute("data-tweet-id")); if(!date)return; target.getElementsByClassName('metadata')[0].textContent = formatDate(date); } })()); //アカウント画面のアカウント登録日時 (() => { var joinDate = document.getElementsByClassName("ProfileHeaderCard-joinDateText")[0]; if(!joinDate)return; var date = getDateFromSnowFrake(document.getElementsByClassName("ProfileNav")[0].getAttribute("data-user-id")); if(!date)return; joinDate.setAttribute("title",formatDate(date)) })(); } })(); function getDateFromSnowFrake(ID){ if(ID < 10000000000) return; var unixTime = Math.floor(parseInt(ID) / 4194304) + 1288834974657; return new Date(unixTime); } function formatDate(date){ return `${date.getHours()}:${date.getMinutes().toString().padStart(2,'0')}:${date.getSeconds().toString().padStart(2,'0')}.${date.getMilliseconds().toString().padStart(3,'0')} - ${1900 + date.getYear()}年${date.getMonth() + 1}月${date.getDate()}日` } })();