SweetPotato::Plagger このページをアンテナに追加 RSSフィード

2008-01-05

[] DateTime::Format::Relative 05:38  DateTime::Format::Relative - SweetPotato::Plagger を含むブックマーク はてなブックマーク -  DateTime::Format::Relative - SweetPotato::Plagger  DateTime::Format::Relative - SweetPotato::Plagger のブックマークコメント

現在の日時からの相対的な日時,例えば「今日」「明後日」「先月」「来年」などを取得するためのモジュール。

ただし「明後日」の場合には,単純に現在時刻に2日加算するのではなく,明後日の0時を返す。他の場合も同様に,まず指定された単位以下をtruncateした後に日時の加減算を行う。例えば「2008年1月5日 5時24分43秒」の場合:

  • 今日: 2008年1月5日 0時0分0秒
  • 明後日: 2008年1月6日 0時0分0秒
  • 先月: 2007年12月1日 0時0分0秒
  • 来年: 2009年1月1日 0時0分0秒

となる。

フォーマットは「tomorrow」「+2 days」「1 month before」「next year」など。

経緯

Yahoo!Pipesで日時の指定に「today」とか「+1 day」とかできるのを知ってムラムラしたので書いた。これまでYAMLに絶対的な日時を指定しなければならなかったSubscriptionやCustomFeedも,このモジュールがあれば定期実行しやすい日付指定ができるようになるはず。

DateTime/Format/Relative.pm

# author: SweetPotato
package DateTime::Format::Relative;
use strict;
use warnings;

our $VERSION = '0.01';

use DateTime;

our %op = (
    '+'        => 'add',
    '-'        => 'subtract',
    'after'    => 'add',
    'later'    => 'add',
    'before'   => 'subtract',
    'ago'      => 'subtract',
    'next'     => 'add',
    'this'     => 'add', # don't care
    'prev'     => 'subtract',
    'previous' => 'subtract',
);

our $units = join '|', qw( day week month year hour minute second );

sub parse_datetime {
    my ($self, $str, %opt) = @_;
    my ($op, $diff, $unit);

    $_ = lc($str);
    s/^\s*|\s*$//g;

    # +2 day(s)
    if (/^(\+|-)\s*(\d+)\s+($units)s?$/) {
        ($op, $diff, $unit) = ($op{$1}, $2, $3);
    }
    # 2 day(s) ago
    elsif (/^(\d+)\s+($units)s?\s+(after|later|before|ago)$/) {
        ($op, $diff, $unit) = ($op{$3}, $1, $2);
    }
    # next month
    elsif (/^(next|this|prev|previous)\s+($units)$/) {
        ($op, $diff, $unit) = ($op{$1}, $1 eq 'this' ? 0 : 1, $2);
    }
    elsif ($_ eq 'today') {
        ($op, $diff, $unit) = ('add', 0, 'day');
    }
    elsif ($_ eq 'yesterday') {
        ($op, $diff, $unit) = ('subtract', 1, 'day');
    }
    elsif ($_ eq 'tomorrow') {
        ($op, $diff, $unit) = ('add', 1, 'day');
    }
    else {
        die "parse error: $str";
    }

    DateTime->now(%opt)->truncate(to => $unit)->$op("${unit}s" => $diff);
}

1;
トラックバック - http://plagger.g.hatena.ne.jp/SweetPotato/20080105