週番号の仕組みと普及
はい、じゃあ前回に引き続いて、カレンダー開発の怖い話、TimeTreeTechTalkでお送りしていきます。
また例によって、シオンとスコットに話を聞いていきたいと思ってますが、よろしくお願いします。
今日は、週番号の、前回も話出ましたけど、週番号、あと繰り返し予定ですね。
はい、まず週番号って、あまり馴染みがないと思うんですけど。
ないですね。
はい、どういうものかっていうと、1年の最初の週から投資番号を振ってあって、
大体1年に52週か53週あるので、その番号で週を特定するっていうやり方です。
日本だと大体、月曜日の日付とかで、何月何日の週とかっていう言い方をすると思うんですけど、
ヨーロッパとかでは、週番号っていうのが普及してて、日付のやり取りをするときに、第何週の何曜日みたいな言い方を使ったりするらしいんですね。
カレンダーにも普通にその週番号書いてあるし、プリの機能としても必須のものとなっているらしくて、
タイムツリー当初は、リリース当初は対応してなかったんですけど、結構ドイツとかのユーザーが多くなってきて、
ご要望が非常に多く上がってきたので、対応したっていう経緯があります。
なるほど、全く馴染みないですね。でもこれは日本人の僕らからすると。
そうですね、そういう意味で言うと文化が知れて面白いなって僕は結構思った事例だったんですけど、
第何週って言われてもピンとこないなっていうのは未だにありますね。
何が怖いのっていう話なんですけど。
そこですね、本題ですよ、本題。
国による週の決め方の違い
第1週目がどの週なんだっていう問題があるんですよ。
なるほど。
そうですね、1年の始まりの曜日って毎年違うじゃないですか。
なので、ある基準でこの週を第1週とするって決めないといけないんですよね。
この決め方が実は国によって違うっていう話なんですけど。
怖いですね。
いろいろあるけど、アメリカ式とヨーロッパ式に大きく2つに分かれているらしくて。
アメリカ式は、まず週の始めを日曜日にしますと。
1月1日が含まれる週が第1週っていうルールです。
なるほど。
で、もう一方のヨーロッパ式なんですけど。
ヨーロッパは週の始めは月曜日です。
その年の最初の木曜日が含まれる週が第1週っていう。
木曜日、なんか決めくれてるな。
月曜始まりだと木曜が真ん中なんですよね。
その真ん中の週が含まれるのがその年の第1週だっていう決め方で。
わかるっちゃわかる。
なるほど。なんか今僕、官平を読んでて地面で読むとすごい複雑に見えるけど。
確かに木曜日真ん中なの。
月曜始まりだと月火水と金土日があって木曜日が真ん中になるってわけですね。
なるほど。
そうですね。
なので、例えばアメリカ式だと1月1日が土曜日とかだと、
その週土曜日しかないのに1週間まるまる第1週ってカウントするみたいなことになるんですよね。
確かに。
という意味だとヨーロッパ式だと、
多く含まれてる方がその年の週、第1週になるっていう形なんで、
それはそれでわかるなっていう。
これ言ったら語弊があるかもしれないですけど、やっぱりアメリカンな決め方ですね。
わかりやすい。
そうです、確かに。
語弊があるかもしれないけど非常に大雑把。
こういうのででも文化の違いが出るのかな。
なるほど、面白い。
面白いけど怖い。
怖くなってきました。
日本は使われてないんですけど、一応その終盤後表示はできて、
iOSの標準カレンダーで表示ってやるとアメリカ式で表示されるようになってます。
お気づきかと思うんですけど、
年によってこの2つの方式で終盤後がずれるってことが起きるんですよね。
2023年これずれてないですか?
2023年ずれてますね。
あと2022年もずれてるんですけど、
これが多分わかりやすくて、
2022年の1月は1月1日が土曜日なんですよね。
なのでアメリカ式になると1月1日の週が第1週になるんですけど、
そうすると12月26日の日曜日から1月1日の土曜日が第1週っていう決めになります。
対してヨーロッパ式にすると最初の木曜日が1月6日になるので、
1月3日から1月9日までが第1週になるっていう形で、
1週間ずれるっていう。
嘘だった。ごめんなさい。2023年ずれなかった。
1月1日日曜日だからずれないんだ。
日曜のアメリカ式。
確かにそうですね。
もうその時点で怖い。
怖くなってきただんだん。
で、これタイムツリーもちゃんと対応はしてて、
タイムツリー設定に終盤号の表示非表示の設定があるので、
ヨーロッパのユーザーはデフォルトでオンになってるんですけど、
日本のユーザーだとデフォルトはオフなので、
これをオンにしてもらうと基本的にアメリカ式で終盤号が表示できます。
これはただiPhoneの本体側の設定に地域設定っていうのがあるんですけど、
そこで国を日本にしてればアメリカ式になるんだけど、
それをヨーロッパの国に変えるとヨーロッパ式になります。
これRubyの実装だとどうなってるんだろう?
わかんない。
終盤号って一応あるにはあるんで。
バックエンド側でも使う場所ってあります?
使ってはいないんですけど、
これ知らずに普通に扱ってたらなんか怖いなと思って。
サーバーとかだと基本的にデータはUTCで扱うから、
ひょっとしたらヨーロッパ式になるのかなとか思ったりしてたんですけど、
タイムゾーンとかによって変わるのかな。
収録中なのにちょっとタイミングを起動して確かめたけど。
今スコットがめちゃくちゃそばそばしだしてる。
怖い怖い怖い怖い。
1週間のズレって結構カレンダー上ではかなりデカいズレですよね。
グローバルの企業で困ることあるんじゃないかって思うんですけど、
確かに。
どっちの基準に合わせるって決めで運用してるのか。
どうなんですかね。
例えば47週に請求書出すわみたいなので、
47週が全然違うってことですよね。
そうですね。
ヨーロッパとアメリカで。
怖いなあ。
これ実装上も結構怖いんですか。
終盤号自体は、
iOSの標準のフレームワークに終盤号を取得する仕組みがあるので、
それを正しく使ってる限りは大丈夫ですね。
ユーザーさんの設定した地域をちゃんと反映して表示させるっていうところができていれば、
大丈夫っていう感じになります。
もう一個怖い話が関連してありまして、
日付を文字として画面に表示するっていうことがあるんですけど、
その時にどういう文字にするかっていう指定するためのフォーマットがあって、
その記述ルールが決まってるんですね。
年の指定方法による表示のズレ
例えばこのY年M月D日みたいなフォーマットを指定すると、
2023年8月24日みたいな文字になるっていうこういうフォーマットがあって、
このYが年に対応するよっていうのがルールとして決まってるんですけど、
年を指定するのに小文字のYと大文字のYがあって、
実はこれ意味が違うんです。
なんと。
これ実際にコードで小文字のYと大文字のYをプリントしたときに何が出るかっていうと、
2023年12月31日のYを取得したときに、
小文字のYは2023って出るんですけど、
大文字のYにすると2024って出るんですよ。
めっちゃ確かにこの怖さすごいわかる。
なるほど。
知らないと理解できないやつですね。
そうですよね。
この大文字のYは実は終盤号基準の年になるので、
2023年12月31日は2024年の第一週になるから、
このYで出力すると2024っていう数字が出てしまうと。
これ実際に不具合を出したことがあります。
懺悔。
多味があるな。
これ多分結構あると思います。他の会社でも。
これ大文字のYでやって普通に1年のほぼほぼ大体は同じ正しい数字が出るので気づけないんですよ。
年末になってあれってなるって。
やばい。年末になるとだから1年ずれちゃうってことですね。
そうですね。
ミスると。これすごいですね。
今ちなみにRubyで確かめてみたんですけど、Rubyはヨーロッパ式でした。
ひょっとしたらシステムのタイムゾーン使われてるのかもしれないんですけど、
タイムゾーンのあれがないクラスでも出るのでちょっと怖いですね。
逆にアメリカ式で出す方法とかないんですかね。
ないんですかね。
深みにはまりそうだぞ。
あー怖い。
あー怖い怖い怖い。
タイムツリーはこれリリースしてからしばらくしてドイツの方からのお問い合わせとか要望で対応した。
そうですね。
カルチャライズっていうらしいですね。前スタッドが言ってたけど。
その国とかの文化に合わせて。
昔ドイツにユーザーインタビューしに行った時に、みんなドイツの壁掛けカレンダーじゃないけど、
ドイツのカレンダー買って帰ってきた。そこが要はその国の日常のはずだから。
日本では土曜日が青いっていうのは普通じゃないですか。
あれでも多分日本独自っぽいんですよね。
そうらしいですね。
韓国とかもそうかもしれないですけど。
一回そのデザイン変えて土曜日を普通に黒くしてたら結構お問い合わせあって、青に戻してくださいっていう。
今は設定で土曜青にするっていうオンオフがあって、日本はデフォルトで青いんだけど海外とかは黒くなってるとか。
それ覚えてますね。
それ僕入社してからだな。すごい覚えてる。
確かに土曜が青で日曜が赤。祝日も赤みたいなのは僕らからすると慣れ親しんだ感じですかね。
もう怖い話終盤後編はこんなとこですか怖い話は。
大丈夫ですか。もうないですか。びっくりしてるんですけど。
はい。一旦大丈夫です。
もうラスボスがあるんですね。ラスボス。
もう1個じゃあ繰り返し予定っていうやつに入っていきたいと思うんですけど。
これは結構タイムツリーのエンジニアみんなが意味嫌う言葉。
そうなんだ。
繰り返し予定のルールと実装
何かっていうと普通に毎週月曜日とか毎年何月何日みたいな繰り返し予定を
登録するのって当たり前に使ってると思うんですけど。
これあの実装するのは結構大変だっていう話ですね。
予定をシステム上でどのように表現するかっていう標準仕様があって
iカレンダーっていうものなんですけど
でその一部としてこの繰り返しルールを表現するための
Rルールっていう書式があります。
インカレンスルールっていうものなんですけど
これは毎週月曜日みたいなやつを決められた文字列で表現するっていうルールなんですけど
タイムツリーに予定登録した時に繰り返し予定はデータとしては1つしかないです。
なんですけどその一つの予定の中にRルールっていう項目があって
そこにこの予定は毎週月曜日の繰り返しですよみたいな情報が書き込まれているっていうイメージですね。
でまぁここまではふーんっていう感じじゃないですか。
はい非常に安定して聞けてますまた。
でこれをじゃあカレンダーに予定を表示しますってなった時に
その何月何日の何月のカレンダー表示するときは何月何日から何月何日までの予定を
どういう予定があるかデータから引っ張ってきて
それを一個ずつ画面に表示していくっていうことになるんですけれども
ある日付の期間この日からこの日までの予定の中に
その繰り返し予定が入っているのかどうかっていうのを確認しないといけないんですね。
それが実はやろうと思うとすごい難しいんですけど
例えば毎週月曜日とかだったら
普通に月曜日に一個ずつ入れていけばいいじゃんって思うかもしれないんですけど
繰り返しのルールってものすごい膨大なパターンがあって
例えば何週起きとか2週起きの月曜日とか
3週起きの月曜日みたいなものがあったりするんですよね。
そうするとその範囲にその予定どこに入るのっていうのパッとわからないと思うんですよ。
なのでそのRルールに従ってその予定が実際に何月何日に入ってくるのかっていうのを
バーッと全部展開していって
そこからその範囲に入っている予定だけをピックアップして表示するみたいなことをする必要があると。
なのでここがちょっと技術的に難しいポイントですね。
確かに。
毎週月曜日とかだったらまだいいんですけど
繰り返し何回100回とかは本当に難しくて
うーん。
全部展開しないとわからない。
それって裏側でバーッと展開されたデータを読みに行って
で表示に反映させてっていう
なんかその長いサイクルが裏側で常に回っているってことですね。
そうですね。
そうですね。
iOSアプリの仕様と問題点
でこれが実はそのiOSアプリの側で
結構長年にわたって付載になっていた部分に関連しているんですけど
当初のTimeZのiOSアプリは
サーバーから取ってきた予定のデータを
一旦その繰り返しを展開した形で
ローカルに保存するっていう方法を取ってたんですね。
なので毎週月曜日のやつは毎週月曜日の予定を
全部バーッと展開して
展開したものをローカルに保存するっていうことをやって
そうすると表示するときは
すでに展開されたものを表示するので
表示のパフォーマンスはいいっていう
メリットはあるんですけど
要は繰り返しって無限に繰り返せるんで
どっかで上限を決めないといけないんですよね
そうすると5年分までしか繰り返せないみたいな
制限がかかってしまう
そこの辺がAndroidとかWeb版とかと
仕様のズレが起きちゃって
これ何とかしないとねっていう話になり
AndroidとかWebとかはもともと
データ自体はそのままワークエンドから持ってきて
表示するときに繰り返しの展開をした上で
表示するっていう方法を取っていて
iOSの方もそのやり方に合わせるっていう
対応したんですけど
とにかく予定の表示に関するところなので
アプリのあらゆる場所に影響するので
ものすごく直すのは大変だったっていう
なるほど
iOSの場合はローカルにデータが溜まる
だから要するに挙動がちょっと重くなるとか
そういう話ですか
そうですね
繰り返し予定が多ければ多いほど
予定をダウンロードしてきたときに
その展開の処理もものすごいたくさん入ることになるので
その予定の動機により時間がかかっちゃったりとか
なるほど
してました
iOSだけ仕様が違ったのは何でだったんですか
ちょっとそこの経緯わかんないんですけど
最初にこの機能繰り返し予定の機能自体は本当に
最初のバージョンからあったので
最初に作った人の判断でそうなっていて
フラットフォンでズレが生じていたっていう感じですね
タイムツリーは予定にコメントとか付けられるんで
コメントするとコメントってその日だけなので
繰り返し予定が外れたりとか
余計に処理が複雑になったり
普通のカレンダーアプリと違って
繰り返し予定にもコメントを付けると
その週だけコメントが表示されるとか
その辺がちょっと何か特殊な処理を
いろいろやってる
そうですね
例えば繰り返し予定の中で
この予定だけちょっとスキップされて
消すみたいなこともすると思うんですけど
そうすると元の繰り返し予定の
この日は除外するみたいなデータを差し込んで
見えなくするみたいなことをやってたりとか
さっき言ってたように
コメントしたりとか
いいねしたりとか
参加したりってすると
それは元々の繰り返し予定と
別の予定になるので
データが新しく加わるんですね
その予定が繰り返し予定の一部から
単体の予定に昇格して
予定が一個新しくできるってイメージですね
元の繰り返し予定からは
その日だけ除外されるみたいな
目が回ってきました
なるほどね
外部カレンダーの対応と不正データ処理
これでも結構スコットが一時期
すごい苦労してた
そうですね
僕はでもちょっと苦労してたのは
Rルールって標準化されたルールなんで
そのルールに従ってると
大丈夫だよっていう感じなんですけど
タイムツリーのデータには
そこから外れた変なデータが
いっぱい入ってるっていうことがあって
ちゃんとマリネーションしてなかった
っていうのがあるんですけど
その変なデータがなぜかうまく表示されてしまう
っていうこともあったんで
それをサーバーでどうやって取り扱うか
あとタイムツリーって
外部のサービスからインポートする
っていう機能があるんですけど
それによってちょっとなんか不思議な
Rルールが書かれてたりとか
標準にないRルールがいっぱい
データとして存在して
一時期すごい困るっていうのがありましたね
その一部の不正なデータが残ってるんで
後からバリデーション追加しようとすると
アプリケーションの挙動によるんですけど
その不正なデータがいきなり壊れてしまうように見える
ちょっと困るのでまだバリデーションかけられないとか
そういう困ったところがありますね
でもカレンダーには欠かせない機能だし
タイムツリーだとめちゃくちゃ使われてるんじゃないですかね
この機能って
そうですよね
お誕生日とか何かの記念日とか
何か定期的に来る家事の予定とか
僕も不念ごみって入れてますもん
結構だから普通に使われるんですけど
タイムツリーにないデータだけでもそうだったりするんですけど
外部のカレンダーからそういうデータをインポートしてくれると
カレンダーその外部のカレンダー独自の仕様とかの
何これみたいなことになって
やばいですね
パルプンって食らったことがありますね
多分その普通のサービス
アイカレンダーRルール
インターネットの世界で標準化されてるものなんですけど
旧歴サポートしないんですね
外部のカレンダーでちょっとどういう経緯で入ってきたかとか
全然定かではないんですけど
1年に1回みたいな予定で
旧歴で1年に1回みたいな感じの
その謎データが入ってたりして
ん?ん?みたいな
旧歴?
旧歴わかるけどみたいな
タイムツリーも一応旧歴の
旧歴で1年に1回みたいな
確かサポートしてるはいるんですけど
Rルールに従うような形で
強引に解釈して書いてるところがあるんで
ちょっとデータ量として多くなったりとか
そういうのがあったりはするんですけど
Rルールを独自解釈した何かを
インポートされてくると動かないっていうやつが
ちょっと困りますね
プログラミング言語にRルールに従って
データを展開するようなライブラリーとか
存在してるんですけど
カレンダー開発の怖い話
壊れてるデータだといきなりエラーになるんで
そういうライブラリーが使えないっていうか
使うと壊れる
使うとそのデータがある人だけ
なんかよくわからないけど予定が壊れるみたいな
ちょっと謎現象も起こったりして
どうしたのかなって思ったことがありましたね
iOSは当初Rルール解釈するのに
なんかオープンソースのコードを持ってきて
それを独自にこちら側で書き換えた
独自のパーサを使ってたんですよ
怖いですよね
それ怖いですね
多分それの影響だと思うんですけど
Rルールの中に何月何日
繰り返し予定何月何日までっていうデータが入ってるんですよね
例えば2023年8月24日までみたいなデータがあるんですけど
表現としてはアラビア数字で
20、23、08、24って書かれてるんですけど
アラビア語の右読みの数字が書かれてることがあって
やばー
言語の変換が効いちゃって
数字がその
なんかうん?みたいな
そういう数字になってることもあるんですけど
アラビア数字じゃない
普通の数字って何?
アラビア数字は普通なんですけど
アラビア語の数字みたいなのかな
そうですね
見えますね
そうそうアラビア語の数字
判別できない
見すぎてだんだん読めるようになってきましたから
それってどういう経路で入ってきたのか謎なんですか
確かiOSの独自パーサーを使ってたから
使ってる人の言語によって
数字のデータがその言語で入っちゃう
そういうこと?
そうそれでアラビア語数字になっちゃって
サーバーにはそれで投稿されてきて
当然パーサーで読むと壊れる
他の言語のパーサーで読むと壊れるっていう
いいですね今シオンのいい渋い顔が見れましたよ僕
画面の向こうでこういう顔してんだろうなーみたいな
開発が大変なとき
本当だから独自パーサー使ってるときは
無限ループになる不具合とかあったりして
いろいろ大変だったんですけど
今はLibAicalっていう
繰り返し予定の問題と改善
C言語で書かれたライブラリを利用しているので
あんまり変なことは起きないはずなんですけど
外部のカレンダーからインポートできる機能があるので
それによってなんかよくわからない
繰り返し情報が入ってきて
なんかおかしいんですってお問い合わせが来て
データの中を見ると
このRルールはどうやって入力するんだみたいな
謎のものがいっぱいありますね
カレンダーサービスによって本当にオリジナルで定義している
標準をオリジナルで定義しないでくれって思いはいっぱいあるんですけど
ルールは守りましょう
それこそサーバーを最初そのバリデーション入れてなかったのもあって
そこら辺が全部すずおりしてたんですけど
バリデーションを厳しくすると突然予定がインポートできなくなった
ってお問い合わせが増えて
なんでか調べたらRルールのバリデーションが厳しすぎて落ちちゃったっていうのがあって
そのRルールを緩くするかどうかっていうのを一時期考えたことがあるんです
緩くすると逆にRルール全部消した
こっちのタイムツリーのやつで動かないので
どっちにしても繰り返し予定が繰り返し予定として表示されないんで
おかしいっていうふうになるはなるんですけど
結構最後に書いてありますけど
iOSのリポジトリでもイシュー件数が結構あるんですね
そうですね繰り返し予定に検索したら100件ぐらい出てきたんで
めちゃくちゃある
この繰り返し予定改善は未だに戦っているところなんですか
それとも結構技術不細は
これはもう一旦
めでたしめでたしっていうことになります
繰り返し予定を設定するUIも
いろんなパターンに対応しなきゃいけないので
UI関連の風が結構あったと思います
まあでも余談を許さない案件ってことですねこれは
そうですねどこまでそうやるかっていうところはありますね
ちゃんとしたいとか
そういうところもありますね
標準に従いたいなっていうのが
サーバーサイドのエンジニアとしては気持ちとしてはある
なるほど
2回にわたってお送りしましたけど
僕も最後が一番怖かったし
現在進行形の問題ですからね
かなり脳みそに混乱をきたしましたねこれは
繰り返し予定タイムゾーンの指定とかもあるんですけど
それもまた怖い話がちょっといつかあります
これって繰り返し予定と
何か前回の放送で出てきた
例えばサマータイムとか複合的に
複合的に絡んで
そう
より怖くなりますね
繰り返すと例えばその時間ないとかっていうのがあるじゃないですか
サマータイムを止めつける時間とか
どうなってんの
正直ちゃんと理解できてないです
どうなるのかわからないですね
多分人類にはちょっと早すぎる
面白い
繰り返しっていうのは
シオンで理解できてなかったらもうちょっと
誰もわからないみたいな
じゃあ2回に渡ってやりました怖い話ですが
今後も怖い話は定期的にしていきましょうね
夏だけにしましょうよ
毎夏だけね
暖まる話しましょうよ
そうですね
暖かくなる話もちょっとシオン待ってます
思いついたら
ありがとうございます
ありがとうございました
ありがとうございました