The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

DateTime::Locale::FromCLDR - DateTime Localised Data from Unicode CLDR

SYNOPSIS

    use DateTime::Locale::FromCLDR;
    my $locale = DateTime::Locale::FromCLDR->new( 'ja-Kana-JP' ) ||
        die( DateTime::Locale::FromCLDR->error );
    my $locale = DateTime::Locale::FromCLDR->new( 'ja-Kana-JP', calendar => 'japanese' ) ||
        die( DateTime::Locale::FromCLDR->error );
    my $array = $locale->am_pm_abbreviated;
    my $array = $locale->available_formats;
    $locale->calendar( 'hebrew' );
    my $str = $locale->calendar;
    # a Locale::Unicode object that stringifies to the initial locale value (ja-Kana-JP)
    my $obj = $locale->code;
    my $str = $locale->date_at_time_format_full;
    my $str = $locale->date_at_time_format_long;
    my $str = $locale->date_at_time_format_medium;
    my $str = $locale->date_at_time_format_short;
    my $str = $locale->date_format_default;
    my $str = $locale->date_format_full;
    my $str = $locale->date_format_long;
    my $str = $locale->date_format_medium;
    my $str = $locale->date_format_short;
    my $str = $locale->date_formats;
    my $str = $locale->datetime_format;
    my $str = $locale->datetime_format_default;
    my $str = $locale->datetime_format_full;
    my $str = $locale->datetime_format_long;
    my $str = $locale->datetime_format_medium;
    my $str = $locale->datetime_format_short;
    my $str = $locale->day_format_abbreviated;
    my $str = $locale->day_format_narrow;
    my $str = $locale->day_format_short;
    my $str = $locale->day_format_wide;
    my $str = $locale->day_period_format_abbreviated( $datetime_object );
    my $str = $locale->day_period_format_narrow( $datetime_object );
    my $str = $locale->day_period_format_wide( $datetime_object );
    my $str = $locale->day_period_stand_alone_abbreviated( $datetime_object );
    my $str = $locale->day_period_stand_alone_narrow( $datetime_object );
    my $str = $locale->day_period_stand_alone_wide( $datetime_object );
    my $hashref = $locale->day_periods;
    my $str = $locale->day_stand_alone_abbreviated;
    my $str = $locale->day_stand_alone_narrow;
    my $str = $locale->day_stand_alone_short;
    my $str = $locale->day_stand_alone_wide;
    my $str = $locale->default_date_format_length;
    my $str = $locale->default_time_format_length;
    my $str = $locale->era_abbreviated;
    my $str = $locale->era_narrow;
    my $str = $locale->era_wide;
    my $str = $locale->first_day_of_week;
    my $str = $locale->format_for( 'yMEd' );
    # Alias for method 'code'
    my $obj = $locale->id;
    my $array = $locale->interval_format( GyMEd => 'd' );
    my $hashref = $locale->interval_formats;
    my $greatest_diff = $locale->interval_greatest_diff( $datetime_object_1, $datetime_object_2 );
    my $str = $locale->language;
    my $str = $locale->language_code;
    # Alias for method 'language_code'
    my $str = $locale->language_id;
    # Locale::Unicode object
    my $obj = $locale->locale;
    # Equivalent to $locale->locale->as_string
    my $str = $locale->locale_as_string;
    # As per standard, it falls back to 'wide' format if it is not available
    my $str = $locale->month_format_abbreviated;
    my $str = $locale->month_format_narrow;
    my $str = $locale->month_format_wide;
    my $str = $locale->month_stand_alone_abbreviated;
    my $str = $locale->month_stand_alone_narrow;
    my $str = $locale->month_stand_alone_wide;
    # Language name in English. Here: Japanese
    my $str = $locale->name;
    # Alias for the method 'native_name'
    my $str = $locale->native_language;
    # Language name in the locale's original language. Here: 日本語
    my $str = $locale->native_name;
    # The local's script name in the locale's original language. Here: カタカナ
    my $str = $locale->native_script;
    # The local's territory name in the locale's original language. Here: 日本
    my $str = $locale->native_territory;
    # The local's variant name in the locale's original language. Here: undef since there is none
    my $str = $locale->native_variant;
    my $str = $locale->native_variants;
    # Returns 1 or 0
    my $bool = $locale->prefers_24_hour_time;
    my $str = $locale->quarter_format_abbreviated;
    my $str = $locale->quarter_format_narrow;
    my $str = $locale->quarter_format_wide;
    my $str = $locale->quarter_stand_alone_abbreviated;
    my $str = $locale->quarter_stand_alone_narrow;
    my $str = $locale->quarter_stand_alone_wide;
    # The locale's script name in English. Here: Katakana
    my $str = $locale->script;
    # The locale's script ID, if any. Here: Kana
    my $str = $locale->script_code;
    # Alias for method 'script_code'
    my $str = $locale->script_id;
    # The locale's territory name in English. Here: Japan
    my $str = $locale->territory;
    # The locale's territory ID, if any. Here: JP
    my $str = $locale->territory_code;
    # Alias for method 'territory_code'
    my $str = $locale->territory_id;
    my $str = $locale->time_format_default;
    my $str = $locale->time_format_full;
    my $str = $locale->time_format_long;
    my $str = $locale->time_format_medium;
    my $str = $locale->time_format_short;
    # Time patterns for 'full', 'long', 'medium', and 'short' formats
    my $array = $locale->time_formats;
    # The locale's variant name, if any, in English. Here undef, because there is none
    my $str = $locale->variant;
    # The locale's variant ID, if any. Here undef, since there is none
    my $str = $locale->variant_code;
    # Alias for method 'variant_code'
    my $str = $locale->variant_id;
    my $array = $locale->variants;
    # The CLDR data version. For example: 45.0
    my $str = $locale->version;

    # To get DateTime to use DateTime::Locale::FromCLDR for the locale data
    my $dt = DateTime->now(
        locale => DateTime::Locale::FromCLDR->new( 'en' ),
    );

VERSION

    v0.1.0

DESCRIPTION

This is a powerful replacement for DateTime::Locale and DateTime::Locale::FromData that use static data from over 1,000 pre-generated modules, whereas DateTime::Locale::FromCLDR builds a locale object to access its Unicode CLDR (Common Locale Data Repository) data from SQLite data made available with Locale::Unicode::Data

It provides the same API as DateTime::Locale, but in a dynamic way. This is important since in the Unicode LDML specifications, a locale inherits from its parent's data.

Once a data is retrieved by a method, it is cached to avoid waste of time.

Also, it provides some improvements, notably, the method prefers_24_hour_time in DateTime::Locale::FromData does a very simple check to see if the letter h or K exist in the time short format. This is wrong as it could catch those letter within single quotes, making them literals not part of the pattern tokens. For example, with the locale fr-CA, the time short format is HH 'h' mm, which would be caught as preferring 12 hours format although the letter h that got caught is a literal, not a pattern token.

It also adds a few methods to access the locale at time patterns, such as date_at_time_format_full, and native_variants

It also provides key support for day period

It also provides support for interval datetime, and a method to find the greatest datetime difference element between 2 datetimes, as well as a method to get all the available format patterns for intervals, and a method to retrieve the components of an specific interval patterns

It adds the short format for day missing in DateTime::Locale::FromData

Note that in CLDR parlance, there are standard pattern formats. For example full, long, medium, short or also abbreviated, short, wide, narrow providing various level of conciseness.

CONSTRUCTOR

new

    # Japanese as spoken in Japan
    my $locale = DateTime::Locale::FromCLDR->new( 'ja-JP' ) ||
        die( DateTime::Locale::FromCLDR->error );
    # Okinawan as spoken in the Japan Southern island
    my $locale = DateTime::Locale::FromCLDR->new( 'ryu-Kana-JP-t-de-t0-und-x0-medical' ) ||
        die( DateTime::Locale::FromCLDR->error );

    use Locale::Unicode;
    my $loc = Locale::Unicode->new( 'fr-FR' );
    my $locale = DateTime::Locale::FromCLDR->new( $loc ) ||
        die( DateTime::Locale::FromCLDR->error );

Specifying a calendar ID other than the default gregorian:

    my $locale = DateTime::Locale::FromCLDR->new( 'ja-JP', calendar => 'japanese' ) ||
        die( DateTime::Locale::FromCLDR->error );

or, using an hash reference:

    my $locale = DateTime::Locale::FromCLDR->new( 'ja-JP', { calendar => 'japanese' } ) ||
        die( DateTime::Locale::FromCLDR->error );

Instantiate a new DateTime::Locale::FromCLDR object based on a locale provided, and returns it. By default, it uses the calendar gregorian, but you can specify a different one with the calendar option.

You can provide any locale, even complex one as shown above, and only its core part will be retailed. So, for example:

    my $locale = DateTime::Locale::FromCLDR->new( 'ryu-Kana-JP-t-de-t0-und-x0-medical' ) ||
        die( DateTime::Locale::FromCLDR->error );
    say $locale; # ryu-Kana-JP

If an error occurs, it sets an exception object and returns undef in scalar context, or an empty list in list context, or possibly a special DateTime::Locale::FromCLDR::NullObject in object context. See "error" for more information.

The object is overloaded and stringifies into the core part of the original string provided upon instantiation.

The core part is comprised of the language ID, an optional script ID, an optional territory ID and zero or multiple variant IDs. See Locale::Unicode and the LDML specifications for more information.

METHODS

All methods are read-only unless stated otherwise.

am_pm_abbreviated

    my $array = $locale->am_pm_abbreviated;

Returns an array reference of the terms used to represent am and pm

The array reference could be empty if the locale does not support specifying am/pm

For example:

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $ampm = $locale->am_pm_abbreviated
    say @$ampm; # AM, PM

    my $locale = DateTime::Locale::FromCLDR->new( 'ja' );
    my $ampm = $locale->am_pm_abbreviated
    say @$ampm; # 午前, 午後

    my $locale = DateTime::Locale::FromCLDR->new( 'fr' );
    my $ampm = $locale->am_pm_abbreviated
    say @$ampm; # Empty

See "calendar_term" in Locale::Unicode::Data

available_formats

    my $array = $locale->available_formats;

Returns an array reference of all the format ID available for this locale

See "calendar_available_format" in Locale::Unicode::Data

calendar

    my $locale = DateTime::Locale::FromCLDR->new( 'ja-Kana-JP', calendar => 'japanese' ) ||
        die( DateTime::Locale::FromCLDR->error );
    my $str = $locale->calendar; # japanese
    $locale->calendar( 'gregorian' );

Sets or gets the calendar ID used to perform queries along with the given locale

code

    my $obj = $locale->code;

Returns the Locale::Unicode object either received or created upon object instantiation.

date_at_time_format_full

    my $str = $locale->date_at_time_format_full;

Returns the full date at time pattern

For example:

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->date_at_time_format_full;
    # EEEE, MMMM d, y 'at' h:mm:ss a zzzz
    # Tuesday, July 23, 2024 at 1:26:38 AM UTC

    my $locale = DateTime::Locale::FromCLDR->new( 'fr' );
    say $locale->date_at_time_format_full;
    # EEEE d MMMM y 'à' HH:mm:ss zzzz
    # mardi 23 juillet 2024 à 01:27:11 UTC

date_at_time_format_long

Same as date_at_time_format_full, but returns the long format pattern.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->date_at_time_format_long;
    # MMMM d, y 'at' h:mm:ss a z
    # July 23, 2024 at 1:26:11 AM UTC

date_at_time_format_medium

Same as date_at_time_format_full, but returns the medium format pattern.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->date_at_time_format_medium;
    # MMM d, y 'at' h:mm:ss a
    # Jul 23, 2024 at 1:25:43 AM

date_at_time_format_short

Same as date_at_time_format_full, but returns the short format pattern.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->date_at_time_format_short;
    # M/d/yy 'at' h:mm a
    # 7/23/24 at 1:25 AM

date_format_default

This is an alias to date_format_medium

date_format_full

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->date_format_full;
    # EEEE, MMMM d, y
    # Tuesday, July 23, 2024

Returns the full date pattern

See also "calendar_format_l10n" in Locale::Unicode::Data

date_format_long

Same as date_format_full, but returns the long format pattern.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->date_format_long;
    # MMMM d, y
    # July 23, 2024

date_format_medium

Same as date_format_full, but returns the medium format pattern.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->date_format_long;
    # MMM d, y
    # Jul 23, 2024

date_format_short

Same as date_format_full, but returns the short format pattern.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->date_format_short;
    # M/d/yy
    # 7/23/24

date_formats

    my $now = DateTime->now( locale => 'en' );
    my $ref = $locale->date_formats;
    foreach my $type ( sort( keys( %$ref ) ) )
    {
        say $type, ":";
        say $ref->{ $type };
        say $now->format_cldr( $ref->{ $type } ), "\n";
    }

Would produce:

    full:
    EEEE, MMMM d, y
    Tuesday, July 23, 2024

    long:
    MMMM d, y
    July 23, 2024

    medium:
    MMM d, y
    Jul 23, 2024

    short:
    M/d/yy
    7/23/24

Returns an hash reference with the keys being: full, long, medium, short and their value the result of their associated date format methods.

datetime_format

This is an alias for datetime_format_medium

datetime_format_default

This is also an alias for datetime_format_medium

datetime_format_full

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->datetime_format_full;
    # EEEE, MMMM d, y, h:mm:ss a zzzz
    # Tuesday, July 23, 2024, 1:53:27 AM UTC

Returns the full datetime pattern

See also "calendar_datetime_format" in Locale::Unicode::Data

datetime_format_long

Same as datetime_format_full, but returns the long format pattern.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->datetime_format_long;
    # MMMM d, y, h:mm:ss a z
    # July 23, 2024, 1:57:02 AM UTC

datetime_format_medium

Same as datetime_format_full, but returns the medium format pattern.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->datetime_format_medium;
    # MMM d, y, h:mm:ss a
    # Jul 23, 2024, 2:03:16 AM

datetime_format_short

Same as datetime_format_full, but returns the short format pattern.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->datetime_format_short;
    # M/d/yy, h:mm a
    # 7/23/24, 2:04 AM

day_format_abbreviated

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $days = $locale->day_format_abbreviated;
    say @$days;
    # Mon, Tue, Wed, Thu, Fri, Sat, Sun

Returns an array reference of week day names abbreviated format with Monday first and Sunday last.

See also "calendar_term" in Locale::Unicode::Data

day_format_narrow

Same as day_format_abbreviated, but returns the narrow format days.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $days = $locale->day_format_abbreviated;
    say @$days;
    # M, T, W, T, F, S, S

day_format_short

Same as day_format_abbreviated, but returns the short format days.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $days = $locale->day_format_short;
    say @$days;
    # Mo, Tu, We, Th, Fr, Sa, Su

day_format_wide

Same as day_format_abbreviated, but returns the wide format days.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $days = $locale->day_format_wide;
    say @$days;
    # Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday

day_period_format_abbreviated

    my $dt = DateTime->new( year => 2024, hour => 7 );
    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->day_period_format_abbreviated( $dt );
    # in the morning

    my $dt = DateTime->new( year => 2024, hour => 13 );
    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->day_period_format_abbreviated( $dt );
    # in the afternoon

    my $dt = DateTime->new( year => 2024, hour => 7 );
    my $locale = DateTime::Locale::FromCLDR->new( 'ja-Kana-JP' );
    say $locale->day_period_format_abbreviated( $dt );
    # 朝
    # which means "morning" in Japanese

    my $dt = DateTime->new( year => 2024, hour => 13 );
    my $locale = DateTime::Locale::FromCLDR->new( 'fr' );
    say $locale->day_period_format_abbreviated( $dt );
    # après-midi

Returns a string representing the localised expression of the period of day the DateTime object provided is.

If nothing relevant could be found somehow, this will return an empty string. undef is returned only if an error occurred.

This is used to provide the relevant value for the token B or b in the Unicode LDML format patterns

See also "calendar_term" in Locale::Unicode::Data, "day_period" in Locale::Unicode::Data and DateTime::Format::Unicode

day_period_format_narrow

Same as day_period_format_abbreviated, but returns the narrow format of day period.

    my $dt = DateTime->new( year => 2024, hour => 7 );
    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->day_period_format_narrow( $dt );
    # in the morning

day_period_format_wide

Same as day_period_format_abbreviated, but returns the wide format of day period.

    my $dt = DateTime->new( year => 2024, hour => 7 );
    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->day_period_format_wide( $dt );
    # in the morning

day_period_stand_alone_abbreviated

    my $dt = DateTime->new( year => 2024, hour => 7 );
    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->day_period_stand_alone_abbreviated( $dt );
    # morning

    my $dt = DateTime->new( year => 2024, hour => 13 );
    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->day_period_stand_alone_abbreviated( $dt );
    # afternoon

    my $dt = DateTime->new( year => 2024, hour => 7 );
    my $locale = DateTime::Locale::FromCLDR->new( 'ja-Kana-JP' );
    say $locale->day_period_stand_alone_abbreviated( $dt );
    # ""

The previous example would yield nothing, and as per the LDML specifications, you would need to use the localised AM/PM instead.

    my $dt = DateTime->new( year => 2024, hour => 13 );
    my $locale = DateTime::Locale::FromCLDR->new( 'fr' );
    say $locale->day_period_stand_alone_abbreviated( $dt );
    # ap.m.

Returns a string representing the localised expression of the period of day the DateTime object provided is.

If nothing relevant could be found somehow, this will return an empty string. undef is returned only if an error occurred.

This is used to provide a stand-alone word that can be used as a title, or in a different context.

See also "calendar_term" in Locale::Unicode::Data, "day_period" in Locale::Unicode::Data and DateTime::Format::Unicode

day_period_stand_alone_narrow

Same as day_period_stand_alone_abbreviated, but returns the narrow stand-alone version of the day period.

    my $dt = DateTime->new( year => 2024, hour => 13 );
    my $locale = DateTime::Locale::FromCLDR->new( 'fr' );
    say $locale->day_period_stand_alone_narrow( $dt );
    # ap.m.

day_period_stand_alone_wide

Same as day_period_stand_alone_abbreviated, but returns the wide stand-alone version of the day period.

    my $dt = DateTime->new( year => 2024, hour => 13 );
    my $locale = DateTime::Locale::FromCLDR->new( 'fr' );
    say $locale->day_period_stand_alone_wide( $dt );
    # après-midi

day_periods

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $hash = $locale->day_periods;
    # Would return an hash reference like:
    {
        midnight => ["00:00", "00:00"],
        morning1 => ["06:00", "12:00"],
        noon => ["12:00", "12:00"],
        afternoon1 => ["12:00", "18:00"],
        evening1 => ["18:00", "21:00"],
        night1 => ["21:00", "06:00"],
    }

Returns an hash reference of day period token and values of 2-elements array (start time and end time in hours and minutes)

day_stand_alone_abbreviated

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $days = $locale->day_stand_alone_abbreviated;
    say @$days;
    # Mon, Tue, Wed, Thu, Fri, Sat, Sun

Returns an array reference of week day names in abbreviated format with Monday first and Sunday last.

This is often identical to the format type.

See the LDML specifications for more information on the difference between the format and stand-alone types.

day_stand_alone_narrow

Same as day_stand_alone_abbreviated, but returns the narrow format days.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $days = $locale->day_stand_alone_narrow;
    say @$days;
    # M, T, W, T, F, S, S

day_stand_alone_short

Same as day_stand_alone_abbreviated, but returns the short format days.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $days = $locale->day_stand_alone_short;
    say @$days;
    # Mo, Tu, We, Th, Fr, Sa, Su

day_stand_alone_wide

Same as day_stand_alone_abbreviated, but returns the wide format days.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $days = $locale->day_stand_alone_wide;
    say @$days;
    # Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday

default_date_format_length

This returns the string medium

default_time_format_length

This returns the string medium

era_abbreviated

    my $array = $locale->era_abbreviated;
    say @$array;
    # BC, AD

Returns an array reference of era names in abbreviated format.

See also "calendar_eras_l10n" in Locale::Unicode::Data

era_narrow

Same as era_abbreviated, but returns the narrow format eras.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->era_narrow;
    say @$array;
    # B, A

era_wide

Same as era_abbreviated, but returns the wide format eras.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->era_wide;
    say @$array;
    # Before Christ, Anno Domini

error

Used as a mutator, this sets an exception object and returns an DateTime::Locale::FromCLDR::NullObject in object context (such as when chaining), or undef in scalar context, or an empty list in list context.

The DateTime::Locale::FromCLDR::NullObject class prevents the perl error of Can't call method "%s" on an undefined value (see perldiag). Upon the last method chained, undef is returned in scalar context or an empty list in list context.

first_day_of_week

    my $integer = $locale->first_day_of_week;

Returns an integer ranging from 1 to 7 where 1 means Monday and 7 means Sunday.

This represents what is the first day of the week for this locale

Since the information on the first day of the week pertains to a territory, if the locale you provided does not have such information, this method will find out the likely subtag to get the locale's rightful territory

See the LDML specifications about likely subtags for more information.

For example:

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );

Since there is no territory associated, this will look up the likely subtag to find the target locale is en-Latn-US, and thus the territory for en is US and first day of the week is 7

Another example:

    my $locale = DateTime::Locale::FromCLDR->new( 'fr-Latn' );

This will ultimately get the territory FR and first day of the week is 1

    # Okinawan as spoken in the Japanese Southern islands
    my $locale = DateTime::Locale::FromCLDR->new( 'ryu' );

This will become ryu-Kana-JP and thus the territory would be JP and first day of the week is 7

This information is cached in the current object, like for all the other methods in this API.

format_for

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $pattern = $locale->format_for( 'Bhm' );

Provided with the format ID of an available format and this will return the localised CLDR pattern.

Keep in mind that the CLDR formatting method of DateTime does not recognise all the CLDR pattern tokens. Thus, for example, if you chose the standard available pattern Bhm, this method would return the localised pattern h:mm B. However, DateTime does not understand the token B

    my $now = DateTime->now( locale => "en", time_zone => "Asia/Tokyo" );
    # Assuming $now = 2024-07-23T21:39:39
    say $now->format_cldr( 'h:mm B' );
    # 9:39 B

But B is the day period, which can be looked up with "day_period" in Locale::Unicode::Data, which provides us with the day period token night1, which itself can be looked up with "calendar_term" in Locale::Unicode::Data and gives us the localised string at night. Thus the proper CLDR formatting really should be 9:39 at night

You can use DateTime::Format::Unicode instead of the default DateTime CLDR formatting if you want to get better support for all CLDR pattern tokens.

With Japanese:

    my $locale = DateTime::Locale::FromCLDR->new( 'ja' );
    my $pattern = $locale->format_for( 'Bhm' );
    # BK:mm
    my $now = DateTime->now( locale => "ja", time_zone => "Asia/Tokyo" );
    say $now->format_cldr( 'BK:mm' );
    # B9:54

But, this should have yielded: 夜9:54 instead.

id

This is an alias for locale

interval_format

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->interval_format( GyMEd => 'G' );
    # ["E, M/d/y G", " – ", "E, M/d/y G", "E, M/d/y G – E, M/d/y G"]
    my $array = $locale->interval_format( GyMEd => 'M' );
    # ["E, M/d/y", " – ", "E, M/d/y G", "E, M/d/y – E, M/d/y G"]
    my $array = $locale->interval_format( GyMEd => 'd' );
    # ["E, M/d/y", " – ", "E, M/d/y G", "E, M/d/y – E, M/d/y G"]
    my $array = $locale->interval_format( GyMEd => 'y' );
    # ["E, M/d/y", " – ", "E, M/d/y G", "E, M/d/y – E, M/d/y G"]

Provided with a format ID and a greatest difference token, and this will return an array reference composed of the following 4 elements:

1. the first part
2. the separator
3. the second part
4. the full interval pattern

If nothing is found for the given format ID and greatest difference token, an empty array reference will be returned.

If an error occurred, this will set an error object and return undef in scalar context and an empty list.

With DateTime::Format::Unicode, you can do something like:

    my $fmt = DateTime::Format::Unicode->new(
        pattern => 'GyMEd',
        locale  => 'en',
    );
    my $str = $fmt->format_interval( $dt1, $dt2 );

This will use this method interval_format

If nothing is found, you can use the fallback pattern, which is something like this (varies from locale to locale): {0} - {1}

    my $array = $locale->interval_format( default => 'default' );
    # ["{0}", " - ", "{1}", "{0} - {1}"]

However, note that not all locales have a fallback pattern, so even the query above may return an empty array.

For example, as of version 45.0 (2024) of the CLDR data:

    # German:
    my $locale = DateTime::Locale::FromCLDR->new( 'de' );
    my $array = $locale->interval_format( default => 'default' );
    # []

    # French:
    my $locale = DateTime::Locale::FromCLDR->new( 'fr' );
    my $array = $locale->interval_format( default => 'default' );
    # []

    # Italian:
    my $locale = DateTime::Locale::FromCLDR->new( 'it' );
    my $array = $locale->interval_format( default => 'default' );
    # []

interval_formats

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $ref = $locale->interval_formats;

This would return something like:

    {
        Bh => [qw( B h )],
        Bhm => [qw( B h m )],
        d => ["d"],
        default => ["default"],
        Gy => [qw( G y )],
        GyM => [qw( G M y )],
        GyMd => [qw( d G M y )],
        GyMEd => [qw( d G M y )],
        GyMMM => [qw( G M y )],
        GyMMMd => [qw( d G M y )],
        GyMMMEd => [qw( d G M y )],
        H => ["H"],
        h => [qw( a h )],
        hm => [qw( a h m )],
        Hm => [qw( H m )],
        hmv => [qw( a h m )],
        Hmv => [qw( H m )],
        Hv => ["H"],
        hv => [qw( a h )],
        M => ["M"],
        Md => [qw( d M )],
        MEd => [qw( d M )],
        MMM => ["M"],
        MMMd => [qw( d M )],
        MMMEd => [qw( d M )],
        y => ["y"],
        yM => [qw( M y )],
        yMd => [qw( d M y )],
        yMEd => [qw( d M y )],
        yMMM => [qw( M y )],
        yMMMd => [qw( d M y )],
        yMMMEd => [qw( d M y )],
        yMMMM => [qw( M y )],
    }

Returns an hash reference of all available interval format IDs and their associated greatest difference token

The default interval format pattern is something like {0} – {1}, but this changes depending on the locale and is not always available.

{0} is the placeholder for the first datetime and {1} is the placeholder for the second one.

See "interval_formats" in Locale::Unicode::Data

interval_greatest_diff

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $diff = $locale->interval_greatest_diff( $dt1, $dt2 );

Provided with 2 DateTime objects, and this will compute the greatest difference.

Quoting from the LDML specifications:

"The data supplied in CLDR requires the software to determine the calendar field with the greatest difference before using the format pattern. For example, the greatest difference in "Jan 10-12, 2008" is the day field, while the greatest difference in "Jan 10 - Feb 12, 2008" is the month field. This is used to pick the exact pattern."

If both DateTime objects are identical, this will return an empty string.

If an error occurred, an exception object is set and undef is returned in scalar context, and an empty list in list context.

language

    my $locale = DateTime::Locale::FromCLDR->new( 'ja' );
    my $str = $locale->language;
    # Japanese

Returns the name of the locale in English

language_code

    my $locale = DateTime::Locale::FromCLDR->new( 'ja-Kana-JP' );
    my $str = $locale->language_code;
    # ja
    my $locale = DateTime::Locale::FromCLDR->new( 'ryu-JP' );
    my $str = $locale->language_code;
    # ryu

Returns the language ID part of the locale

language_id

This is an alias for language_code

locale

Returns the current Locale::Unicode object used in the current object.

month_format_abbreviated

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->month_format_abbreviated;
    say @$array;
    # Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec

Returns an array reference of month names in abbreviated format from January to December.

See also "calendar_term" in Locale::Unicode::Data

month_format_narrow

Same as month_format_abbreviated, but returns the months in narrow format.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->month_format_narrow;
    say @$array;
    # J, F, M, A, M, J, J, A, S, O, N, D

month_format_wide

Same as month_format_abbreviated, but returns the months in wide format.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->month_format_wide;
    say @$array;
    # January, February, March, April, May, June, July, August, September, October, November, December

month_stand_alone_abbreviated

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->month_stand_alone_abbreviated;
    say @$array;
    # Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec

Returns an array reference of month names in abbreviated stand-alone format from January to December.

See also "calendar_term" in Locale::Unicode::Data

Note that there is often little difference between the format and stand-alone format types.

See the LDML specifications for more information on the difference between the format and stand-alone types.

month_stand_alone_narrow

Same as month_stand_alone_abbreviated, but returns the months in narrow format.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->month_stand_alone_narrow;
    say @$array;
    # J, F, M, A, M, J, J, A, S, O, N, D

month_stand_alone_wide

Same as month_format_abbreviated, but returns the months in wide format.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->month_stand_alone_wide;
    say @$array;
    # January, February, March, April, May, June, July, August, September, October, November, December

name

    my $locale = DateTime::Locale::FromCLDR->new( 'fr' );
    say $locale->name; # French

    my $locale = DateTime::Locale::FromCLDR->new( 'fr-CH' );
    say $locale->name; # Swiss French

The locale's name in English.

See also native_name

native_language

    my $locale = DateTime::Locale::FromCLDR->new( 'fr-CH' );
    say $locale->native_language; # français

Returns the locale's language name as written in the locale own language.

If nothing can be found, it will return an empty string.

native_name

    my $locale = DateTime::Locale::FromCLDR->new( 'fr-CH' );
    say $locale->native_name; # français suisse

Returns the locale's name as written in the locale own language.

If nothing can be found, it will return an empty string.

native_script

    my $locale = DateTime::Locale::FromCLDR->new( 'fr-Latn-CH' );
    say $locale->native_script; # latin

    my $locale = DateTime::Locale::FromCLDR->new( 'fr' );
    say $locale->native_script; # undef

Returns the locale's script name as written in the locale own language.

If there is no script specified in the locale, it will return undef

If there is a script in the locale, but, somehow, it cannot be found in the locale's own language tree, it will return an empty string.

native_territory

    my $locale = DateTime::Locale::FromCLDR->new( 'fr-CH' );
    say $locale->native_territory; # Suisse

    my $locale = DateTime::Locale::FromCLDR->new( 'fr' );
    say $locale->native_territory; # undef

    my $locale = DateTime::Locale::FromCLDR->new( 'en-Latn-003' );
    say $locale->native_territory; # North America

    my $locale = DateTime::Locale::FromCLDR->new( 'en-XX' );
    say $locale->native_territory; # ''

Returns the locale's territory name as written in the locale own language.

If there is no territory specified in the locale, it will return undef

If there is a territory in the locale, but, somehow, it cannot be found in the locale's own language tree, it will return an empty string.

native_variant

    my $locale = DateTime::Locale::FromCLDR->new( 'es-valencia' );
    say $locale->native_variant; # Valenciano

    my $locale = DateTime::Locale::FromCLDR->new( 'es' );
    say $locale->native_variant; # undef

    my $locale = DateTime::Locale::FromCLDR->new( 'en-Latn-005' );
    say $locale->native_variant; # undef

Returns the locale's variant name as written in the locale own language.

If there is no variant specified in the locale, it will return undef, and if there is more than one variant it will return the value for the first one only. To get the values for all variants, use native_variants

If there is a variant in the locale, but, somehow, it cannot be found in the locale's own language tree, it will return an empty string.

native_variants

    my $locale = DateTime::Locale::FromCLDR->new( 'ja-Latn-fonipa-hepburn-heploc' );
    say $locale->native_variants;
    # ["IPA Phonetics", "Hepburn romanization", ""]

Here, heploc is an empty string in the array, because it is a deprecated variant, and as such there is no localised name value for it in the CLDR data.

    my $locale = DateTime::Locale::FromCLDR->new( 'es' );
    say $locale->native_variants; # []

Returns an array reference of each of the locale's variant subtag name as written in the locale own language.

If there is no variant specified in the locale, it will return an empty array.

If a variant subtag cannot be found in the locale's own language tree, then an empty string will be set in the array instead.

Either way, the size of the array will always be equal to the number of variants in the locale

prefers_24_hour_time

This checks whether the locale prefers the 24H format or the 12H one and returns true (1) if it prefers the 24 hours format or false (0) otherwise.

quarter_format_abbreviated

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->quarter_format_abbreviated;
    say @$array;
    # Q1, Q2, Q3, Q4

Returns an array reference of quarter names in abbreviated format.

See also "calendar_term" in Locale::Unicode::Data

quarter_format_narrow

Same as quarter_format_abbreviated, but returns the quarters in narrow format.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->quarter_format_narrow;
    say @$array;
    # 1, 2, 3, 4

quarter_format_wide

Same as quarter_format_abbreviated, but returns the quarters in wide format.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->quarter_format_wide;
    say @$array;
    # 1st quarter, 2nd quarter, 3rd quarter, 4th quarter

quarter_stand_alone_abbreviated

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->quarter_stand_alone_abbreviated;
    say @$array;
    # Q1, Q2, Q3, Q4

Returns an array reference of quarter names in abbreviated format.

See also "calendar_term" in Locale::Unicode::Data

Note that there is often little difference between the format and stand-alone format types.

See the LDML specifications for more information on the difference between the format and stand-alone types.

quarter_stand_alone_narrow

Same as quarter_stand_alone_abbreviated, but returns the quarters in narrow format.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->quarter_stand_alone_narrow;
    say @$array;
    # 1, 2, 3, 4

quarter_stand_alone_wide

Same as quarter_stand_alone_abbreviated, but returns the quarters in wide format.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->quarter_stand_alone_wide;
    say @$array;
    # 1st quarter, 2nd quarter, 3rd quarter, 4th quarter

script

    my $locale = DateTime::Locale::FromCLDR->new( 'ja-Kana-JP' );
    my $str = $locale->script;
    # Katakana

Returns the name of the locale's script in English.

If there is no script specified in the locale, it will return undef

If there is a script in the locale, but, somehow, it cannot be found in the en locale's language tree, it will return an empty string.

script_code

    my $locale = DateTime::Locale::FromCLDR->new( 'ja-Kana-JP' );
    my $script = $locale->script_code;
    # Kana

    my $locale = DateTime::Locale::FromCLDR->new( 'ja-JP' );
    my $script = $locale->script_code;
    # undef

Returns the locale's script ID, or undef if there is none.

script_id

This is an alias for script_code

territory

    my $locale = DateTime::Locale::FromCLDR->new( 'ja-JP' );
    my $script = $locale->territory;
    # Japan

    my $locale = DateTime::Locale::FromCLDR->new( 'zh-034' );
    my $script = $locale->territory;
    # Southern Asia

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $script = $locale->territory;
    # undef

    my $locale = DateTime::Locale::FromCLDR->new( 'en-XX' );
    my $script = $locale->territory;
    # ''

Returns the name of the locale's territory in English.

If there is no territory specified in the locale, it will return undef

If there is a territory in the locale, but, somehow, it cannot be found in the en locale's language tree, it will return an empty string.

territory_code

    my $locale = DateTime::Locale::FromCLDR->new( 'ja-JP' );
    my $script = $locale->territory_code;
    # JP

    my $locale = DateTime::Locale::FromCLDR->new( 'ja-Kana' );
    my $script = $locale->territory_code;
    # undef

Returns the locale's territory ID, or undef if there is none.

territory_id

This is an alias for territory_code

time_format_default

This is an alias for time_format_medium

time_format_full

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->time_format_full;
    # h:mm:ss a zzzz
    # 10:44:07 PM UTC

Returns the full date pattern

See also "calendar_format_l10n" in Locale::Unicode::Data

time_format_long

Same as time_format_full, but returns the long format pattern.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->time_format_long;
    # h:mm:ss a z
    # 10:44:07 PM UTC

time_format_medium

Same as time_format_full, but returns the medium format pattern.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->time_format_medium;
    # h:mm:ss a
    # 10:44:07 PM

time_format_short

Same as time_format_full, but returns the short format pattern.

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->time_format_short;
    # h:mm a
    # 10:44 PM

time_formats

    my $now = DateTime->now( locale => 'en' );
    my $ref = $locale->time_formats;
    foreach my $type ( sort( keys( %$ref ) ) )
    {
        say $type, ":";
        say $ref->{ $type };
        say $now->format_cldr( $ref->{ $type } ), "\n";
    }

Would produce:

    full:
    h:mm:ss a zzzz
    10:44:07 PM UTC

    long:
    h:mm:ss a z
    10:44:07 PM UTC

    medium:
    h:mm:ss a
    10:44:07 PM

    short:
    h:mm a
    10:44 PM

Returns an hash reference with the keys being: full, long, medium, short and their value the result of their associated time format methods.

variant

    my $locale = DateTime::Locale::FromCLDR->new( 'es-valencia' );
    my $script = $locale->variant;
    # Valencian

    my $locale = DateTime::Locale::FromCLDR->new( 'es' );
    my $script = $locale->variant;
    # undef

    # No such thing as variant 'klingon'. Language 'tlh' exists though :)
    my $locale = DateTime::Locale::FromCLDR->new( 'en-klingon' );
    my $script = $locale->variant;
    # ''

Returns the name of the locale's variant in English.

If there is no variant specified in the locale, it will return undef

If there is a variant in the locale, but, somehow, it cannot be found in the en locale's language tree, it will return an empty string.

variant_code

    my $locale = DateTime::Locale::FromCLDR->new( 'es-valencia' );
    my $script = $locale->variant_code;
    # valencia

    my $locale = DateTime::Locale::FromCLDR->new( 'es-ES' );
    my $script = $locale->variant_code;
    # undef

Returns the locale's variant ID, or undef if there is none.

variant_id

This is an alias for variant_code

variants

    my $locale = DateTime::Locale::FromCLDR->new( 'es-valencia' );
    my $array = $locale->variants;
    # ["valencia"]

    my $locale = DateTime::Locale::FromCLDR->new( 'ja-Latn-fonipa-hepburn-heploc' );
    my $array = $locale->variants;
    # ["fonipa", "hepburn", "heploc"]

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    my $array = $locale->variants;
    # []

This returns an array reference of variant subtags for this locale, even if there is no variant.

version

    my $locale = DateTime::Locale::FromCLDR->new( 'en' );
    say $locale->version; # 45.0

Returns the Unicode CLDR data version number.

SERIALISATION

Locale::Unicode supports Storable::Improved, Storable, Sereal and CBOR serialisation, by implementing the methods FREEZE, THAW, STORABLE_freeze, STORABLE_thaw

For serialisation with Sereal, make sure to instantiate the Sereal encoder with the freeze_callbacks option set to true, otherwise, Sereal will not use the FREEZE and THAW methods.

See "FREEZE/THAW CALLBACK MECHANISM" in Sereal::Encoder for more information.

For CBOR, it is recommended to use the option allow_sharing to enable the reuse of references, such as:

    my $cbor = CBOR::XS->new->allow_sharing;

Also, if you use the option allow_tags with JSON, then all of those modules will work too, since this option enables support for the FREEZE and THAW methods.

AUTHOR

Jacques Deguest <jack@deguest.jp>

SEE ALSO

Locale::Unicode, Locale::Unicode::Data, DateTime::Format::Unicode

DateTime::Locale

COPYRIGHT & LICENSE

Copyright(c) 2024 DEGUEST Pte. Ltd.

All rights reserved

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.