Translate

2012年9月14日金曜日

その2 ルートについて

■ルートの指定
まずは、ヘルパースクリプトを使ってルートの確認
#!/usr/bin/env perl                                                                                       
use Mojolicious::Lite;

# Documentation browser under "/perldoc"                                                                  
plugin 'PODRenderer';

get '/' => sub {
  my $self = shift;
  $self->render('index');
};

app->start;
__DATA__

@@ index.html.ep
% layout 'default';
% title 'Welcome';
Welcome to the Mojolicious real-time web framework!

@@ layouts/default.html.ep


  <%= title %>
  <%= content %>

該当部分は、以下のコードですね
get '/' => sub{};


1.静的パス
get '/foo/bar/baz1' => sub {shift->render(text=>'/foo/bar/baz1'};
get '/foo/bar/baz2' => sub {shift->render(text=>'/foo/bar/baz2'};
get '/foo/bar/baz3' => sub {shift->render(text=>'/foo/bar/baz3'};

http://localhost:3000/foo/bar/baz1
http://localhost:3000/foo/bar/baz2
http://localhost:3000/foo/bar/baz3
それぞれにアクセスしたら
/foo/bar/baz1
/foo/bar/baz2
/foo/bar/baz3
と表示されます


2.動的パス
実際のところ、静的なパスより動的なパスの方が多いと思うので
一番最後のパスは動的に変わるとしたら…
get '/foo/bar/:baz' => sub{
  my $self = shift;
  my $baz  = $self->param('baz');
  $self->render(text => '/foo/bar/' . $baz);
};

:名前 は、ドットとスラッシュ以外の全てにマッチします。
そして、shift->param('名前')で値を取り出せます。


ただ、静的パスの例のようにbaz+数字にヒットさせたい場合
上記の方法では、それ以外のパターンもヒットするので困ります。
こういった場合、正規表現を指定することで解決できます。
get '/foo/bar/:baz' => [baz => qr/baz\d+/] => sub{                                                        
  my $self = shift;
  my $baz  = $self->param('baz'); #stashにも登録されている $self->stash('baz')
  $self->render(text => '/foo/bar/' . $baz);
};


ルートの指定についてはいろいろあり紹介しきれないので
こちらを参照するとよいと思います。
Mojolicious::Lite


■パラメータの取得
get/postどちらもparamメソッドを使えば取得できます。
[getの場合]
shift->param("Query名");
[postの場合]
shift->param("Name属性名");

getの参考例
get '/get' => sub{
  my $self = shift;
  my $date = $self->param("date");
  $self->render_text("Date:" . $date);
};
http://localhost:3000/get?date=20121203
にアクセスすると
Date:20121203
と表示されます。

チェックボックスの値など複数の値が帰ってくる場合は
配列変数で受け取ればよいです。
また、引数を省略すると全てのパラメータ名が帰ってきます。


Mojolicious::Liteへ戻る

2012年9月13日木曜日

Mojolicious

■メモ。
その1 てっとり早く動かしてみる

その2 ルートについて


$self->app->log->debug()
$self->app->log->error()
$self->app->log->fatal()
$self->app->log->info()
$self->app->log->warn()

$self->app->render->paths

$self->helper() 

$self->req->param()

$self->res->code

$self->render() text,template

その1 てっとり早く動かしてみる

雰囲気を味わうためにヘルパースクリプトを実行してみます。
何も考えずに実行してみます。
$mojo generate lite_app hello.pl

以下のようなコードが生成されます。
#!/usr/bin/env perl                                                                                       
use Mojolicious::Lite;

# Documentation browser under "/perldoc"                                                                  
plugin 'PODRenderer';

get '/' => sub {
  my $self = shift;
  $self->render('index');
};

app->start;
__DATA__

@@ index.html.ep
% layout 'default';
% title 'Welcome';
Welcome to the Mojolicious real-time web framework!

@@ layouts/default.html.ep


  <%= title %>
  <%= content %>

これまた、何も考えずに以下を実行します
$morbo hello.pl

すると以下メッセージが表示されるので、localhostの3000ポートにアクセスしてみます。
[Wed Sep 12 23:45:49 2012] [info] Listening at "http://*:3000".
Server available at http://127.0.0.1:3000.

Welcome to the Mojolicious real-time web framework!
と表示されました。


ここまでの補足。
・ヘルパーコマンドについて
$mojo generate help
でmojo generateのコマンドの簡単な説明が表示されます

---------------------------------------------------------------------------
These generators are currently available:
app Generate Mojolicious application directory structure.
lite_app Generate Mojolicious::Lite application.
makefile Generate "Makefile.PL".
plugin Generate Mojolicious plugin directory structure.
---------------------------------------------------------------------------

Mojolicious::Liteのひな形を作りたかったので
$mojo generate lite_app アプリ名 としたわけですね。


・開発用webサーバ
$morbo アプリ名
で、開発用webサーバが起動します。
ファイルを書きなおしても再度立ち上げ直す必要はありません。
Ctrl + cで終了。


・use Mojolicious::Lite
use strict; use warings;が有効になる


・plugin 'PODRenderer'
ヘルパーコマンドのソースには、Mojoliciousのガイドページが閲覧できるようになっています。
http://localhost:3000/perldoc で見れます。

ひとまずここまで。
ルート、ビューについては後日メモ。

Mojolicious::Liteへ戻る

2012年4月9日月曜日

リファレンスのメモ

変数の前に\をつけることでその変数に対する参照(リファレンス)でやり取りが可能になる。
そして、参照情報から実際の値を取り出すには、各変数のファニー文字(スカラー⇒$,
配列⇒@, ハッシュ⇒%)をつけてあげれば元の変数のように扱うことができる。

サンプルコード
#!/usr/bin/perl                                                                         
use feature 'say';
use strict;
use warnings;
use utf8;
use File::Find;

binmode STDIN,  ":utf8";
binmode STDOUT, ":utf8";

#配列、ハッシュ                                                                         
my @array = ("a", "b", "c");
my %hash  = (
             guu   => "rock",
             cyoki => "scissors",
             paa   => "paper",
            );

#リファレンス                                                                           
my $ref_array = \@array;
my $ref_hash  = \%hash;

                                                                                   
#表示                                                                                   
for(my $i = 0; $i < @{$ref_array}; $i++){
  say "${$ref_array}[$i]";
}


for my $key (keys %{$ref_hash}){ 
  say "key: $key / value: ${$ref_hash}{$key}";
}
実行結果:
a
b
c
key: paa / value: paper
key: cyoki / value: scissors
key: guu / value: rock
変数の頭に\をつけることをリファレンスと呼びその逆の行為をデリファレンスと呼ぶ。
デリファレンスした後
配列の場合 ${$ref_array}[$i]
ハッシュの場合 ${$ref_hash}{$key}
とアクセスすることもできるが、アロー演算子による表記が用意されているので
以下のように書き換えることができる。

配列の場合   $ref_array->[$i]
ハッシュの場合 $ref_hash->{$key}
サブルーチンの場合も同様にアロー演算子による表記が可能である。
まとめ。
配列   リファレンス->[要素]
ハッシュ リファレンス->{キー}
関数   リファレンス->(引数)


上記の例では、配列とハッシュの変数に格納してからリファレンスを
扱っているが直接リファレンスを扱うこともできる。

配列の場合
(要素, 要素, 要素)から
[要素, 要素, 要素]に変えるだけ。

ハッシュの場合
(キー=>値, キー=>値)から
{キー=>値, キー=>値}に変えるだけ。

上記の例を書き直すとこうなる。
#!/usr/bin/perl                                                                         
use feature 'say';
use strict;
use warnings;
use utf8;
use File::Find;

binmode STDIN,  ":utf8";
binmode STDOUT, ":utf8";


#リファレンス                                                                           
my $ref_array = ["a", "b", "c"];
my $ref_hash  = {
                 guu   => "rock",
                 cyoki => "scissors",
                 paa   => "paper",
                };

                                                                                   
#表示                                                                                   
for(my $i = 0; $i < @{$ref_array}; $i++){
  say "${$ref_array}[$i]";
}


for my $key (keys %{$ref_hash}){ 
  say "key: $key / value: ${$ref_hash}{$key}";
}
簡単ですね! さて、今度は多次元配列を表現してみます。
#!/usr/bin/perl                                                                         
use feature 'say';
use strict;
use warnings;
use utf8;
use File::Find;

binmode STDIN,  ":utf8";
binmode STDOUT, ":utf8";


#リファレンス
my $ref_array = [
                 [1, 2],
                 [3, 4, 5],
                 [6, 7, 8, 9, 0],
                ];


for (my $x = 0; $x < @{$ref_array}; $x++){
  for (my $y = 0; $y < @{$ref_array->[$x]}; $y++){
    say $ref_array->[$x][$y];
  }
}

@{$ref_array} で [1, 2]と[3, 4, 5]と[6, 7, 8, 9, 0]の3要素であることを取得し
@{$ref_array->[$x]}で各要素
[1, 2] => 2要素
[3, 4, 5] => 3要素
[6, 7, 8, 9, 0] => 4要素
であることを取得しています。

2012年4月8日日曜日

File::Find

■再帰的にディレクトリを移動して、ファイル/ディレクトリ名を取得する

.
├── 1
│   └── 2
│       └── 3.txt
├── a
│   └── b.txt
└── Sample.pl

上記構成を例に使用してみる。
■"1"ディレクトリの構成を調べる
#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use File::Find;


find(\&wanted, '1');                                                                    

sub wanted{
  say "CurrentDirectory :", $File::Find::dir;
  say "Name             :", $_;
  say "FullPath         :", $File::Find::name;
  say "---";
}

実行結果:
CurrentDirectory :1
Name             :.
FullPath         :1
---
CurrentDirectory :1
Name             :2
FullPath         :1/2
---
CurrentDirectory :1/2
Name             :3.txt
FullPath         :1/2/3.txt
---



■複数のディレクトリを指定してみる
#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use File::Find;


find(\&wanted, qw/1 a/); #配列で指定

sub wanted{
  say "CurrentDirectory :", $File::Find::dir;
  say "Name             :", $_;
  say "FullPath         :", $File::Find::name;
  say "---";
}

実行結果:
CurrentDirectory :1
Name             :.
FullPath         :1
---
CurrentDirectory :1
Name             :2
FullPath         :1/2
---
CurrentDirectory :1/2
Name             :3.txt
FullPath         :1/2/3.txt
---
CurrentDirectory :a
Name             :.
FullPath         :a
---
CurrentDirectory :a
Name             :b.txt
FullPath         :a/b.txt
---



■一番下の階層からスタートする
#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use File::Find;


finddepth(\&wanted, '1');

sub wanted{
  say "CurrentDirectory :", $File::Find::dir;
  say "Name             :", $_;
  say "FullPath         :", $File::Find::name;
  say "---";
}

実行結果:
CurrentDirectory :1/2
Name             :3.txt
FullPath         :1/2/3.txt
---
CurrentDirectory :1
Name             :2
FullPath         :1/2
---
CurrentDirectory :1
Name             :.
FullPath         :1
---

FindBin

実行スクリプトのディレクトリを取得するモジュール

#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use FindBin;
                                                        
say $FindBin::Bin;

libモジュールのパス指定をする際に利用すると便利。
use lib "$FindBin::Bin/lib";

File::Path

■ディレクトリの作成
カレントディレクトリにfoo/bar/bazなディレクトリ階層を作成したい時

下記構成
├── foo
│   └── bar
│   └── baz

#!/usr/bin/perl
use strict;
use warnings;
use utf8;

mkdir foo
mkdir foo/bar
mkdir foo/bar/baz
のように上位ディレクトリから順に作成していくことになる。

File::Pathを使うと1行ですむ。
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use File::Path qw/make_path/;

make_path('foo/bar/baz'); #ver 2.06以降


■ディレクトリの削除
下記ディレクトリ構造でfooディレクトリを削除したい時
├── foo
│   ├── bar
│   │   ├── baz
│   │   │   └── sample.txt
│   │   └── sample.txt
│   └── sample.txt
最下層のディレクトリ内のファイルを削除⇒ディレクトリ削除の順で削除する必要がある。
File::Findeモジュールのfinddepth関数で最下層のディレクトリからアクセスして削除していく
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use File::Find;
use FindBin;

finddepth(\&deleteAll, 'foo');

sub deleteAll{
  #フルパスじゃないと削除できなかったのでスクリプトのパスを取得しておく
  my $BasePath = $FindBin::Bin . '/';
  if(-f $_){ unlink $BasePath . $File::Find::name || die $! };
  if(-d $_){ rmdir  $BasePath . $File::Find::name || die $! };                          
}


File::Pathを使うと1行ですむ。
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use File::Path qw/remove_tree/;

remove_tree('foo'); #ver 2.06以降


v2.00より前とv2.06より前とそれ以降でインターフェースが異なります。
perl -MFile::Path -le 'print "$File::Path::VERSION"'
等で、確認した上で利用する必要があります。

v2.06以降の場合
use File::Path qw(make_path remove_tree);

  make_path('foo/bar/baz', '/zug/zwang'); #複数作成したい場合コンマで区切る
  make_path('foo/bar/baz', '/zug/zwang', {
      verbose => 1,  #1を指定すると実行時コマンドを出力する
      mode => 0711, #アクセス権限を指定  デフォ:0777
  });

  remove_tree('foo/bar/baz', '/zug/zwang');
  remove_tree('foo/bar/baz', '/zug/zwang', {
      verbose => 1,
      error  => \my $err_list, #エラー情報
  });

ワンライナー

随時追加していく予定。

・eスイッチ
文字列をスクリプトとして解釈する
---
perl -e 'print "hello world¥n"'
---


・lスイッチ
行末に改行をつけてくれる。下の2コードは同じ結果となる
---
perl -e 'print "hello world¥n"'
perl -le 'print "hello world"'
---
改行を自動的につけてくれるといえばsay関数があるのでそれを使っても同じ結果となる。
ただし、Eスイッチになる。
---
perl -e 'print "hello world¥n"'
perl -le 'print "hello world"'
perl -E 'say "hello world"'
---


・Mスイッチ
モジュールを呼び出す
---
#FilePathモジュールのバージョンを出力
perl -MFile::Path -E 'say "$File::Path::VERSION"'
#LWP::Simpleをつかってwww.google.co.jpを取得
perl -MLWP::Simple -E 'say get shift' http://google.co.jp
---


配列からハッシュを作る

■ハッシュ
・2つの配列(キー用の配列,値用の配列)からハッシュを作る
⇒ハッシュのスライスを使う

#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use Encode;

my @k = qw/k1 k2 k3/;
my @v = qw/v1 v2 v3/;
my %h = ();
@h{@k} = @v; #ハッシュのスライス

for my $key (sort keys %h){
  say encode_utf8("key:". $key. " value:". $h{$key});
}
実行結果
key:k1 value:v1
key:k2 value:v2
key:k3 value:v3

上記では、空のハッシュに対し、ハッシュのスライスをおこなってみた。
今度は、値が入っているハッシュに対し、ハッシュのスライスを行い
配列データを配列に格納してみる。
#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use Encode;

my @k = qw/k1 k2 k3/;
my @v = qw/v1 v2 v3/;
my %h = ("k0" => "v0", "k1" => "dummy");
@h{@k} = @v; #ハッシュのスライス

for my $key (sort keys %h){
  say encode_utf8("key:". $key. " value:". $h{$key});
}

実行結果
key:k0 value:v0
key:k1 value:v1
key:k2 value:v2
key:k3 value:v3


・配列(一つ)からハッシュを作る。
(存在するかどうかを知るためにハッシュ化するだけで値は意味のある値を必要としないとする)
#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use Encode;

my @k = qw/k1 k2 k3/;
my %h = ();
@h{@k} = 1..@k; #ハッシュのスライス

for my $key (sort keys %h){
  say encode_utf8("key:". $key. " value:". $h{$key});
}

実行結果
key:k1 value:1
key:k2 value:2
key:k3 value:3


でも…map関数を使えばもっと綺麗に。
#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use Encode;

my @k = qw/k1 k2 k3/;
my %h = map{($_, 1)} @k;

for my $key (sort keys %h){
  say encode_utf8("key:". $key. " value:". $h{$key});
}

2012年3月11日日曜日

WebService::YahooJapan::WebMA

■Yahoo! 形態素解析APIを使ってみるメモ。
形態素解析APIを利用するにあたり、Yahooのアカウントと
AppIDを取得する必要があるので先に済ませておく。

1.Yahoo!のアカウントを取る。
https://login.yahoo.co.jp/config/login

2.どのページでもよいが、アプリケーションIDの登録をすませておく。
http://developer.yahoo.co.jp/webapi/jlp/ma/v1/parse.html

#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use WebService::YahooJapan::WebMA;
use utf8;
use Dumpvalue; my $d = Dumpvalue->new();
binmode STDOUT, ":utf8";

my $AppID = '上記で取得しておいたアプリケーションIDを記載する';
$WebService::YahooJapan::WebMA::APIBase = 
         'http://jlp.yahooapis.jp/MAService/V1/parse';

my $api    = WebService::YahooJapan::WebMA->new( appid => $ApiID);
my $result = $api->parse(sentence => '本日は晴天なり') or die $api->error; #解析したい文章を指定する

$d->dumpValue($result);

'ma_result' => HASH(0x7fa5bbb28ec8)
   'filtered_count' => 4
   'total_count' => 4
   'word_list' => ARRAY(0x7fa5bbb1ee98)
      0  HASH(0x7fa5bbb25838)
         'pos' => '名詞'
         'reading' => 'ほんじつ'
         'surface' => '本日'
      1  HASH(0x7fa5bbb25880)
         'pos' => '助詞'
         'reading' => 'は'
         'surface' => 'は'
      2  HASH(0x7fa5bbb25670)
         'pos' => '名詞'
         'reading' => 'せいてん'
         'surface' => '晴天'
      3  HASH(0x7fa5bbb24718)
         'pos' => '助動詞'
         'reading' => 'なり'
         'surface' => 'なり'
'xmlns' => 'urn:yahoo:jp:jlp'
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance'
'xsi:schemaLocation' => 'urn:yahoo:jp:jlp http://jlp.yahooapis.jp/MAService/V1/parseResponse.xsd'

2012年3月4日日曜日

perlの特殊変数のめも

気長にメモしていく予定。

変数内容
$$プロセスIDを返す
$,リストを出力時のセパレータ。デフォルトは空文字。
$.ファイルハンドルが読み込みを行った行番号が格納されている。ファイルの内容を1行ずつ読み込んでいる際に目的の行を見つけた際にそれが何行目か知りたい時などに利用
$0スクリプト実行時のパスを返す(絶対パスなら絶対パス。相対パスなら相対パス)
$]スクリプト実行した際のperlのバージョン
$|0以外を指定すると出力時のバッファーを行わなくなる。デフォルトは0

2012年3月3日土曜日

say関数

say関数を使いたい時どうすればいいのか。
というので、調べてみたら

use feature 'say';

だったり

use 5.10.0;

だったり

use feature ':5.10.0';

だったり

use 5.010;

いろいろあって違いがよくわからなかった。
で、featureプラグマの訳があったんで非常に理解しやすかった。
http://perldoc.jp/docs/modules/feature-1.11/feature.pod


つまり
use feature では、ピンポイントの機能追加を行い
use feature ':5.10.0'; では、追加機能が全て使えるようになる
use 5.10.0; は、上の別表記。
use 5.010; は、移植性の警告(?)を出さないための書き方ということなのね。

言ってしまえば、sayだけ使いたいんよ。
というのであるなら、追加機能すべて使える必要はなくて
use feature 'say';

で、OKってことになるのね。
で、おk?

Time:Piece

■日時の取得
#!/usr/bin/perl
use feature 'say';
use strict;
use warnings;
use utf8;
use Time::Piece;
binmode STDOUT, ":utf8";


my $t = localtime;

### 日時の表示
say $t;              #Sat Mar  3 14:53:37 2012
say $t->datetime;    #2012-03-03T14:53:37
say $t->datetime(
         date => '/', 
         T    => ' ',
         time => '-'
                );   #2012/03/03 14-53-37
say $t->strftime('%Y*%m*%d  %H@%M@%S');
                     #2012*03*03  14@53@37  注:UTF8フラグが落ちてます


### 年月日の表示
say $t->ymd;      #2012-03-03
say $t->ymd("/"); #2012/03/03
say $t->ymd("");  #20120303

say $t->year;     #2012
say $t->mon;      #3
say $t->mday;     #3


### 曜日の表示
say $t->wday;      #7
say $t->wdayname;  #Sat
say $t->wdayname(
   qw/日 月 火 水 木 金 土/
                ); #土

#wdaynameを何度も使うのなら
#デフォルトの曜日を変更してしまう
$t->day_list(qw/日 月 火 水 木 金 土/);
say $t->wdayname;  #土


### 時分秒の表示
say $t->hms;      #14:53:37
say $t->hms("-"); #14-53-37
say $t->hms("");  #145337

say $t->hour;     #14
say $t->min;      #53
say $t->sec;      #37


### 他
#閏年判定
say $t->is_leap_year ? "閏年" : "Not閏年"; #閏年

#最終日
say $t->month_last_day; #31


### 任意の時間を設定
$t = localtime->strptime('2000-01-01 12:00:00', '%Y-%m-%d %H:%M:%S');
say $t->datetime; #2000-01-01T12:00:00


### 時間の比較
my $BaseDate = localtime->strptime('20001122', '%Y%m%d');
my $TestDate = localtime->strptime('20111122', '%Y%m%d');
say $BaseDate < $TestDate ? "もうすぎたよ" : "まだ過ぎてないよ";
                  #もうすぎだよ

### 時間の加減・減算(秒単位で返ってくる)
my $date1 = localtime->strptime('20120101', '%Y%m%d');
my $date2 = localtime->strptime('20130101', '%Y%m%d');
my $days  = ($date2 - $date1) / (24 * 60 * 60);
say $days;        #366

ただ、一つ注意。
strftimeメソッドは、utf8フラグを落とすことに注意。

#!/usr/bin/perl
use strict;
use warnings;
use Time::Piece;
use utf8;
use Devel::Peek;

my $t = localtime;
Dump $t->wdayname(qw/日 月 火 水 木 金 土/);
Dump $t->strftime('%Y年%m月%d日');

実行結果
SV = PV(0x7fd56b801170) at 0x7fd56b842708
  REFCNT = 1
  FLAGS = (TEMP,POK,pPOK,UTF8)
  PV = 0x105d08220 "\346\227\245"\0 [UTF8 "\x{65e5}"]
  CUR = 3
  LEN = 16
SV = PV(0x7fd56b801190) at 0x7fd56b842708
  REFCNT = 1
  FLAGS = (TEMP,POK,pPOK)
  PV = 0x105d06df0 "2012\345\271\26403\346\234\21004\346\227\245"\0
  CUR = 17
  LEN = 32

wdaynameメソッドの方には、UTF8フラグが残っているけど
strftimeメソッドの方には、UTF8フラグがないですよね。

上の例のように
binmode STDOUT, ":utf8";
して、標準出力する際にフラグを落とすようにしている場合
文字化けしちゃいます。

美しくないけど
binmode STDOUT, ":utf8"; するなら
use Encode;
say decode_utf8($t->strftimeメソッド);

のように内部にあるデータには徹底してフラグをつけるか

binmode STDOUT, ":utf8"; を使わないなら
use Encode;
say encode_utf8($t->strftime以外のメソッド);
say $t->strftimeメソッド;

とするしかないのかな…。


おまけ。
1日後、1ヶ月後を簡単に求めるのに
Time::Secondsを使う方法があります。

#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use feature 'say';
use Time::Piece;
use Time::Seconds;

my $t = localtime;
say $t->ymd; #2012-03-03

$t += ONE_MONTH;
say $t->ymd; #2012-04-03

$t += ONE_MONTH;
say $t->ymd; #2012-05-03

$t += ONE_MONTH * 2;
say $t->ymd; #2012-07-03

Time::Secondsを利用すると以下の定数が使えるようになります。
ONE_DAY
ONE_WEEK
ONE_HOUR
ONE_MINUTE
ONE_MONTH
ONE_YEAR
ONE_FINANCIAL_MONTH
LEAP_YEAR
NON_LEAP_YEAR

後は、掛け算して加減算するなりすればよいですね。