前提・実現したいこと
タイムスタンプを持つとあるデータに対する「時刻情報+その他情報」による複合キーを、「できるだけ少ない文字数」かつ「どのデータでも同じ文字数」でも表現したいと考えています。
ここで、特に「時刻情報」に関して、何某かの知恵をお借りしたいと思い投稿しました。
つまり、よくある「yyyy-mm-dd HH:MM:SS」というタイムスタンプから得られる情報をを、できるだけ少ない文字数で表現したいです。
例:「yyyy-mm-dd HH:MM:SS(19文字)」→「yyyymmddHHMMSS(14文字)」
ただ、検索してもあまり情報がなく、自分だけの考察では手一杯な感触を得ています。
そこで、なにか方法がないかお聞きしたく、投稿させていただきました。
※検索しても出てこない=そもそもそんなこと考えずに別の方法を考えるべきだという啓示な気もしますが…
試したこと
日時情報を、UNIX秒に変換する方法と、変換したUNIX秒をn進数に変換する方法を思いつきました。
※n進数の変換は、一般に用意されるようなアルゴリズムではないと思っているため、別途何某か変換用のスクリプトを組む必要があると思っています。
※36進数=0~9,A~Zまでの36文字、62進数=0~9、a~z、A~Zの62文字、94進数=ASCII文字33番(0x21)[!]~126番(0x7e)[~]までの94文字と想定しています
※「データの圧縮」というキーワードから連想し、「可逆圧縮アルゴリズム(ランレングス符号、ハフマン符号、LZ77、LZSS、LZW、Deflateなど)」が使えないかと調べたこともあるのですが、たかだか14文字の数字データを圧縮するような話とは別では…?と思ってしまい、深くは調査しませんでした。
概要 | 桁数 | 表示データ | 範囲 |
---|---|---|---|
そのまま表記 | 14桁 | 2021/09/30 05:16:04 | 9999年以上 |
UNIX秒 | 10桁 | 1632978964 | 9,999,999,999(10進数10桁)→'2286-11-21 02:46:39' |
UNIX秒を16進数変換 | 8桁 | 61554814 | 0xFFFFFFFF(16進数8桁)→4,294,967,295(UNIX秒)→2106-02-07 15:28:15 |
UNIX秒を36進数変換 | 6桁 | R08EMS | zzzzzz(36進数)→2038-12-24 05:45:35 |
UNIX秒を62進数変換 | 6桁 | 1MvOqo | ZZZZZZ(62進数)→56,800,235,583(10進数)→3769-12-05 03:13:03 |
UNIX秒を94進数変換 | 5桁 | 7o1RY | ~~~~~~(94進数)→7,339,040,223(10進数)→2202-07-26 14:17:03 |
お聞きしたいこと
以下の2点についてお聞きしたいです。
- 上記アプローチが、あまりにも突拍子のない、変な方法なのかどうか?
- 他に考えられる方法はないか?
おかしな質問かもしれませんが、、何卒よろしくおねがいします。
追加検討した結果
UNIX秒をオフセットする
UNIX秒は1970/1/1からの経過秒数なので、固定値でオフセットし、2020/1/1からの経過秒数にしてみる。
→表示できる範囲が50年分だけ後ろにオフセットされる。ただし、"桁数"の観点からからいうと、表示できる範囲が変わるわけではないので、長いスパンで考えると大差なく、桁数を削減できるほどの効果は得られないと思われる。
0秒='1970/1/1'を基準にした場合(通常) → 0秒='2020/1/1'を基準にし直した場合(工夫あり)
桁数 | unix秒(開始) | unix秒(終了) | 表現できる範囲(開始) | 表現できる範囲(終了) | 50年分オフセットした場合(終了) |
---|---|---|---|---|---|
1 | 0 | 9 | 1970/01/01 00:00:00 | 1970/01/01 00:00:09 | 2020/01/01 00:00:09 |
2 | 0 | 99 | 1970/01/01 00:00:00 | 1970/01/01 00:01:39 | 2020/01/01 00:01:39 |
3 | 0 | 999 | 1970/01/01 00:00:00 | 1970/01/01 00:16:39 | 2020/01/01 00:16:39 |
4 | 0 | 9999 | 1970/01/01 00:00:00 | 1970/01/01 02:46:39 | 2020/01/01 02:46:39 |
5 | 0 | 99999 | 1970/01/01 00:00:00 | 1970/01/02 03:46:39 | 2020/01/02 03:46:39 |
6 | 0 | 999999 | 1970/01/01 00:00:00 | 1970/01/12 13:46:39 | 2020/01/12 13:46:39 |
7 | 0 | 9999999 | 1970/01/01 00:00:00 | 1970/04/26 17:46:39 | 2020/04/25 17:46:39 |
8 | 0 | 99999999 | 1970/01/01 00:00:00 | 1973/03/03 09:46:39 | 2023/03/03 09:46:39 |
9 | 0 | 999999999 | 1970/01/01 00:00:00 | 2001/09/09 01:46:39 | 2051/09/09 01:46:39 |
10 | 0 | 9999999999 | 1970/01/01 00:00:00 | 2286/11/20 17:46:39 | 2336/11/20 17:46:39 |
base64で変換する
元のバイナリデータを、アルファベットの小文字(a~zの26文字)とアルファベットの大文字(A~Zの26文字)と数字0~9(の10文字)と「+」と「/」の計64文字を用いた文字列でエンコードするものです。上述で投稿者が勝手に考えた基数変換とは微妙に異なるものだと思っています。
使い方としては、「UNIX秒」を「整数型」としていったん「バイナリ」に変換し、base64のルールに則って、「6bitずつ文字列にエンコード」する感じです。
エンコード結果は4文字区切りでないといけないので、4文字or8文字or12文字…となります。
「64文字x8桁」の表現ができれば、281,474,976,710,656(281兆通り)の情報量を持つことができるので、もしミリ秒UNIX秒にしても事足りそうな気がします。
回答2件
あなたの回答
tips
プレビュー