Data::Currency - Container class for currency conversion/formatting


Data-Currency documentation Contained in the Data-Currency distribution.

Index


Code Index:

NAME

Top

Data::Currency - Container class for currency conversion/formatting

SYNOPSIS

Top

    use Data::Currency;

    my $price = Data::Currency->new(1.2. 'USD');
    print $price;            # 1.20 USD
    print $price->code;      # USD
    print $price->format;    # FMT_SYMBOL
    print $price->as_string; # 1.20 USD
    print $price->as_string('FMT_SYMBOL'); # $1.20

    print 'Your price in Canadian Dollars is: ';
    print $price->convert('CAD')->value;

DESCRIPTION

Top

The Data::Currency module provides basic currency formatting and conversion:

    my $price = 1.23;
    my $currency = Data::Currency->new($price);

    print $currency->convert('CAD')->as_string;

Each Data::Currency object will stringify to the original value except in string context, where it stringifies to the format specified in format.

CONSTRUCTOR

Top

new

Arguments: $price [, $code, $format] || \%options

To create a new Data::Currency object, simply call new and pass in the price to be formatted:

    my $currency = Data::Currency->new(10.23);

    my $currency = Data::Currency->new({
        value  => 1.23,
        code   => 'CAD',
        format => 'FMT_SYMBOL',
        converter_class => 'MyConverterClass'
    });

You can also pass in the default currency code and/or currency format to be used for each instance. If no code or format are supplied, future calls to as_string and convert will use the default format and code values.

You can set the defaults by calling the code/format values as class methods:

    Data::Currency->code('USD');
    Data::Currency->format('FMT_COMMON');

    my $currency = Data::Currency->new(1.23);
    print $currency->as_string; # $1.23

    my $currency = Data::Currency->new(1.23, 'CAD', 'FMT_STANDARD');
    print $currency->as_string; # 1.23 CAD

The following defaults are set when Data::Currency is loaded:

    value:  0
    code:   USD
    format: FMT_COMMON

METHODS

Top

code

Arguments: $code

Gets/sets the three letter currency code for the current currency object. code dies loudly if code isn't a valid currency code.

convert

Arguments: $code

Returns a new Data::Currency object containing the converted value.

If no code is specified, the current value of code will be used. If the currency you are converting to is the same as the current objects currency code, convert will just return itself.

Remember, convert returns another currency object, so you can chain away:

    my $price = Data::Currency->new(1.25, 'USD');
    print $price->convert('CAD')->as_string;

convert dies if code isn't valid currency code or isn't defined.

converter_class

Arguments: $converter_class

Gets/sets the converter class to be used when converting currency numbers.

    Data::Currency->converter_class('MyCurrencyConverter');

The converter class can be any class that supports the following method signature:

    sub convert {
        my ($self, $price, $from, $to) = @_;

        return $converted_price;
    };

This method dies if the specified class can not be loaded.

format

Arguments: $options

Gets/sets the format to be used when as_string is called. See Locale::Currency::Format for the available formatting options.

name

Returns the currency name for the current objects currency code. If no currency code is set the method will die.

stringify

Sames as as_string.

as_string

Returns the current objects value as a formatted currency string.

value

Returns the original price value given to new.

get_component_class

Arguments: $name

Gets the current class for the specified component name.

    my $class = $self->get_component_class('converter_class');

There is no good reason to use this. Use the specific class accessors instead.

set_component_class

Arguments: $name, $value

Sets the current class for the specified component name.

    $self->set_component_class('converter_class', 'MyCurrencyConverter');

This method will croak if the specified class can not be loaded. There is no good reason to use this. Use the specific class accessors instead.

SEE ALSO

Top

Locale::Currency, Locale::Currency::Format, Finance::Currency::Convert::WebserviceX

AUTHOR

Top

    Christopher H. Laco
    CPAN ID: CLACO
    claco@chrislaco.com
    http://today.icantfocus.com/blog/



Data-Currency documentation Contained in the Data-Currency distribution.

# $Id: Currency.pm 1830 2007-05-05 01:34:36Z claco $
package Data::Currency;
use strict;
use warnings;
use overload
    '0+'     => sub {shift->value},
    'bool'   => sub {shift->value},
    '""'     => sub {shift->stringify},
    fallback => 1;
use vars qw/$VERSION/;

$VERSION = '0.04002';

BEGIN {
    use base qw/Class::Accessor::Grouped/;
    use Locale::Currency ();
    use Locale::Currency::Format;
    use Scalar::Util ();
    use Class::Inspector ();
    use Carp;

    __PACKAGE__->mk_group_accessors('inherited', qw/
        format value converter converter_class
    /);
    __PACKAGE__->mk_group_accessors('component_class', qw/converter_class/);
};

__PACKAGE__->converter_class('Finance::Currency::Convert::WebserviceX');
__PACKAGE__->value(0);
__PACKAGE__->code('USD');
__PACKAGE__->format('FMT_COMMON');

my %codes;

sub new {
    my ($class, $value, $code, $format) = @_;
    my $self = bless {}, $class;

    if (ref $value eq 'HASH') {
        foreach my $key (keys %{$value}) {
            $self->$key($value->{$key}) if defined $value->{$key};
        };
    } else {
        if (defined $value){
            $self->value($value)
        };
        if ($code) {
            $self->code($code)
        };
        if ($format) {
            $self->format($format)
        };
    };

    return $self;
};

sub code {
    my $self = shift;

    if (scalar @_) {
        my $code = shift;

        croak "Invalid currency code: $code"
            unless _is_currency_code($code);

        $self->set_inherited('code', $code);
    };

    return $self->get_inherited('code');
};

sub convert {
    my ($self, $to) = @_;
    my $class = Scalar::Util::blessed($self);
    my $from = $self->code;

    $to ||= '';
    if (uc($from) eq uc($to)) {
        return $self;
    };

    croak 'Invalid currency code source: ' . ($from || 'undef')
        unless _is_currency_code($from);

    croak 'Invalid currency code target: ' . ($to || 'undef')
        unless _is_currency_code($to);

    if (!$self->converter) {
        $self->converter($self->converter_class->new)
    };

    return $class->new(
        $self->converter->convert($self->value, $from, $to) || 0,
        $to,
        $self->format
    );
};

sub name {
    my $self = shift;
    my $name = Locale::Currency::code2currency($self->code);

    ## Fix for older Locale::Currency w/mispelled Candian
    $name =~ s/Candian/Canadian/;

    return $name;
};

*as_string = \&stringify;

sub stringify {
    my $self = shift;
    my $format = shift || $self->format;
    my $code = $self->code;
    my $value = $self->value;

    if (!$format) {
        $format = 'FMT_COMMON';
    };

    ## funky eval to get string versions of constants back into the values
    eval '$format = Locale::Currency::Format::' .  $format;

    croak 'Invalid currency code:  ' . ($code || 'undef')
        unless _is_currency_code($code);

    return _to_utf8(
        Locale::Currency::Format::currency_format($code, $value, $format)
    );
};

sub _is_currency_code {
    my $value = defined $_[0] ? uc(shift) : '';

    return unless ($value =~ /^[A-Z]{3}$/);

    if (! keys %codes) {
        %codes = map {uc($_) => uc($_)} Locale::Currency::all_currency_codes();
    };
    return exists $codes{$value};
};

sub _to_utf8 {
    my $value = shift;

    if ($] >= 5.008) {
        require utf8;
        utf8::upgrade($value);
    };

    return $value;
};

sub get_component_class {
    my ($self, $field) = @_;

    return $self->get_inherited($field);
};

sub set_component_class {
    my ($self, $field, $value) = @_;

    if ($value) {
        if (!Class::Inspector->loaded($value)) {
            eval "use $value";

            croak "The $field $value could not be loaded: $@" if $@;
        };
    };

    $self->set_inherited($field, $value);

    return;
};

1;
__END__