古い記事
ランダムジャンプ
新しい記事
このブログの記事専用のURL短縮の仕掛けを作りました。
tinyurl.com や bit.ly などのURL短縮サービスの「たつをの ChangeLog」専用ロジックです。
特徴はデータベースを使っていないこと。
ロジックのみで圧縮、展開ができるのでメンテフリーで超軽量です。

ロジックの解説


このブログは chalow というブログツールを使っているのですが、各記事の URL の最後は日付+その日の通し番号となっています。

例えば
「http://chalow.net/2009-01-02-3.html」

「2009年1月2日の3つ目の記事」
を表しています。

このブログでは1日あたり24記事も書くことはないので、何個目の記事を表す通し番号は「時」とみなすことにします。
つまり
「2009年1月2日3時」
となります。

で、「2009年1月2日3時」を10進数の数値にします。
と、その前に chalow でのブログは2000年からなので、年は2009から2000を引いて9にしておきます。
あと計算のため月、日、時はそれぞれ1マイナスしています。
「9年0月1日2時」になります。

さて10進数にしてみます。

((9 x 12 + 0) x 31 + 1) x 24) + 2 = 80378

まあ、ユリウス通日みたいにどこかを基準にした経過日数に変換しても良いのですが、面倒だし本質ではないので上記の式でざっくりと。

これを64進数に変換します。
使う字は下記の64文字。小さい順に並べてあります。
Base64っぽい感じです。

ABCDEFGHIJKLMNOPQRSTUVWXYZ
abcdefghijklmnopqrstuvwxyz
0123456789-_

「2009年1月2日3時」→「80378」の64進数変換結果は下記となります。

Tn6

つまり、 「http://1.jp/」がURL短縮サイトとすると、
「http://chalow.net/2009-01-02-3.html」

「http://1.jp/Tn6」
に圧縮されます。

戻すときは今の手順を逆に進めばOKです。
データベースは不要ながら、なかなかの圧縮率です。

コードと実行例


サンプルコードと実行例です。

■コード(tinytcl.pl):
#!/usr/bin/perl
use strict;
use warnings;

my ($y, $m0, $d0, $h) = (2009,1,2,3);
print "ID(DATE): $y, $m0, $d0, $h\n";

my $ec = clid_encode($y, $m0, $d0, $h);
print "Short CODE: $ec\n";

($y, $m0, $d0, $h) = clid_decode($ec);
print "ID(DATE): $y, $m0, $d0, $h\n";

sub clid_encode {
    my ($y, $m, $d, $h) = @_;
    $m--; $d--; $h--;
    $y -= 2000 if $y >= 2000;
    my $ec = (($y * 12 + $m) * 31 + $d) * 24 + $h;
    my $str = "";
    while ($ec > 0) {
	my $v = $ec %64;
	my $c = substr("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
		       ."abcdefghijklmnopqrstuvwxyz"
		       ."0123456789-_", $v, 1);
	$str = $c.$str;
	$ec = int($ec / 64);
    }
    return $str;
}

sub clid_decode {
    my ($str) = @_;
    my $ec = 0;
    foreach my $c (split(//, $str)) {
	my $v = index("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
		      ."abcdefghijklmnopqrstuvwxyz"
		      ."0123456789-_", $c);
	$ec = $ec * 64 + $v;
    }
    my $h = $ec % 24;
    $ec = int($ec / 24);
    my $d = $ec % 31;
    $ec = int($ec / 31);
    my $m = $ec % 12;
    $ec = int($ec / 12);
    $m++; $d++; $h++;
    $ec += 2000 if $ec < 100;
    return ($ec, $m, $d, $h);
}

■実行例:
% ./tinytcl.pl
ID(DATE): 2009, 1, 2, 3
Short CODE: Tn6
ID(DATE): 2009, 1, 2, 3