DateTime::Locale 有一个非常全面的针对不同地区和国家的日期和时间格式列表。我想在给客户的电子邮件中使用它,具体取决于客户来自哪个国家/地区。
不幸的是,从文档中很难理解如何在中等或长期的情况下实际使用这些功能。例如,DateTime::Locale::de_DE在文档中列出了这些日期格式(摘录):
Long 2008-02-05T18:30:30 = 5. Februar 2008 1995-12-22T09:05:02 = 22. Dezember 1995 -0010-09-15T04:44:23 = 15. September -10 Medium 2008-02-05T18:30:30 = 05.02.2008 1995-12-22T09:05:02 = 22.12.1995 -0010-09-15T04:44:23 = 15.09.-010
这太棒了。根据 DateTime::Locale::Base,语言环境对象中有方法可以获取这些格式:
$locale->date_format_long()
和 $locale->date_format_medium()
。
经过一番谷歌搜索后,我找到了Sinan Ünür 的博客,他在其中展示了这段代码(摘录):
for my $locale ( qw(ar da de en_GB es fr ru tr) ) { $dt->set_locale( $locale ); print_date( $dt ); } sub print_date { my ($dt) = @_; my $locale = $dt->locale; printf( "In %s: %s\n", $locale->name, $dt->format_cldr($locale->date_format_full) ); }
因此这些方法产生的格式是 cldr 格式。凉爽的。但思南所展示的内容看起来很乏味。简而言之,就是:
for (qw( ar da de en_GB es fr ru tr )) {
my $dt2 = DateTime->now( locale => $_ );
printf "%s: %s\n", $_, $dt2->format_cldr($dt2->locale->date_format_long);
}
为了缩短时间,我当然可以这样做:
package DateTime;
sub stringify_long {
return $_[0]->format_cldr($_[0]->locale->date_format_long);
}
package Main;
use strict; use warnings;
use DateTime;
my $dt = DateTime->now( locale => 'de_DE' );
print $dt->stringify_long;
但我不想那样做。所以我的问题是:有没有一种方法可以使用我缺少的内置方法根据其语言环境中的这些格式之一来字符串化 DateTime 对象?
我不确定你对 Sinan Ünür 的方法有什么反对意见,所以我不知道这是否会吸引你,但你可以指定一个格式化程序对象来控制
DateTime
对象的字符串化:
use DateTime;
use DateTime::Format::CLDR;
use DateTime::Locale;
my $locale = DateTime::Locale->load('de_DE');
my $formatter = DateTime::Format::CLDR->new(
pattern => $locale->date_format_long,
locale => $locale
);
my $dt = DateTime->now( locale => $locale, formatter => $formatter );
print $dt;
或
use DateTime;
use DateTime::Format::CLDR;
use DateTime::Locale;
my $locale = DateTime::Locale->load('de_DE');
my $dt = DateTime->now( locale => $locale );
my $formatter = DateTime::Format::CLDR->new(
pattern => $locale->date_format_long,
locale => $locale
);
$dt->set_formatter($formatter);
print $dt;
这种方法的好处是,一旦设置了格式化程序,打印日期就很容易了。
OP已经过去11年了,但我非常努力,发布了一个非常精细的模块DateTime::Format::Intl,它解决了OP表达的需求,即本地化日期时间,例如:
use DateTime;
use DateTime::Format::Intl;
my $dt = DateTime->now;
my $fmt = DateTime::Format::Intl->new(
# You can use ja-JP (Unicode / web-style) or ja_JP (system-style), it does not matter.
'ja_JP', {
localeMatcher => 'best fit',
# The only one supported. You can use 'gregory' or 'gregorian' indifferently
calendar => 'gregorian',
# see getNumberingSystems() in Locale::Intl for the supported number systems
numberingSystem => 'latn',
formatMatcher => 'best fit',
dateStyle => 'long',
timeStyle => 'long',
},
) || die( DateTime::Format::Intl->error );
say $fmt->format( $dt );
此模块反映了其 JavaScript 等效项
Intl.DateTimeFormat
的 API。
而且,这个 Perl 模块使用了另一个: DateTime::Locale::FromCLDR 我也创建了它,它依赖于一个非常全面的 Unicode CLDR 数据 SQLite 数据库(公共区域设置数据存储库),并提供与
DateTime::Locale
相同的方法(实际上是DateTime::Locale::FromData
)等等。您可以使用 Locale::Unicode::Data 查看我创建的另一个依赖于这些 CLDR 数据的模块
因此,通过在上面提供更强大和更简单的层,这有助于本地化项目中的日期时间
DateTime::Locale::FromCLDR
,尽管如果您想要或需要直接访问它们,您仍然可以访问所有这些方法。