NAME

DateTime::Lite::TimeZone - DateTime::Liteのための軽量なタイムゾーンサポート

SYNOPSIS

use DateTime::Lite::TimeZone;

my $tz = DateTime::Lite::TimeZone->new( name => 'Asia/Tokyo' ) ||
    die( DateTime::Lite::TimeZone->error );

my $dt = DateTime::Lite->now( time_zone => $tz );

# エイリアス
my $tz2 = DateTime::Lite::TimeZone->new( name => 'US/Eastern' );

# 固定オフセット
my $tz3 = DateTime::Lite::TimeZone->new( name => '+09:00' );

# 特別なゾーン
my $utc  = DateTime::Lite::TimeZone->new( name => 'UTC' );
my $flt  = DateTime::Lite::TimeZone->new( name => 'floating' );

# 単一引数の省略形
my $tz4 = DateTime::Lite::TimeZone->new( 'Europe/Paris' );

# 緯度と経度を使用
my $tz = DateTime::Lite::TimeZone->new(
    latitude  => 35.658558,
    longitude => 139.745504,
) || die( "Could not find a timezone: ", DateTime::Lite::TimeZone->error );

# 'lat'と'lon'も使用できます
my $tz = DateTime::Lite::TimeZone->new(
    lat => 35.658558,
    lon => 139.745504,
) || die( "Could not find a timezone: ", DateTime::Lite::TimeZone->error );
say $tz->name;  # Asia/Tokyo

# メモリキャッシュ(3層:object + span + POSIX footer)
# 最良のパフォーマンスを得るには、アプリケーション起動時に一度だけ有効化します:
DateTime::Lite::TimeZone->enable_mem_cache;

# または呼び出しごとに:
my $tz5 = DateTime::Lite::TimeZone->new(
    name          => 'America/New_York',
    use_cache_mem => 1,
);

DateTime::Lite::TimeZone->disable_mem_cache;  # 無効化してクリアします
DateTime::Lite::TimeZone->clear_mem_cache;    # 無効化せずにクリアします

# オフセットおよびDSTクエリ
use DateTime::Lite;
my $dt = DateTime::Lite->now( time_zone => $tz );

my $offset_secs = $tz->offset_for_datetime( $dt );        # 例:-18000
my $local_off   = $tz->offset_for_local_datetime( $dt );  # 壁時計時刻から
my $is_dst      = $tz->is_dst_for_datetime( $dt );        # 1または0
my $abbr        = $tz->short_name_for_datetime( $dt );    # 例:"EDT"

printf "%s", $tz->offset_as_string( $offset_secs );       # "-0500"
printf "%s", $tz->offset_as_string( $offset_secs, ':' );  # "-05:00"

# オフセット文字列を秒数へ解析:
my $secs = DateTime::Lite::TimeZone->offset_as_seconds( '-05:00' );  # -18000

# ゾーンメタデータ
$tz->name;             # 正規名。例:"America/New_York"
$tz->is_olson;         # IANA名前付きゾーンなら1
$tz->is_utc;           # UTCなら1
$tz->is_floating;      # floatingなら1
$tz->has_dst;          # ゾーンが過去または現在DSTを採用するなら1
$tz->country_codes;    # ISO 3166-1 alpha-2コードの配列リファレンス。例:['US']
$tz->countries;        # 国データを含むハッシュリファレンスの配列リファレンス
$tz->coordinates;      # 例:"+404251-0740023"
$tz->comment;          # IANAデータ由来の自由記述注釈
$tz->latitude;
$tz->longitude;
$tz->tz_version;       # IANAリリース文字列。例:"2026a"
$tz->tzif_version;     # TZifバイナリ形式バージョン(1, 2, 3, または 4)
$tz->footer_tz_string; # 繰り返しDST規則用のPOSIX TZ文字列
$tz->transition_count;
$tz->type_count;
$tz->leap_count;

# ゾーン探索
my $all      = DateTime::Lite::TimeZone->all_names;  # 配列リファレンス
my @all      = DateTime::Lite::TimeZone->all_names;
my $cats     = DateTime::Lite::TimeZone->categories; # 配列リファレンス
my @cats     = DateTime::Lite::TimeZone->categories;
my $in_cat   = DateTime::Lite::TimeZone->names_in_category('America');  # 配列リファレンス
my @in_cat   = DateTime::Lite::TimeZone->names_in_category('America');
my $in_cc    = DateTime::Lite::TimeZone->names_in_country('JP');        # 配列リファレンス
my @in_cc    = DateTime::Lite::TimeZone->names_in_country('JP');
my $is_valid = DateTime::Lite::TimeZone->is_valid_name('Asia/Tokyo');   # 1

my $aliases  = DateTime::Lite::TimeZone->aliases;   # hashref alias => canonical
my %aliases  = DateTime::Lite::TimeZone->aliases;   # hash    alias => canonical
my $links    = $tz->links;                          # エイリアス名の配列リファレンス

# IANA types テーブルに対してタイムゾーン略称を解決
my $results = DateTime::Lite::TimeZone->resolve_abbreviation( 'JST' );
# $results = [
#     {
#         ambiguous        => 0,
#         extended         => 0,
#         first_trans_time => -2587712400,
#         is_active        => 1,
#         is_dst           => 0,
#         last_trans_time  => -577962000,
#         utc_offset       => 32400,
#         zone_name        => "Asia/Tokyo",
#     },
#     {
#         ambiguous        => 0,
#         extended         => 0,
#         first_trans_time => -1830414600,
#         is_active        => 0,
#         is_dst           => 0,
#         last_trans_time  => -1830414600,
#         utc_offset       => 32400,
#         zone_name        => "Asia/Pyongyang",
#     },
#     # etc...
# ]

# 一緒に解析された数値オフセットで絞り込み
my $pst = DateTime::Lite::TimeZone->resolve_abbreviation( 'PST',
    utc_offset => -28800
);

# 期間フィルタ:1950年以降もJSTを使用していたゾーン
my $modern = DateTime::Lite::TimeZone->resolve_abbreviation( 'JST',
    period => '>1950-01-01'
);

# 2つのISO日付境界を持つ期間フィルタ
my $wartime = DateTime::Lite::TimeZone->resolve_abbreviation( 'JST',
    period => ['>1941-01-01', '<1946-01-01']
);

# 生のエポック整数を使った期間フィルタ(1970 年以降の値なら全プラットフォームで安全)
my $epoch_2010 = 1262304000;  # 2010-01-01 00:00:00 UTC
my $recent = DateTime::Lite::TimeZone->resolve_abbreviation( 'EST',
    period => ">$epoch_2010"
);

# 期間フィルタ:現在この略称を使用しているゾーンのみ
my $current = DateTime::Lite::TimeZone->resolve_abbreviation( 'JST',
    period => 'current'
);

# 拡張モード:IANA typesにない場合、extended_aliases にフォールバック
# (AFT, AMST, CEST, HAEC など、実際に使われる略称をカバーします)
my $aft = DateTime::Lite::TimeZone->resolve_abbreviation( 'AFT',
    extended => 1
);
# $aft = [
#     {
#         ambiguous  => 0,
#         extended   => 1,
#         is_dst     => undef,
#         is_primary => 1,
#         utc_offset => undef,
#         zone_name  => "Asia/Kabul",
#     },
# ]

# データベースアクセス(低レベル)
my $path = DateTime::Lite::TimeZone->datafile;  # tz.sqlite3へのパス
# public viewメソッド経由の生SQLiteクエリ(DBI statement handleを返します):
#   $tz->zones, $tz->spans, $tz->transition, $tz->types,
#   $tz->aliases, $tz->countries, $tz->leap_second, $tz->metadata

# エラー処理
my $bad = DateTime::Lite::TimeZone->new( name => 'Mars/Olympus' );
if( !defined( $bad ) )
{
    warn DateTime::Lite::TimeZone->error;  # "Unknown time zone 'Mars/Olympus'"
}
$tz->fatal(1);  # エラーを warn+undef ではなく die にします

# エラー時でもオブジェクトコンテキストを検出し、典型的な
# "Can't call method "%s" on an undefined value"を避けるため、
# チェーンが最後まで展開されるようにします。
# https://perldoc.perl.org/perldiag#Can't-call-method-%22%25s%22-on-an-undefined-value を参照
my $bad = DateTime::Lite::TimeZone->new( name => 'Mars/Olympus' )->name;

VERSION

v0.5.7

DESCRIPTION

DateTime::Lite::TimeZoneは、DateTime::TimeZoneの重い依存関係とメモリフットプリントを取り除くことを目的とした、ドロップイン代替モジュールです。

DateTime::TimeZoneは、コンストラクタ引数を検証するだけのために、SpecioParams::ValidationCompilerException::Classスタック全体を含む85個のモジュールを起動時に読み込みます。DateTime::Lite::TimeZoneは、そのすべてを、同梱されたコンパクトなデータベース(tz.sqlite3)に対する単一のDBD::SQLiteクエリで置き換えます。

Locale::Unicode::Dataモジュールによって提供されるUnicode CLDR(Common Locale Data Repository)にも関心があるかもしれません。これはmetazonesregions、履歴タイムゾーンデータなど、より豊富なタイムゾーン情報を提供します。

たとえば:

my $cldr = Locale::Unicode::Data->new;
my $ref  = $cldr->timezone( timezone => 'Asia/Tokyo' );

これは次のような情報を含むハッシュリファレンスを返します。

{
   timezone_id => 281,
   timezone    => 'Asia/Tokyo',
   territory   => 'JP',
   region      => 'Asia',
   tzid        => 'japa',
   metazone    => 'Japan',
   tz_bcpid    => 'jptyo',
   is_golden   => 1,
   is_primary  => 0,
   is_preferred => 0,
   is_canonical => 0,
}

国コードに対応するすべてのタイムゾーンを取得することもできます。

my $array_ref = $cldr->timezones( territory => 'US' );

これは次のような55件の結果を返します。

{
    alias => [qw( America/Atka US/Aleutian )],
    is_canonical => 1,
    is_golden => 1,
    is_preferred => 0,
    is_primary => 0,
    metazone => "Hawaii_Aleutian",
    region => "America",
    territory => "US",
    timezone => "America/Adak",
    timezone_id => 55,
    tz_bcpid => "usadk",
    tzid => "haal",
}

タイムゾーンに対応するローカライズ済み都市名も取得できます。

my $ref = $cldr->timezone_city(
    locale   => 'de',
    timezone => 'Asia/Tokyo',
);

これは次のような値を返します。

{
   tz_city_id  => 7486,
   locale      => 'de',
   timezone    => 'Asia/Tokyo',
   city        => 'Tokio',
   alt         => undef,
}

履歴情報へアクセスしたい場合は、次のようにできます。

my $ref = $cldr->timezone_info(
    timezone    => 'Europe/Simferopol',
    start       => '1994-04-30T21:00:00',
);

これは次のような値を返します。

{
   tzinfo_id   => 594,
   timezone    => 'Europe/Simferopol',
   metazone    => 'Moscow',
   start       => '1994-04-30T21:00:00',
   until       => '1997-03-30T01:00:00',
}

または、次のようにすることもできます。

my $ref = $cldr->timezone_info(
    timezone    => 'Europe/Simferopol',
    start       => ['>1992-01-01', '<1995-01-01'],
);

正確な日付が分からず、代わりに範囲を指定したい場合に便利です。

データベーススキーマ

同梱のtz.sqlite3は、主に次のテーブルを使用します。

aliases

エイリアスからzone_idへのFKマッピングです(例:US/EasternからAmerica/New_York)。

metadata

tzdataバージョンを含むキー/値ペアです。

spans

遷移とtypesから導出された事前計算済みの期間です。高速な範囲検索のためにインデックスされています。

types

TZifファイル由来のローカル時刻タイプレコードです。

zones

国コードと座標を含む、正規IANAゾーン名です。

フォールバックモード

DBD::SQLiteが利用できない場合、または同梱のtz.sqlite3が見つからない場合、DateTime::Lite::TimeZoneは透過的にDateTime::TimeZoneへフォールバックし、警告が許可されていれば一度だけ警告を出します。

DateTime::TimeZoneも利用できない場合は、dieします。

CONSTRUCTOR

new

my $zone = DateTime::Lite::TimeZone->new( 'Asia/Tokyo' );
my $zone = DateTime::Lite::TimeZone->new(
    name  => 'Asia/Tokyo',
    fatal => 1, # すべてのエラーを fatal にします
);

# 緯度と経度を使用
my $tz = DateTime::Lite::TimeZone->new(
    latitude  => 35.658558,
    longitude => 139.745504,
) || die( "Could not find a timezone: ", DateTime::Lite::TimeZone->error );

# 'lat'と'lon'も使用できます
my $tz = DateTime::Lite::TimeZone->new(
    lat => 35.658558,
    lon => 139.745504,
) || die( "Could not find a timezone: ", DateTime::Lite::TimeZone->error );
say $tz->name;  # Asia/Tokyo

新しいDateTime::Lite::TimeZoneオブジェクトは、タイムゾーンを単一引数として渡すか、name => 'Asia/Tokyo'のようなハッシュとして渡すことで生成できます。

認識される形式:

America/New_YorkEurope/Parisのような名前付きIANAタイムゾーン。
US/EasternJapanのようなエイリアス。
+09:00-0500のような固定オフセット文字列。
特別な名前UTCfloatinglocal

localという名前は、外部モジュールを必要とせずに、システムのローカルタイムゾーンを自動判定するようDateTime::Lite::TimeZoneに指示します。判定戦略はOS固有で、$^Oに依存します。

Linux、macOS (darwin)、FreeBSD、OpenBSD、NetBSD、Solaris、AIX、HP-UX、OS/2、Cygwin

次の順に試します。

  • $ENV{TZ}

  • /etc/localtimeのsymlink先、または/usr/share/zoneinfoに対するバイナリ一致

  • /etc/timezone(Debian/Ubuntu)

  • TZ=行を含む/etc/TIMEZONE(Solaris, HP-UX)

  • ZONE=またはTIMEZONE=行を含む/etc/sysconfig/clock(RedHat/CentOS)

  • TZ=行を含む/etc/default/init(古いUnix)

Windows (MSWin32、NetWare)

まず$ENV{TZ}を試し、その後Windows Registry(SYSTEM/CurrentControlSet/Control/TimeZoneInformation)からタイムゾーン名を読み取り、CLDRのwindowsZones.xmlテーブルを使ってIANA名へマッピングします。 Win32::TieRegistryが必要です(CPANで利用可能ですが、必須依存ではありません)。

Android

$ENV{TZ}、次にgetprop persist.sys.timezoneを試し、その後UTCへフォールバックします。

VMS

環境変数TZSYS$TIMEZONE_RULESYS$TIMEZONE_NAMEUCX$TZTCPIP$TZを確認します。

Symbian、EPOC、MS-DOS、Mac OS 9以前

$ENV{TZ}のみを確認します。

ローカルタイムゾーンを判定できない場合は、エラーが設定され、スカラコンテキストではundef、リストコンテキストでは空リストが返されます。チェーン呼び出し(オブジェクトコンテキスト)では、典型的なCan't call method '%s' on an undefined valueを避けるため、ダミーオブジェクト(DateTime::Lite::Null)を返します。

latitudeおよびlongitude引数による座標。

nameの代わりに10進度の座標を渡すことで、DateTime::Lite::TimeZoneに最も近いIANAタイムゾーンを自動解決させることができます。

my $tz = DateTime::Lite::TimeZone->new(
    latitude  => 35.658558,
    longitude => 139.745504,
);
say $tz->name;  # Asia/Tokyo

解決にはIANAzone1970.tabファイルに保存された参照座標(正規ゾーンごとに1つの代表点)を使用し、haversine great-circle distanceにより最も近いゾーンを探します。これは近似です。ほとんどの場所では正確ですが、タイムゾーン境界付近、係争地域、またはKaliningradのような飛び地では誤った結果になる可能性があります。境界に厳密な解決が必要な場合は、代わりにGeo::Location::TimeZoneFinderを検討してください。

latitude-90から90longitude-180から180の範囲でなければなりません。値が範囲外である場合、またはデータベース内に座標付きゾーンが見つからない場合、エラーオブジェクトが設定され、スカラコンテキストではundef、リストコンテキストでは空リストが返されます。

haversine公式は、データベースが-DSQLITE_ENABLE_MATH_FUNCTIONS付きでコンパイルされている場合、SQLite内で計算されます(SQLite version >= 3.35.0、2021年3月リリース)。

古いシステム、または数学関数が存在しないビルドでは、必要な関数(sqrtsincosasin)が、初回使用時に"sqlite_create_function" in DBD::SQLite経由でPerl UDF(User Defined Functions)として自動登録されます。そのため、座標解決はサポートされるすべてのSQLiteバージョンで透過的に動作します。

検出はバージョンを考慮して行われます。つまり:

  • SQLite version >= 3.35.0では、UDFを登録する前に特殊なsystem table pragma_function_listsqrtを問い合わせ、ネイティブ関数を優先的に使用することを確認します。

  • SQLite version <3.35.0では、数学関数がまだ存在しないため、pragma_function_listを問い合わせずにUDFを直接登録します。

  • SQLite version <3.16.0では、pragma_function_listはtable-valued functionとして利用できないため、UDFを直接登録します。

UDFはSQLite version >= 3.0.0のすべてで利用できます。

古いシステムでSQLite 3.31.1が同梱されている場合も、必要な関数(sqrtsincosasin)は初回使用時に"sqlite_create_function" in DBD::SQLite経由でPerl UDF(User Defined Functions)として自動登録されるため、座標解決はサポートされるすべてのSQLiteバージョンで透過的に動作します。

真の値を持つbooleanオプションuse_cache_memは、この呼び出しに対してプロセスレベルのメモリキャッシュを有効化します。設定されると、同じゾーン名(またはそのエイリアス)での以後の呼び出しは、データベースクエリなしでキャッシュ済みオブジェクトを返します。詳細およびクラスレベルの代替である"enable_mem_cache"については"メモリキャッシュ"を参照してください。

# これらは最初の構築後、キャッシュにヒットします:
my $tz = DateTime::Lite::TimeZone->new(
    name          => 'America/New_York',
    use_cache_mem => 1,
);

真の値を持つbooleanオプションextendedは、名前が有効なIANAタイムゾーン名として認識されない場合に、略称解決をフォールバックとして有効化します。これは、呼び出し元が外部ソースからJSTCETESTのようなタイムゾーン略称を受け取り、"resolve_abbreviation"を明示的に呼び出さずに正規IANAゾーンへ解決したい場合に便利です。

extendedが設定され、名前がIANAタイムゾーンとして未知の場合、newは内部的にextendedオプションを真にしてresolve_abbreviationを呼び出します。そして単一の曖昧でない候補が見つかった場合、その解決済み正規名で再帰的に呼び出します。略称が曖昧である場合、またはextended aliasesテーブルでも見つからない場合は、通常のUnknown time zoneエラーが返されます。

my $tz = DateTime::Lite::TimeZone->new( name => 'JST', extended => 1 );
say $tz->name;  # Asia/Tokyo

成功時には新しいオブジェクトを返します。エラー時にはerror()により例外オブジェクトを設定し、スカラコンテキストではundef、リストコンテキストでは空リストを返します。メソッドチェーン(オブジェクト)コンテキストでは、Can't call method '%s' on an undefined valueエラーを避けるため、DateTime::Lite::NullObjectを返します。ただし、チェーンの最後ではundefまたは空リストが返されます。

メモリキャッシュ

デフォルトでは、"new"を呼び出すたびにSQLiteクエリを使って新しいオブジェクトを構築します。同じゾーン名でDateTime::Lite::TimeZoneオブジェクトを繰り返し構築するアプリケーション向けに、3層のキャッシュが用意されています。

Layer 1 - オブジェクトキャッシュ:有効化されている場合、同じゾーン名に対する2回目以降の呼び出しは、データベースを完全に迂回し、元のオブジェクトをハッシュから直接返します。

Layer 2 - spanキャッシュ:キャッシュ済みの各TimeZoneオブジェクトは、直近に一致したUTCおよびローカル時刻spanを保存します。offset_for_datetimeおよびoffset_for_local_datetimeの呼び出しでは、タイムスタンプがキャッシュ済みspanの[utc_start, utc_end)または[local_start, local_end)範囲内にある場合、SQLiteクエリを省略します。

Layer 3 - POSIX footerキャッシュ:現在の日付が繰り返しDST規則(POSIX TZ footer文字列)によって管理されるゾーンでは、footer計算の結果が暦日単位でキャッシュされます。DST遷移は年に2回発生するだけなので、それ以外の日では規則を再評価せずにキャッシュ済みの結果を返します。

これら3層により、DateTime::Lite->new( time_zone => 'America/New_York' )の呼び出しごとのコストは約430 µsから約25 µsまで低下し、DateTimeと同等になります。

キャッシュエントリは、"new"に渡された名前と、エイリアス解決後の正規名をキーにします。そのため、US/EasternAmerica/New_Yorkは同じキャッシュ済みオブジェクトへ対応します。

通常の使用では、キャッシュ済みオブジェクトは不変です。すべてのpublic accessorは読み取り専用なので、複数の呼び出し元でオブジェクトを共有しても安全です。

enable_mem_cache

クラスメソッドです。以後のすべての"new"呼び出しに対してメモリキャッシュを有効化します。

DateTime::Lite::TimeZone->enable_mem_cache;

# すべての new() 呼び出しは、最初の構築後にキャッシュへヒットします:
my $tz = DateTime::Lite::TimeZone->new( name => 'America/New_York' );
my $tz2 = DateTime::Lite::TimeZone->new( name => 'America/New_York' );
# $tz と $tz2 は同じオブジェクトです

すべての"new"呼び出しにuse_cache_mem => 1を渡すことと同等ですが、プロセスの存続期間中キャッシュを有効にしたい場合には、こちらの方が便利です。チェーン呼び出しを可能にするため、クラス名を返します。

disable_mem_cache

クラスメソッドです。メモリキャッシュを無効化し、すべてのキャッシュエントリをクリアします。以後の"new"呼び出しでは、新しいオブジェクトが構築されます。

DateTime::Lite::TimeZone->disable_mem_cache;

クラス名を返します。

clear_mem_cache

クラスメソッドです。キャッシュを無効化せずに空にします。任意のゾーン名に対する次の"new"呼び出しでは、データベースへ再クエリし、キャッシュを再構築します。

tz.sqlite3データベースが実行時に置き換えられた場合に便利です(通常はまれな操作です)。

DateTime::Lite::TimeZone->clear_mem_cache;

クラス名を返します。

METHODS

aliases

# エラーも確認します
my $aliases  = DateTime::Lite::TimeZone->aliases ||
    die( DateTime::Lite::TimeZone->error );
my( %aliases ) = DateTime::Lite::TimeZone->aliases ||
    die( DateTime::Lite::TimeZone->error );
my $aliases    = $zone->aliases ||
    die( $zone->error );
my( %aliases ) = $zone->aliases ||
    die( $zone->error );

これはインスタンスメソッドとしても、クラス関数としても呼び出せます。

すべてのゾーンエイリアス(古く、非推奨となった名前)から、それぞれ対応する正規名へのハッシュを返します。

例:

Japan -> Asia/Tokyo

スカラコンテキストではハッシュリファレンスを返し、リストコンテキストではハッシュを返します。

エラーが発生した場合は例外オブジェクトを設定し、スカラコンテキストではundef、リストコンテキストでは空リストを返します。例外オブジェクトはその後"error"で取得できます。

all_names

# エラーも確認します
my $names    = DateTime::Lite::TimeZone->all_names ||
    die( DateTime::Lite::TimeZone->error );
my( @names ) = DateTime::Lite::TimeZone->all_names ||
    die( DateTime::Lite::TimeZone->error );
my $names    = $zone->all_names ||
    die( $zone->error );
my( @names ) = $zone->all_names ||
    die( $zone->error );

これはインスタンスメソッドとしても、クラス関数としても呼び出せます。

すべてのタイムゾーン名をアルファベット順に並べたリストを返します。 このリストにはゾーンエイリアス(いわゆる “links”)は含まれません。

スカラコンテキストでは配列リファレンスを返し、リストコンテキストでは配列を返します。

エラーが発生した場合は例外オブジェクトを設定し、スカラコンテキストではundef、リストコンテキストでは空リストを返します。例外オブジェクトはその後"error"で取得できます。

categories

# エラーも確認します
my $categories    = DateTime::Lite::TimeZone->categories ||
    die( DateTime::Lite::TimeZone->error );
my( @categories ) = DateTime::Lite::TimeZone->categories ||
    die( DateTime::Lite::TimeZone->error );
my $categories    = $zone->categories ||
    die( $zone->error );
my( @categories ) = $zone->categories ||
    die( $zone->error );

これはインスタンスメソッドとしても、クラス関数としても呼び出せます。

すべてのタイムゾーンカテゴリのリストを返します。categoryとは、ゾーン名のスラッシュより前にある部分が存在する場合、その部分を指します。たとえばAsia/Tokyoでは、categoryはAsiaになります。ただし、特別なゾーンFactoryにはcategoryはありません。

スカラコンテキストでは配列リファレンスを返し、リストコンテキストでは配列を返します。

エラーが発生した場合は例外オブジェクトを設定し、スカラコンテキストではundef、リストコンテキストでは空リストを返します。例外オブジェクトはその後"error"で取得できます。

category

my $zone = DateTime::Lite::TimeZone->new( name => "Asia/Tokyo" );
say $zone->category; # Asia
my $zone = DateTime::Lite::TimeZone->new( name => "UTC" );
say $zone->category; # undef

タイムゾーン名の最初のスラッシュより前の部分を返します。たとえばAsia/TokyoではAsiaです。

comment

zone1970.tabに由来する任意のゾーンコメントを返します。たとえば"Mountain Time - south Idaho and east Oregon"のような値です。

コメントが記録されていない場合は、スカラコンテキストではundef、リストコンテキストでは空リストを返します。

coordinates

zone1970.tabに由来するコンパクトな座標文字列を返します。たとえば東京の場合は+3518+13942です。 UTCfloating、固定オフセットゾーンのように座標が存在しない場合は、スカラコンテキストではundef、リストコンテキストでは空リストを返します。

country_codes

このタイムゾーンに関連付けられたISO 3166-1 alpha-2国コードの配列リファレンスを返します。たとえば["JP"]または["US","CA"]です。

UTCfloating、固定オフセットゾーンのように、このタイムゾーンに関連付けられた国がない場合は、スカラコンテキストではundef、リストコンテキストでは空リストを返します。

countries

# エラーも確認します
my $countries    = DateTime::Lite::TimeZone->countries ||
    die( DateTime::Lite::TimeZone->error );
my( @countries ) = DateTime::Lite::TimeZone->countries ||
    die( DateTime::Lite::TimeZone->error );
my $countries    = $zone->countries ||
    die( $zone->error );
my( @countries ) = $zone->countries ||
    die( $zone->error );

これはインスタンスメソッドとしても、クラス関数としても呼び出せます。

ISO 3166の2文字国コードをすべて、アルファベット順かつ小文字で並べたリストを返します。これらのコードは"names_in_country"の呼び出しに使用できます。

スカラコンテキストでは配列リファレンスを返し、リストコンテキストでは配列を返します。

エラーが発生した場合は例外オブジェクトを設定し、スカラコンテキストではundef、リストコンテキストでは空リストを返します。例外オブジェクトはその後"error"で取得できます。

国コードをローカライズされた国名へ変換したい場合は、そのために設計されたUnicode CLDR databaseを使用できます。

たとえばlocale enを使う場合:

use Locale::Unicode::Data;
my $cldr = Locale::Unicode::Data->new;
my $ref  = $cldr->territory_l10n( locale => 'en', territory => 'JP', alt => undef );

# 次のようなハッシュリファレンスを返します:
{
   terr_l10n_id    => 13385,
   locale          => 'en',
   territory       => 'JP',
   locale_name     => 'Japan',
   alt             => undef,
}

また、ローカライズされた国名からISO3166コードを検索したい場合は、次のようにできます。ここでは、日本語でAmericaを意味するアメリカに一致する国コードを検索しています。

use strict;
use warnings;
use utf8;
use open ':std' => ':utf8';
use Data::Pretty qw( dump );
use Locale::Unicode::Data;
my $cldr = Locale::Unicode::Data->new;
my $all = $cldr->territories_l10n( locale => 'ja' );
foreach my $ref ( @$all )
{
    if( $ref->{locale_name} =~ /アメリカ/ &&
        $ref->{territory} =~ /^[A-Z]{2}$/ ) # Unicode CLDR では territory が 3 桁コードの場合もあるため
    {
        say dump( $ref );
    }
}

これは次のような出力を生成します。

{
    alt => undef,
    locale => "ja",
    locale_name => "アメリカ合衆国",
    terr_l10n_id => 26334,
    territory => "US",
}

datafile

同梱されているtz.sqlite3データベースファイルへの絶対パスを返します。

designation_charcount

略称文字列テーブルの合計サイズをバイト単位で返します。

これはTZifヘッダーフィールドcharcntに相当し、末尾のNULバイトも含みます。

rfc9636, section 3.1を参照してください。

error

my $ex = $zone->error;

直近の例外オブジェクトがあれば、それを返します。

extended_aliases

my $aliases = DateTime::Lite::TimeZone->extended_aliases;
my $aliases = $tz->extended_aliases;

# エラーも確認します
my $aliases  = DateTime::Lite::TimeZone->extended_aliases ||
    die( DateTime::Lite::TimeZone->error );
my( %aliases ) = DateTime::Lite::TimeZone->extended_aliases ||
    die( DateTime::Lite::TimeZone->error );
my $aliases    = $zone->extended_aliases ||
    die( $zone->error );
my( %aliases ) = $zone->extended_aliases ||
    die( $zone->error );

これはインスタンスメソッドとしても、クラス関数としても呼び出せます。

すべての拡張ゾーンエイリアスから、それぞれ対応する正規名へのハッシュを返します。

例:

JST -> Asia/Tokyo

スカラコンテキストではハッシュリファレンスを返し、リストコンテキストではハッシュを返します。

エラーが発生した場合は例外オブジェクトを設定し、スカラコンテキストではundef、リストコンテキストでは空リストを返します。例外オブジェクトはその後"error"で取得できます。

fatal

このオブジェクトのfatalプロパティを設定または取得します。

有効化されている場合、任意のエラーはfatal exceptionを発生させ、"die" in perlfuncを呼び出します。

タイムゾーンのfooter部分を返します。

rfc9636, section 3.3を参照してください。

has_dst

"has_dst_changes"のエイリアスです。

has_dst_changes

このタイムゾーンが夏時間の遷移を持つ場合に真を返します。

is_canonical

my $zone = DateTime::Lite::TimeZone->new( 'Japan' );
say $zone->is_canonical; # false
my $zone = DateTime::Lite::TimeZone->new( 'Asia/Tokyo' );
say $zone->is_canonical; # true

指定されたタイムゾーン名が正規名であれば真を返し、そうでなければ偽を返します。

is_dst_for_datetime( $dt )

$dtがこのタイムゾーンにおけるDST期間内にある場合に真を返します。

is_floating

特別なfloatingタイムゾーンであれば真を返します。

is_olson

IANA/Olson由来のタイムゾーンであれば真を返します。

is_utc

UTCタイムゾーン、または固定オフセット+0000であれば真を返します。

is_valid_name

say DateTime::Lite::TimeZone->is_valid_name( 'Singapore' );  # true
say $zone->is_valid_name( 'Singapore' );                     # true
say DateTime::Lite::TimeZone->is_valid_name( 'Paris' );      # false
say $zone->is_valid_name( 'Paris' );                         # false
say DateTime::Lite::TimeZone->is_valid_name( 'Asia/Seoul' ); # true
say $zone->is_valid_name( 'Asia/Seoul' );                    # true

正規タイムゾーン名またはタイムゾーンエイリアスを受け取り、指定された値が有効であれば真を、そうでなければ偽を返します。

値が渡されなかった場合にのみ例外オブジェクトを設定してエラーを返します。そのため、戻り値が定義されているか確認した方がよい場合があります。

DateTime::TimeZoneとは異なり、DateTime::TimeZone::Aliasを渡しても、そのゾーンが有効になるわけではありません。このクラスはIANAタイムゾーンに厳密に従います。

isstd_count

standard time(別名 “standard/wall”)インジケータの数を返します。

これは「0であるか、またはtypecntと等しくなければなりません」。

rfc9636, section 3.1を参照してください。

isut_count

UT/local timeインジケータの数を返します。

これは「0であるか、またはtypecntと等しくなければなりません」。

rfc9636, section 3.1を参照してください。

latitude

このゾーンの緯度が存在する場合、実数として返します。

"aliases"のエイリアスです。

longitude

このゾーンの経度が存在する場合、実数として返します。

name

my $zone = DateTime::Lite::TimeZone->new( name => 'Japan' );
say $zone->name; # Asia/Tokyo

Asia/Tokyoのような正規タイムゾーン名を返します。

これは、インスタンス化時にエイリアスを指定した場合、それが解決され、このメソッドからアクセスできることを意味します。

names_in_category

# エラーも確認します
my $names    = DateTime::Lite::TimeZone->names_in_category( 'Asia' ) ||
    die( DateTime::Lite::TimeZone->error );
my( @names ) = DateTime::Lite::TimeZone->names_in_category( 'Asia' ) ||
    die( DateTime::Lite::TimeZone->error );
my $names    = $zone->names_in_category( 'America' ) ||
    die( $zone->error );
my( @names ) = $zone->names_in_category( 'America' ) ||
    die( $zone->error );

これはcategoryを受け取ります。このクラスでは、categoryとは、スラッシュで区切られたゾーン名の左側の部分を意味します。したがって、Asia/Seoulの例では、categoryAsiaになります。

このcategoryが指定されると、最初のスラッシュの右側にある名前のリストを返します。

例:

Asia/Taipeiの場合、categoryはAsiaであり、返される74件の結果の中にはTaipeiという名前が含まれます。

category Americaの場合は121件の結果があり、その中には完全なタイムゾーン名がAmerica/Indiana/VincennesであるIndiana/Vincennesも含まれます。

スカラコンテキストでは配列リファレンスを返し、リストコンテキストでは配列を返します。

エラーが発生した場合は例外オブジェクトを設定し、スカラコンテキストではundef、リストコンテキストでは空リストを返します。例外オブジェクトはその後"error"で取得できます。

names_in_country

# エラーも確認します
my $names    = DateTime::Lite::TimeZone->names_in_country( 'US' ) ||
    die( DateTime::Lite::TimeZone->error );
my( @names ) = DateTime::Lite::TimeZone->names_in_country( 'US' ) ||
    die( DateTime::Lite::TimeZone->error );
my $names    = $zone->names_in_country( 'US' ) ||
    die( $zone->error );
my( @names ) = $zone->names_in_country( 'US' ) ||
    die( $zone->error );

2文字のISO3166国コードを受け取り、それに関連付けられたすべてのタイムゾーンのリストを返します。

大文字小文字は区別されないため、USusのような国コードは同じように扱われます。

スカラコンテキストでは配列リファレンスを返し、リストコンテキストでは配列を返します。

エラーが発生した場合は例外オブジェクトを設定し、スカラコンテキストではundef、リストコンテキストでは空リストを返します。例外オブジェクトはその後"error"で取得できます。

返されるタイムゾーンの順序は、IANAデータベースで設定されている順序と同じです。

offset_as_seconds

+09:00のようなオフセット文字列を受け取り、そのオフセットが表す秒数を符号付き整数として返します。

値が渡されなかった場合、その値が-99:59:59から+99:59:59の範囲に含まれない場合、または渡されたオフセット文字列が次の2つのパターンのいずれにも一致しない場合、エラーオブジェクトを設定し、スカラコンテキストではundef、リストコンテキストでは空リストを返します。

サポートされるオフセットパターンは次のとおりです(符号が省略された場合、デフォルトは+です)。

コロン形式:[+-]H:MM, [+-]HH:MM, [+-]HH:MM:SS

正規表現は次のとおりです:\A([+-])?(\d{1,2}):(\d{2})(?::(\d{2}))?\z

例:+09:00, -02:00, 9:0:0

コンパクト形式:[+-]HHMM, [+-]HHMMSS

正規表現は次のとおりです:/\A([+-])?(\d{2})(\d{2})(\d{2})?\z/

例:+0900, -0200, 0900, +090000, 090000

特別な文字列"0"0を返します)。

offset_as_string

say DateTime::Lite::TimeZone->offset_as_string(32400);       # +0900
say DateTime::Lite::TimeZone->offset_as_string(32400, ':' ); # +09:00
say $zone->offset_as_string(32400);                          # +0900
say $zone->offset_as_string(32400, ':');                     # +09:00

クラスメソッドまたはインスタンスメソッドです。秒単位の数値UTCオフセットを、+0900(デフォルト)または:を区切り文字とする+09:00のような書式付き文字列へ変換します。

"offset_as_string" in DateTime::TimeZoneとドロップイン互換です。

offset_for_datetime

my $offset = $zone->offset_for_datetime( $dt );

DateTime::Liteオブジェクトを受け取り、そのオブジェクトに適用されるUTCオフセットを秒単位で返します。

エラー時にはエラーオブジェクトを設定し、スカラコンテキストではundef、リストコンテキストでは空リストを返します。

offset_for_local_datetime

my $offset = $zone->offset_for_local_datetime( $dt );

DateTime::Liteオブジェクトを受け取り、ローカル時刻(壁時計時刻)に対するUTCオフセットを秒単位で返します。

タイムゾーン変換時に内部で使用されます。

エラー時にはエラーオブジェクトを設定し、スカラコンテキストではundef、リストコンテキストでは空リストを返します。

resolve_abbreviation

# 曖昧ではない例: JST は単一の UTC オフセットへ対応します
# 結果は is_active DESC, first_trans_time ASC, last_trans_time DESC, name ASC でソートされます。
my $results = DateTime::Lite::TimeZone->resolve_abbreviation( 'JST' );
# $results = [
#     {
#         ambiguous        => 0,
#         extended         => 0,
#         first_trans_time => -2587712400,
#         is_active        => 1,
#         is_dst           => 0,
#         last_trans_time  => -577962000,
#         utc_offset       => 32400,
#         zone_name        => "Asia/Tokyo",
#     },
#     {
#         ambiguous        => 0,
#         extended         => 0,
#         first_trans_time => -1830414600,
#         is_active        => 0,
#         is_dst           => 0,
#         last_trans_time  => -1830414600,
#         utc_offset       => 32400,
#         zone_name        => "Asia/Pyongyang",
#     },
#     # etc...
# ]

# 本当に曖昧な例: CST はアジアとアメリカで異なるオフセットを持ちます
my $cst = DateTime::Lite::TimeZone->resolve_abbreviation( 'CST' );
# $cst->[0]{ambiguous} == 1

# オフセットが既に分かっている場合に絞り込みます(同時に解析された %z トークンなど)
my $filtered = DateTime::Lite::TimeZone->resolve_abbreviation(
    'PST', utc_offset => -28800
);

# 期間フィルタ: 1950 年以降に JST を使用していたゾーンのみ
my $modern = DateTime::Lite::TimeZone->resolve_abbreviation(
    'JST', period => '>1950-01-01'
);

# 2 つの境界を持つ期間フィルタ: 第二次世界大戦中に JST を使用していたゾーン
my $wartime = DateTime::Lite::TimeZone->resolve_abbreviation(
    'JST', period => ['>1941-01-01', '<1946-01-01']
);

# 期間フィルタ: 現在この略称を使用しているゾーンのみ
my $current = DateTime::Lite::TimeZone->resolve_abbreviation(
    'JST', period => 'current'
);

# 拡張モード: IANA types にない場合は extended_aliases にフォールバックします
my $aft = DateTime::Lite::TimeZone->resolve_abbreviation(
    'AFT', extended => 1
);
# $aft = [
#   { zone_name => 'Asia/Kabul', utc_offset => undef, is_dst => undef,
#     ambiguous => 0, is_primary => 1, extended => 1 },
# ]

# extended => 1 は、IST や CST のように既に IANA types に存在する略称では何もしません。
# IANA の結果が返され、extended_aliases テーブルは参照されません。

クラスメソッドまたはインスタンスメソッドです。JSTESTのようなタイムゾーン略称を、同梱のtz.sqlite3データベース内のIANAデータに対して解決し、その略称を過去に使用したことのあるすべての正規ゾーンを返します。

IANAの結果は、4段階のキーでソートされます。

1. is_active降順:POSIX footerが現在もその略称を参照しているゾーンが、既に使用しなくなったゾーンより先に来ます。
2. first_trans_time昇順:同じis_active値を持つゾーンの中では、その略称を最も早く採用したゾーンが先に来ます。
3. last_trans_time降順:最初の2つのキーが同じゾーンの中では、その略称を最も最近まで使用していたゾーンが先に来ます。
4. zone_name昇順:最後の決定的なタイブレーカーです。

実際には、CESTのような略称では、現在も有効な中央ヨーロッパのゾーンが先に来ます(採用日の順)。その後に、Europe/Kaliningradのように、後にCESTから移行したゾーンが続きます。Europe/Kaliningradは2014年にCESTを廃止しました。

extended aliasの結果(extended => 1によりextended_aliasesテーブルへフォールバックした場合)は、異なる順序を使用します:is_primary降順、その後zone_name昇順です。下記の"is_primary"を参照してください。

唯一必須の引数は略称文字列です。次の任意のキーワード引数を受け付けます。

extended

真偽値です。真で、略称がIANA typesテーブルに見つからない場合、このメソッドはextended_aliasesテーブルの問い合わせへフォールバックします。これにより、AFT, AMST, HAECのような、日付文字列には現れるもののIANAデータベースのTZif type略称としては保存されていない実世界の略称を扱えます。

extendedの結果が返される場合、extended_aliasesテーブルは略称をゾーン名へ対応付けるだけなので、utc_offsetis_dstundefになります。オフセットが必要な場合は、返されたzone_nameからDateTime::Lite::TimeZoneオブジェクトを生成してください。

period

直近の一致する遷移(MAX(trans_time))が指定された時間範囲に含まれるゾーンに結果を制限します。単一の文字列、または複数条件用の文字列配列リファレンスを受け付けます。

各値には比較演算子を接頭辞として付けることができます。

>(演算子がない場合のデフォルト)

より大きい。最も一般的な演算子です。指定された日付よりも最近にその略称を使用したゾーンを返します。

>=

以上。

<

より小さい。その略称の最後の使用が指定日より古いゾーンを返します。

<=

以下。

演算子=!=も受け付けますが、それぞれSQLのISIS NOTに対応します。タイムスタンプ比較では実用性がなく、推奨されません。

値の型: 1950-01-01のようなISO日付文字列は、SQLiteのstrftime('%s', ...)によりUnix epochへ変換されます。通常の整数はepoch秒として扱われ、Perlスカラの内部表現に関係なく正しい数値比較を行うため、CAST(? AS INTEGER)として渡されます。可搬性のため、生の整数を渡す場合は1970年以降のepoch値を使用してください。1970年以前の負の値は、一部のプラットフォームで予期しない挙動をする可能性があります。

特別な値currentは、その略称の直近の使用が過去にあり、かつ次に予定されている遷移がまだ発生していないゾーンのみを返します。つまり、現在その略称を使用しているゾーンを意味します。

period => '>1950-01-01'                   # 1950 年以降に最後に使用されたもの(ISO 日付)
period => ['>1941-01-01', '<1946-01-01']  # 第二次世界大戦中の範囲で最後に使用されたもの
period => '>1262304000'                   # 2010-01-01 以降に最後に使用されたもの(epoch int)
period => 'current'                       # 現在有効なもののみ

periodフィルタはextended aliasの結果には適用されません。

utc_offset

UTCの東側を正とする整数秒です。同じ文字列から一緒に解析された数値オフセット(たとえば%zトークン由来)が既に分かっている場合に、結果を一致するオフセットの候補へ絞り込めます。IANA types lookupにのみ適用され、extended aliasesフォールバックには使用されません。

成功時には、次のキーを持つハッシュリファレンスの配列リファレンスを返します。

zone_name

Asia/Tokyoのような正規IANAゾーン名です。

utc_offset

このゾーンでこの略称が表す、UTCの東側を正とするUTCオフセット秒数です。extended aliasの結果ではundefです。

is_dst

この略称がDST期間を表す場合は1、そうでなければ0です。extended aliasの結果ではundefです。

ambiguous

IANAの結果では、この略称が複数の異なるUTCオフセットへ対応する場合(ISTCSTのような真の曖昧性)は1、すべての候補が同じUTCオフセットを共有する場合は0です。

extended aliasの結果では、候補が複数あり、かつis_primaryとして印が付いた候補が0個または複数ある場合に1、ちょうど1つの候補がis_primary = 1を持つ場合に0です。

extended

結果がextended_aliasesテーブル由来であれば1、IANA typesテーブル由来であれば0です。

is_active

IANAの結果(extended => 0)にのみ存在します。ゾーンのPOSIX TZ footer文字列が現在もこの略称を参照している場合は1です。これは、そのゾーンが現在の夏時間規則の下でこの略称を循環的に使い続けている、または恒久的な略称として使っていることを意味します。footerがその略称をもはや含まない場合は0で、通常はそのゾーンがその略称から移行したことを意味します。

たとえばEurope/BerlinのfooterはCET-1CEST,M3.5.0,M10.5.0/3なので、CETCESTはどちらもis_active => 1になります。対照的に、Europe/KaliningradのfooterはEET-2です。そのため、resolve_abbreviation('CEST')はKaliningradも一覧に含めます(2014年までCESTを使用していたため)が、is_active => 0になります。

このフィールドは主要なソートキーとして使用されるため、is_active => 1のゾーンはis_active => 0のゾーンより先に表示されます。現在有効なゾーンのみが必要な呼び出し元は、grep { $_->{is_active} } @$resultsでフィルタできます。

検出はfooter文字列に対する単語境界正規表現です。アルファベット略称は非アルファベット文字に隣接していなければなりません(そのためCSTCESTに一致しません)。また、-03+0430のような数値または符号付きの略称は、POSIX TZ構文に従って<...>の中に現れる必要があります。この正規表現は、同梱データベース内の1449個すべての(zone, abbreviation)ペアに対して検証され、経験的なground truthに対するfalse negativeは0でした。詳細に興味がある場合は、内部文書RESOLVE_ABBREVIATION_DESIGN_NOTES.mdを参照してください。

extended aliasの結果には存在しません。そこでは代わりに編集上のis_primaryマーカーが順序付けのシグナルになります。

is_primary

extended aliasの結果(extended => 1)にのみ存在します。複数の候補が一致する場合、1はその略称に対して編集上選ばれた正規ゾーン(たとえばBRTに対するAmerica/Sao_Paulo)を示し、0はその他を示します。IANAの結果には存在しません。略称のIANA候補の中で単一のゾーンが正規に指定されているわけではないためです。IANAの結果では、is_activeマーカーとソート順(最初に使用されたものを優先し、現在も有効なものを優先)が類似の役割を果たします。

CLDR的な意味での正規または優先ゾーン指定が必要な場合は、Locale::Unicode::Dataを使用してください。これはタイムゾーンごとにCLDRのis_golden, is_primary, is_preferredフラグを公開しています。例については、下記の"正規指定にLocale::Unicode::Dataを使用する"を参照してください。

first_trans_time

このゾーンでその略称を使用した最も古い遷移のUnix epochです。extended aliasの結果には存在しません。is_activeの後、昇順のソートキーとして使用されます。そのため、同じis_active値を持つゾーンの中では、その略称を最初に採用したゾーンが先に表示されます。

last_trans_time

このゾーンでその略称を使用した最も新しい遷移のUnix epochです。extended aliasの結果には存在しません。降順の副次ソートキーとして使用されます。同じis_activeおよび同じfirst_trans_timeを持つゾーンの中では、その略称を最も最近まで使用していたゾーンが先に表示されます。

エラーが発生した場合は例外オブジェクトを設定し、スカラコンテキストではundef、リストコンテキストでは空リストを返します。例外オブジェクトはその後"error"で取得できます。

ESTPSTのような多くの略称は、同じUTCオフセットを共有する複数のゾーン名に一致する点に注意してください。これらはdatetime文字列の解析という目的では真に曖昧ではありません。そのような場合、ambiguousフラグは0になります。IST(Irish Summer Time、Indian Standard Time、Israel Standard Time)のような真に曖昧な略称では、ambiguous => 1になります。

クラスメソッドまたはインスタンスメソッドです。JSTESTのようなタイムゾーン略称を、同梱されているtz.sqlite3データベース内のIANAデータに照合し、その略称を過去に使用したことのあるすべての正規ゾーンを返します。

IANAの結果は、次の4段階のキーでソートされます。

1. is_activeの降順:POSIX footerが現在もその略称を参照しているゾーンが、すでに使用しなくなったゾーンより先に表示されます。
2. first_trans_timeの昇順:同じis_active値を持つゾーンの中では、その略称を最も早く採用したゾーンが先に表示されます。
3. last_trans_timeの降順:最初の2つのキーが同じゾーンの中では、その略称をより最近まで使用していたゾーンが先に表示されます。
4. zone_nameの昇順:最後の決定的なタイブレークです。

実際には、CESTのような略称では、現在も有効な中央ヨーロッパのゾーンが先に表示されます(採用日の順)。その後に、Europe/Kaliningradのように、過去にはCESTを使用していたものの、2014年に使用をやめたゾーンが続きます。

拡張エイリアスの結果(extended => 1によりextended_aliasesテーブルへフォールバックした場合)は、異なる順序を使用します。is_primaryの降順、次にzone_nameの昇順です。下記の"is_primary"を参照してください。

必須引数は略称文字列1つです。次の任意のキーワード引数を受け付けます。

extended

真偽値です。真の場合で、略称がIANA typesテーブルに見つからないとき、このメソッドはextended_aliasesテーブルの検索にフォールバックします。これは、AFT, AMST, HAECのように、実際の日時文字列には現れるものの、IANAデータベース内のTZif type略称としては保存されていない現実世界の略称を扱うためのものです。

拡張結果が返される場合、utc_offsetis_dstundefになります。これは、拡張エイリアステーブルが略称をゾーン名に対応付けるだけだからです。オフセットが必要な場合は、返されたzone_nameからDateTime::Lite::TimeZoneオブジェクトを生成してください。

period

結果を、最も新しい一致する遷移時刻(MAX(trans_time))が指定された時間範囲内にあるゾーンに限定します。単一の文字列、または複数条件用の文字列の配列リファレンスを受け付けます。

各値には比較演算子を前置できます。

>(演算子がない場合のデフォルト)

より大きい。最も一般的な演算子です。略称の最後の使用時刻が、指定された日付より新しいゾーンを返します。

>=

以上。

<

より小さい。最後の使用時刻が、指定された日付より古いゾーンを返します。

<=

以下。

演算子=!=も受け付けますが、それぞれSQLのISIS NOTに対応します。タイムスタンプ比較では実用的な意味がなく、推奨されません。

値の型: 1950-01-01のようなISO日付文字列は、SQLiteのstrftime('%s', ...)によってUnix epochに変換されます。単なる整数はepoch秒として扱われ、Perlスカラーの内部表現にかかわらず正しい数値比較を行うためにCAST(? AS INTEGER)として渡されます。移植性のため、生の整数を渡す場合は1970年以降のepoch値を使用してください。1970年より前の負の値は、一部のプラットフォームで予期しない挙動になる可能性があります。

特別な値currentは、その略称の最も新しい使用時刻が過去にあり、かつ次に予定されている遷移がまだ発生していないゾーンだけを返します。つまり、現在その略称を使用しているゾーンを意味します。

period => '>1950-01-01'                   # 1950 年以降に最後に使用されたもの(ISO 日付)
period => ['>1941-01-01', '<1946-01-01']  # 第二次世界大戦中の範囲で最後に使用されたもの
period => '>1262304000'                   # 2010-01-01 以降に最後に使用されたもの(epoch 整数)
period => 'current'                       # 現在有効なもののみ

期間フィルタは、拡張エイリアスの結果には適用されません。

utc_offset

UTCの東方向を正とする整数秒です。結果を、一致するオフセットを持つ候補に絞り込みます。これは、同じ文字列から数値オフセットもすでに解析済みの場合(たとえば同時に解析された%zトークンから得られた場合)に便利です。IANA typesの検索にのみ適用され、拡張エイリアスへのフォールバックでは使用されません。

成功時には、ハッシュリファレンスの配列リファレンスを返します。各ハッシュには次のキーが含まれます。

zone_name

Asia/Tokyoのような正規IANAゾーン名です。

utc_offset

このゾーンでこの略称が表す、UTCの東方向を正とするUTCオフセット秒です。拡張エイリアスの結果ではundefです。

is_dst

この略称が夏時間期間を表す場合は1、そうでない場合は0です。拡張エイリアスの結果ではundefです。

ambiguous

IANAの結果では、この略称が複数の異なるUTCオフセットに対応する場合(ISTCSTのような真の曖昧性)は1です。すべての候補が同じUTCオフセットを共有する場合は0です。

拡張エイリアスの結果では、候補が複数あり、is_primaryが付いた候補が1つもない、または複数ある場合は1です。is_primary = 1の候補がちょうど1つだけある場合は0です。

extended

この結果がextended_aliasesテーブル由来であれば1、IANA typesテーブル由来であれば0です。

is_active

IANAの結果(extended => 0)にのみ存在します。そのゾーンのPOSIX TZ footer文字列が現在もこの略称を参照している場合は1です。これは、そのゾーンが現在の夏時間規則のもとで引き続きこの略称を周期的に使用している、または恒久的な略称として使用していることを意味します。footerがその略称をもう含んでいない場合は0です。通常これは、そのゾーンがその略称から移行済みであることを意味します。

たとえば、Europe/BerlinのfooterはCET-1CEST,M3.5.0,M10.5.0/3なので、CETCESTのどちらもis_active => 1になります。一方、Europe/KaliningradのfooterはEET-2なので、resolve_abbreviation('CEST')はKaliningradを一覧に含めます(2014年までCESTを使用していたため)が、is_active => 0になります。

このフィールドは主ソートキーとして使用されるため、is_active => 1のゾーンはis_active => 0のゾーンより前に表示されます。現在有効なゾーンだけが必要な呼び出し側は、grep { $_->{is_active} } @$resultsでフィルタできます。

検出はfooter文字列に対する単語境界の正規表現で行われます。アルファベット略称は非アルファベット文字に隣接している必要があります(そのためCSTCESTに一致しません)。また、数値または符号付きの略称(-03, +0430など)は、POSIX TZ構文に従って<...>の中に現れる必要があります。この正規表現は、同梱データベース内の1449個の(zone, abbreviation)ペアすべてに対して検証され、経験的な正解データに対するfalse negativeは0件でした。詳細に興味があれば、内部文書RESOLVE_ABBREVIATION_DESIGN_NOTES.mdを参照してください。

拡張エイリアスの結果には存在しません。そこでは、編集上のis_primaryマーカーが順序付けのシグナルになります。

is_primary

拡張エイリアスの結果(extended => 1)にのみ存在します。複数の候補が一致する場合、1はこの略称に対して編集上選ばれた正規ゾーンを示します(たとえばBRTに対するAmerica/Sao_Paulo)。0はその他の候補を示します。IANAの結果には存在しません。略称のIANA候補の中で、単一のゾーンが正規として指定されることはないためです。IANAの結果では、is_activeマーカーとソート順(最初に使用されたものを優先し、現在も有効なものを優先)が、これに類似した役割を果たします。

CLDR的な意味での正規または優先ゾーン指定が必要な場合は、Locale::Unicode::Dataを使用してください。このモジュールは、タイムゾーンごとにCLDRのis_golden, is_primary, is_preferredフラグを公開しています。例については、下記の"USING Locale::Unicode::Data FOR CANONICAL DESIGNATION"を参照してください。

first_trans_time

このゾーンでその略称を使用した最も古い遷移のUnix epochです。拡張エイリアスの結果には存在しません。is_activeの後に昇順のソートキーとして使用されるため、同じis_active値を持つゾーンの中では、その略称を最も早く採用したゾーンが先に表示されます。

last_trans_time

このゾーンでその略称を使用した最も新しい遷移のUnix epochです。拡張エイリアスの結果には存在しません。二次ソートキーとして降順で使用されます。つまり、is_activefirst_trans_timeが同じゾーンの中では、その略称をより最近まで使用していたゾーンが先に表示されます。

エラーが発生した場合、このメソッドは例外オブジェクトを設定し、スカラーコンテキストではundef、リストコンテキストでは空リストを返します。その後、例外オブジェクトは"error"で取得できます。

ESTPSTのような多くの略称は、すべて同じUTCオフセットを共有する複数のゾーン名に一致することに注意してください。これらは日時文字列の解析という目的では真に曖昧ではありません。そのため、そのような場合ambiguousフラグは0になります。IST(Irish Summer Time, Indian Standard Time, Israel Standard Time)のような真に曖昧な略称では、ambiguous => 1になります。

short_name_for_datetime

say $zone->short_name_for_datetime( $dt );

DateTime::Liteオブジェクトを受け取り、JSTEDTのような、該当する省略形のタイムゾーン名を返します。

transition_count

このタイムゾーンの遷移レコード数を返します。

TZifヘッダーフィールドtimecntに相当します。

rfc9636, section 3.1を参照してください。

type_count

このタイムゾーンのtype数を返します。

rfc9636, section 3.1を参照してください。

tz_version

データベースのmetadataテーブルから、2026aのようなIANA tzdataバージョン文字列を返します。

tzif_version

タイムゾーンデータのTZifバージョン文字列を返します。

可能な値は1, 2, 3, 4です。

rfc9636, section 3.1を参照してください。

正規指定のためにLocale::Unicode::Dataを使用する

"resolve_abbreviation"が、ある略称に対して複数のIANA候補を返す場合(たとえばCESTに一致する30個のゾーンなど)、その結果セットにはis_primaryマーカーは含まれません。DateTime::Lite::TimeZoneは、IANA候補の中から正規ゾーンを選ぼうとは意図的にしていません。どの略称にも満足に適用できる単一のヒューリスティックは存在しないためです。

Locale::Unicode::Dataは、CLDR独自の正規指定フラグ(is_golden, is_primary, is_preferred, is_canonical)をタイムゾーンごとに公開しています。単一の代表ゾーンが必要な場合は、これを信頼できる情報源として使うことを推奨します。典型的な使い方は、まずここで略称を解決し、その候補の中でどれがCLDRのgolden zoneであるかをLocale::Unicode::Dataに問い合わせる、というものです。

use DateTime::Lite::TimeZone;
use Locale::Unicode::Data;

my $candidates = DateTime::Lite::TimeZone->resolve_abbreviation( 'CEST' );
my $cldr       = Locale::Unicode::Data->new;

my $golden;
foreach my $c ( @$candidates )
{
    my $info = $cldr->timezone( timezone => $c->{zone_name} ) || next;
    if( $info->{is_golden} )
    {
        $golden = $c->{zone_name};
        last;
    }
}
# $golden は現在 'Europe/Paris' です
# ('Europe_Central' メタゾーンに対する CLDR golden zone)

別の方法として、その略称が特定のメタゾーンに対応することが分かっている場合は、golden zoneを直接問い合わせることもできます。

my $zones  = $cldr->timezones( metazone => 'Europe_Central', is_golden => 1 );
my $golden = $zones->[0]->{timezone};  # 'Europe/Paris'

IANA typesテーブルに含まれていない略称(BRT, HAEC, AFTなど多数)については、extendedフラグ付きで"resolve_abbreviation"を使用してください。extended_aliasesテーブルには、候補の中で優先されるゾーンを示す独自の編集上のis_primaryマーカーがあります。

エラー処理

エラーが発生した場合、このクラスのメソッドは例外オブジェクトを設定し、スカラーコンテキストではundef、リストコンテキストでは空リストを返します。例外は次のように取得できます。

my $err = DateTime::Lite::TimeZone->error;   # クラスメソッド
my $err = $tz->error;                        # インスタンスメソッド

例外オブジェクトは、ソースファイル名と行番号を含む、人間が読めるメッセージへ文字列化されます。

インスタンスオプションfatalが有効になっている場合、発生したエラーはすべてfatalになります。

EPOCHの規約

tz.sqlite3データベースは、span境界をUnix秒(1970-01-01T00:00:00 UTCからの秒数)として保存します。これはTZifバイナリファイル内の生の値と一致します。DateTime::LiteはRata Die秒(0001-01-01T00:00:00からの秒数)を使用します。

変換定数は次のとおりです。

UNIX_TO_RD = 62_135_683_200

すべての検索メソッドは、データベースに問い合わせる前に$dt->utc_rd_as_secondsからUNIX_TO_RDを差し引きます。NULLのspan境界は ±無限大(最初に記録された遷移より前、および最後の遷移より後)を表します。

データベースの構築

同梱されているtz.sqlite3は、次を実行して生成されます。

perl scripts/build_tz_database.pl [--verbose, --debug 3]

このスクリプトは、IANAから最新のtzcodeおよびtzdataリリースを取得し、GPG署名を検証し、zic(1)でコンパイルして、データベースに投入します。tzdataの各リリースごとにこのスクリプトを一度実行し、更新されたlib/DateTime/Lite/tz.sqlite3をコミットしてください。

SQLスキーマ

SQLiteのSQLスキーマは、ファイルscripts/tz_schema.sqlにあります。

データは、scripts/build_tz_database.plにあるスクリプトと、https://ftp.iana.org/tz/releasesから取得できるデータを使ってSQLiteデータベースに投入されます。

SQLiteデータベースを作成するために使用されるSQLスキーマは、このディストリビューションのscriptsディレクトリ内のtz_schema.sqlファイルにあります。

使用されるテーブルは、アルファベット順で次のとおりです。

aliases

  • alias

    大文字小文字を区別しない文字列フィールドです。

  • zone_id

    整数フィールドです。

countries

  • code

    大文字小文字を区別しない文字列フィールドです。

  • name

    大文字小文字を区別しない文字列フィールドです。

extended_aliases

  • abbr_id

    整数フィールドです。

  • abbreviation

    大文字小文字を区別しない文字列フィールドです。

  • zone_id

    整数フィールドです。

  • is_primary

    真偽値フィールドです。

    デフォルトはfalseです。

  • comment

    文字列フィールドです。

leap_second

  • leap_sec_id

    整数フィールドです。

  • zone_id

    整数フィールドです。

  • leap_index

    整数フィールドです。

  • occurrence_time

    整数フィールドです。

  • correction

    整数フィールドです。

  • is_expiration

    真偽値フィールドです。

    デフォルトはfalseです。

metadata

  • key

    文字列フィールドです。

  • value

    文字列フィールドです。

spans

  • span_id

    整数フィールドです。

  • zone_id

    整数フィールドです。

  • type_id

    整数フィールドです。

  • span_index

    整数フィールドです。

  • utc_start

    整数フィールドです。

  • utc_end

    整数フィールドです。

  • local_start

    整数フィールドです。

  • local_end

    整数フィールドです。

  • offset

    整数フィールドです。

  • is_dst

    真偽値フィールドです。

    デフォルトはfalseです。

  • short_name

    大文字小文字を区別しない文字列フィールドです。

transition

  • trans_id

    整数フィールドです。

  • zone_id

    整数フィールドです。

  • trans_index

    整数フィールドです。

  • trans_time

    整数フィールドです。

  • type_id

    整数フィールドです。

types

  • type_id

    整数フィールドです。

  • zone_id

    整数フィールドです。

  • type_index

    整数フィールドです。

  • utc_offset

    整数フィールドです。

  • is_dst

    真偽値フィールドです。

  • abbreviation

    大文字小文字を区別しない文字列フィールドです。

  • designation_index

    整数フィールドです。

  • is_standard_time

    真偽値フィールドです。

  • is_ut_time

    真偽値フィールドです。

  • is_placeholder

    真偽値フィールドです。

    デフォルトはfalseです。

zones

  • zone_id

    整数フィールドです。

  • name

    大文字小文字を区別しない文字列フィールドです。

  • canonical

    真偽値フィールドです。

    デフォルトはtrueです。

  • has_dst

    真偽値フィールドです。

    デフォルトはfalseです。

  • countries

    文字列配列フィールドです。

  • coordinates

    文字列フィールドです。

  • latitude

    実数フィールドです。

  • longitude

    実数フィールドです。

  • comment

    文字列フィールドです。

  • tzif_version

    整数フィールドです。

  • footer_tz_string

    文字列フィールドです。

  • transition_count

    整数フィールドです。

  • type_count

    整数フィールドです。

  • leap_count

    整数フィールドです。

  • isstd_count

    整数フィールドです。

  • isut_count

    整数フィールドです。

  • designation_charcount

    整数フィールドです。

  • category

    大文字小文字を区別しない文字列フィールドです。

  • subregion

    大文字小文字を区別しない文字列フィールドです。

  • location

    大文字小文字を区別しない文字列フィールドです。

SEE ALSO

DateTime::Lite, DateTime::TimeZone, Locale::Unicode::Data

RFC 9636(The Time Zone Information Format (TZif))https://www.rfc-editor.org/rfc/rfc9636

タイムゾーン、メタゾーン、およびBCP47タイムゾーンデータの履歴情報については、Locale::Unicode::Dataを参照してください。

AUTHOR

Jacques Deguest <jack@deguest.jp>

COPYRIGHT & LICENSE

Copyright(c) 2026 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.