前回、ツイッターやマストドンが返す日付テキストが正しいISO8601形式になっていないせいで、webmentionコメント欄の日付が狂ってしまう問題が発覚しました。どうしても気になったので仮対応しました。

対応

正しいISO8601に強制修正する処理を書きました。

サーバ 返ってくる書式 対応
Mastodon(mstdn.jp, pawoo.net 2022-05-24T02:49:03 末尾にZを付与した
Twitter 2022-05-27T22:09:18+00:00 +00:00+09:00に置換した

あとはそれをDate型に変換し、それをキーに降順ソートして、統一した書式で日付表示するようにしました。

確認したこと

pawoo.netの日時テキストもmstdn.jpと同じでした

その原因はおそらく、同じコードを使っているからでしょう。どちらもMastodonのインスタンスなので、日付の部分のコードはそのまま流用したのだと思われます。

あらためてISO8601形式のタイムゾーンがおかしいと時間がずれることを以下コードで確認しました

date.html

<script>
function show(iso) {
    const epoch = Date.parse(iso)
    const date = new Date(epoch)
    console.log(iso)
    console.log(epoch)
    console.log(date)
    console.log(date.toISOString())
    console.log('--------------------------')
}
show('2022-05-24T02:49:03Z') // 正しく日本時間に変換できる
show('2022-05-24T02:49:03')  // 日本時間から9時間マイナス
show('2022-05-27T22:09:18+00:00') // 日本時間から9時間マイナス
show('2022-05-27T22:09:18+09:00') // 正しく日本時間に変換できる
</script>

日時がnullのメンションがありました

ツイートのいいね!でした。でも、日付をもっているいいね!メンションもあるようで。その違いはどこからくるのか。原因不明。

なんにせよ日付でソートするので、ないと困ります。そこで、もし公開日時publishedがなければ、代わりにwm-receivedを使うことにしました。これはwebmentionがコメントとして取得するようリクエストを受けた日時だと思われます。

心配なこと

Mastodonが将来、この日付バグにどう対処するのか。たぶん問題ないのですが、特殊な修正をされたらバグるでしょう。

今回マストドンは次のコードのように修正すればOKでした。publishedはサーバから返ってきた日付テキストです。もし末尾にZがないなら、それをつけるよう対処しました。

if (!published.endsWith('Z')) { return published + 'Z' }

もしMastodonのサーバ側が急に「あ、正しいISO8601に直さなきゃ!」と思って2022-05-24T02:49:03Zのように末尾にZを追加してきても、その場合は何も処理しないため、正しい形式のままです。末尾がZZになったりはしません。

ところで、正しいISO8601形式って、他にもあるんですよね。2022-05-24T11:49:03Z+09:00です。これでも正しいんですよ。そしてこれ、末尾にZがついてない! だから今回の修正で書いたコードに従い、末尾にZがついちゃいます。2022-05-24T11:49:03+09:00Z。でもこれは不正なISO8601形式です……。

というわけで、+09:00形式で修正されたとき用に次のようにコードを書きました。

this.timezone = new RegExp(/[+\-][0-9]{2}:[0-0]{2}$/);
if (published.match(this.timezone)) { return published } // 将来マストドンが正しく修正したとき用
if (published.endsWith('Z')) { return published }        // 将来マストドンが正しく修正したとき用
if (!published.endsWith('Z')) { return published + 'Z' } // 今回はこれだけで大丈夫
return published

タイムゾーンの書式は末尾がZか、あるいは+-00:00のような書式の2パターンあります。なので、その条件に一致したら正しいISO8601形式と判断して、そのまま返すコードも追加しておきました。これでマストドンが正しい値を返すよう修正しても安心です。

もちろん、タイムゾーン以外がまちがっていても、そのまま返してしまいます。もう完全にサーバ依存です。お願いですから正しい値を返してください。下々の者は祈るしかありません。

まだ問題があります。タイムゾーンの書式は時間だけでいいパターンもあります。でも、これには今回、非対応です。あまり見たことがない書式なので。大抵タイムゾーンは30分刻みになるため分単位も入っていたような気がします。

いずれにせよ、ISO8601の全パターンに対応するとなると面倒なんで、代表的なパターンだけに対応することにしました。もしマストドンがタイムゾーンを+09とかにしやがったら対応できません。

タイムゾーン書式 対応
hh
hhmm
hh:mm

こうなるかどうかわかりもしないうちに、ムダにコードを複雑化するとか、バカみたいですからね。もうすでにバカみたいなことやってるんですけど。この辺の塩梅をどうするかもむずかしい判断です。コード書いたほうが早くね? って言える人になりたいので書きました。

対応できなかったこと

Twitterで+00:00タイムゾーンの人からツイートされたとき、時刻が9時間プラスされて未来になってしまいます。これには対応できません。

今回、次のように修正したからです。

if (published.endsWith('+00:00')) { return published.replace('+00:00', '+09:00') }

ことの発端は、いただいたツイートのタイムゾーンが+00:00だったことです。おそらく日本の方でタイムゾーンも日本の+09:00だと思うのです。なのでツイッターがおかしな日時テキストを返したのだろうと思っています。違ってたらごめんなさい。

とにかく、その前提で今回のコードにより+00:00を強制的に+09:00に変換しちゃいます。なので正しく+00:00のタイムゾーンにいる人は、9時間分だけ未来人になってしまいます。ジョン・タイターになれます。禁則事項です。マーティン&デロリアンです。

もし、ツイッターがすべてのタイムゾーンを無視して+00:00にするのだとしたら? もし、私のサイトに世界中からコメントが来たら? 世界中のローカル時刻が入り乱れ、ずれずれの時間で表示&ソートすることになるでしょう。

世界に名だたるツイッター様がそんな凡ミスをしているとも思いにくいので、私が何か勘違いしているような気もしますが。