Reputation: 434
I want yesterdays date in perl in a specific format.
My Script:
use DateTime qw( );
use Date::Parse;
use Date::Language;
my $lang = Date::Language->new('German');
my $yday_date =
DateTime
->now( time_zone => 'local' )
->set_time_zone('floating')
->truncate( to => 'day' )
->subtract( days => 1 )
->strftime('%b%d');
print $lang ->time2str($yday_date)
What I get:
Dec08
What I need
Dez08
Does anyone know what the issue is? Any answer is appreciated!
Upvotes: 2
Views: 194
Reputation: 6840
You're calling Date::Language's time2str
with a literal string, not with a format string plus a time in second since 1970.
But you don't need Date::Language at all, DateTime can handle localization by itself.
Try this:
use strict;
use warnings;
use DateTime;
my $yday_date =
DateTime
->now( time_zone => 'local', locale => 'de' )
->set_time_zone('floating')
->truncate( to => 'day' )
->subtract( days => 1 )
->strftime('%b%d');
print $yday_date;
Edit: if you need a string like Dez08
instead of Dez.08
, I wouldn't add another module to the mix, but just solve it by removing the .
. Something like:
$yday_date =~ s/\.//;
Upvotes: 6
Reputation: 54333
This isn't what I would do to solve this, but it does answer how to use the DateTime::Locale module linked in OP's comment on mscha's answer.
DateTime::Locale::de_DE is one of the packages that provides the data for the formatter to format the date into a locale. It has different methods that provide that data. The one you have linked to in particular (Abbreviated (stand-alone) ) is used when a certain component of the date is used on its own, rather than in a form. There's a second block called Abbreviated (format) that has the dots.
These are used by methods on the DateTime::Locale::* objects of similar names. We want month_stand_alone_abbreviated
, but when called, it returns a list of month names.
Because the one you want to use is not to be used in an actual format string, which is what strftime
would do, we can do it ourselves. You can implement your own DateTime::Format that does exactly what you need, for this very specific case.
Disclaimer: I don't know if this is the right approach, and it's probably incomplete and will not work in any but this very specific use-case. It also won't parse incoming dates properly. I didn't bother looking up how that works. It needed to have a parser to work, so I wrote one that is probably wrong.
package DateTime::Format::GermanOhnePunkt;
use DateTime::Format::Builder (
parsers => {
parse_date => [ {
regex => qr/^(...)(..)$/,
params => [qw(month day)]
}
]});
sub format_datetime {
my ($self, $dt) = @_;
my @months = $dt->locale->month_stand_alone_abbreviated;
return sprintf '%s%02d', $months[0][$dt->month - 1], $dt->day;
}
All this does is fetch the DateTime::Locale out, get the list of months, and then return the string you wanted. It's very naive, but it works.
Use it like this:
my $yday_date =
DateTime
->now(
time_zone => 'local',
locale => 'de_DE',
formatter => DateTime::Format::GermanOhnePunkt->new,
)
->set_time_zone('floating')
->truncate( to => 'day' )
->subtract( days => 1 );
print $yday_date;
This will output Dez08
today at the time of writing.
Also see the DateTime::Format::Builder tutorial.
Upvotes: 5
Reputation: 117318
You should pass the time
to the language object together with the formatting string.
Example:
use DateTime qw( );
use Date::Parse;
use Date::Language;
my $lang = Date::Language->new('German');
my $yday_date =
DateTime
->now( time_zone => 'local' )
->set_time_zone('floating')
->truncate( to => 'day' )
->subtract( days => 1 )
->epoch;
print $lang->time2str('%b%d', $yday_date) . "\n";
Upvotes: 5