OracleのNLS_DATE_FORMAT解析プラグイン

と、言いつつ中途半端なプラグインです。

まず、
Class::DBI::Plugin::DateFormat::Oracleから


package Class::DBI::Plugin::DateFormat::Oracle;
use strict;
use warnings;
use Carp;
use vars '$VERSION';
$VERSION = '0.01';
sub import {
my $class = shift;
my $pkg = caller(0);
no strict 'refs';
*{"$pkg\::set_nls_date_format"} = sub {
my $self = shift;
my $format = shift;
eval {
$self->db_Main->do(qq[ALTER SESSION SET NLS_DATE_FORMAT = '$format']);
};
$self->_croak("ALTER SESSION ERROR ".$@ ) if $@;
};
*{"$pkg\::get_nls_date_format"} = sub {
my $self = shift;
$self->set_sql(nls_date_format => q[SELECT VALUE FROM v$nls_parameters WHERE PARAMETER = 'NLS_DATE_FORMAT']);
eval {
$self->{__NLS_DATE_FORMAT} = $self->search_nls_date_format->first->{value};
};
$self->_croak("SELECT NLS_DATE_FORMAT ERROR ".$@ ) if $@;
}
}
1;

このプラグインでは
set_nls_date_formatメソッドと
get_nls_date_formatメソッドを提供します。

次にClass::DBI::Plugin::TimePiece::Oracle


package Class::DBI::Plugin::TimePiece::Oracle;
use strict;
use warnings;
use Carp;
use Class::DBI::Plugin::DateFormat::Oracle;
use vars '$VERSION';
$VERSION = '0.01';
# This module supports the following %FORMAT.
my %FORMAT = (
'YYYY' => '%Y',
'YY' => '%y',
'RRRR' => '%Y',
'RR' => '%y',
'MM' => '%m',
'MON' => '%b',
'MONTH' => '%B',
'DD' => '%d',
'HH' => '%I',
'HH24' => '%H',
'MI' => '%M',
'SS' => '%S',
);
# This module supports the following $SEPARATOR.
my $SEPARATOR = q[\s\-\/\,\;\:];
sub import {
my $class = shift;
my $pkg = caller(0);
no strict 'refs';
*{"$pkg\::has_a_auto_timepiece"} = sub {
my $self = shift;
my $colum = shift;
$self->get_date_format;
$self->has_a(
$colum => 'Time::Piece',
inflate => sub { Time::Piece->strptime(shift , $self->{__DATE_FORMAT} ) },
deflate => sub { shift->strftime($self->{__DATE_FORMAT}) },
);
};
*{"$pkg\::has_a_atp"} = *{"$pkg\::has_a_auto_timepiece"};
*{"$pkg\::get_date_format"} = sub {
my $self = shift;
$self->_get_nls_date_format;
};
*{"$pkg\::_get_nls_date_format"} = sub {
my $self = shift;
if ( ! defined $self->{__NLS_DATE_FORMAT} ) {
$self->get_nls_date_format;
}
my $chk_target = $self->{__NLS_DATE_FORMAT};
$self->{__DATE_FORMAT} = $self->{__NLS_DATE_FORMAT};
for my $key ( reverse sort keys %FORMAT ) {
$self->{__DATE_FORMAT} =~ s/${key}/$FORMAT{$key}/;
$chk_target =~ s/${key}//;
}
$self->_croak("FORMAT PARSE ERROR!") if ( $chk_target eq q[] && $chk_target =~ /[^${SEPARATOR}]/ );
};
goto &Class::DBI::Plugin::DateFormat::Oracle::import;
}
1;

このプラグインOracleのDATE型のカラムにマッピングさせます。

利用者はClass::DBI::Plugin::TimePiece::OracleClass::DBIを継承しているクラスにuseさせて、


__PACKAGE__->has_a_atp( 'INSERT_DATE' );
__PACKAGE__->has_a_auto_timepiece( 'UPDATE_DATE' );

こんな感じで使うだけです。
has_a_atpメソッドはhas_a_auto_timepieceへのエイリアスです。
has_a_atpメソッドでは内部でOracleのNLS DATE FORMATを取得して、
TIME::Pieceに渡せる形のフォーマットを作成しています。

なにが中途半端かというと、Oracleの全てのNLS DATE FORMATには対応してません。
一般的なものだけとりあえず対応してます。

次に、Class::DBI::Plugin::TimePieceというプラグインも作ってるのですが、
Class::DBI::Plugin::TimePieceで提供するメソッド(クロージャ)を再利用したいのですが、
スキル不足のせいでできませんでした^^;
Class::DBI::Plugin::DateFormat::Oracleはなんとか再利用できたのですが、、、

ちなみにClass::DBI::Plugin::TimePieceはこんなのです。


package Class::DBI::Plugin::TimePiece;
use strict;
use warnings;
use Carp;
use vars '$VERSION';
$VERSION = '0.01';
sub import {
my $class = shift;
my $pkg = caller(0);
no strict 'refs';
*{"$pkg\::has_a_timepiece"} = sub {
my $self = shift;
my $colum = shift;
my $format = shift;
if ( $format ) {
$self->has_a(
$colum => 'Time::Piece',
inflate => sub { Time::Piece->strptime(shift , $format ) },
deflate => sub { shift->strftime($format) },
);
}
else {
$self->has_a(
$colum => 'Time::Piece',
inflate => sub { Time::Piece->strptime(shift , $self->{__DATE_FORMAT} ) },
deflate => sub { shift->strftime($self->{__DATE_FORMAT}) },
);
}
};
*{"$pkg\::has_a_tp"} = *{"$pkg\::has_a_timepiece"};
}
1;

これは一応、汎用的に使えるようにしてます。
これで結構使えるようになったとおもいませんか?
かぜぶろさんの期待にこたえられたかなぁ。。。と、書いてみるテストw