Moment Timezone ドキュメント

moment-timezoneを使用するには、[メールアドレス保護]+moment-timezone.js、およびmoment-timezoneデータが必要です。

便宜上、momentjs.com/timezone/には、すべてのゾーンデータまたはデータのサブセットを含むビルドが用意されています。

  • moment-timezone-with-data.jsは、サーバー環境(Node.js)に推奨され、使用可能なすべての年をカバーしています。
  • moment-timezone-with-data-10-year-range.jsは、ほとんどのブラウザ環境に推奨され、公開年から±5年をカバーしています。
  • moment-timezone-with-data-1970-2030.jsは60年間の範囲をカバーしており、より多くのデータが必要だが、完全なデータファイルの大きなファイルサイズを避けたい場合に適しています。

上記のファイルのいずれかを使用する場合でも、moment.jsは必要ですが、moment-timezone.jsは含まれているため、必要ありません。

Node.js

編集
npm install moment-timezone

Node.jsでは、すべてのデータがプリロードされています。データの読み込みには追加のコードは必要ありません。

var moment = require('moment-timezone');
moment().tz("America/Los_Angeles").format();

ECMAScriptネイティブモジュール形式(またはTypeScript)の場合

import moment from 'moment-timezone';
moment().tz("America/Los_Angeles").format();

注記:基本的なmomentライブラリをrequire/importする必要はありません。Moment Timezoneは自動的にmomentモジュールを読み込んで拡張し、変更されたインスタンスを返します。

npmyarnなどのパッケージマネージャーでは、複数のバージョンのmomentがインストールされる場合があります。moment-timezoneからのみインポートすることで、同じバージョンが常に一貫して使用されるようにすることができます。潜在的なバージョン管理の問題を解決するための手順を含む、より詳細な説明については、issue #982に関するこのコメントを参照してください。

// Unnecessary, can cause issues with package managers
import moment from 'moment';
import 'moment-timezone';

// Correct
import moment from 'moment-timezone';

プリビルドバンドルはこちらnpmパッケージにも含まれており、直接ロードできます。これにより、より小さなデータサブセットを使用してライブラリをインポートできます。

import moment from 'moment-timezone/builds/moment-timezone-with-data-10-year-range.js'; // or .min.js

プリロードされたデータなしでライブラリのみをインポートすることもできます。

import moment from 'moment-timezone/moment-timezone.js'; // or .min.js
moment.tz.load(customData);

ブラウザ

編集
<script src="moment.js"></script>
<script src="moment-timezone-with-data.js"></script>

ブラウザでMoment Timezoneを使用する場合は、データとライブラリの両方をロードする必要があります。

ホームページにリンクされているプリビルドのライブラリとデータファイルを使用するか、データのサブセットを自分でビルドしてロードすることができます。

moment().tz("America/Los_Angeles").format();

Require.js

編集
require.config({
    paths: {
        "moment": "path/to/moment"
    }
});
define(["path/to/moment-timezone-with-data"], function (moment) {
    moment().tz("America/Los_Angeles").format();
});

Webpack

編集
npm install moment-timezone
var moment = require('moment-timezone');
moment().tz("America/Los_Angeles").format();

注記:デフォルトでは、Webpackはすべてのmoment-timezoneデータ(moment-timezone 0.5.25では、900KB以上の縮小版)をバンドルします。不要なデータを削除し、必要なゾーンと日付範囲データのみをバンドルするには、moment-timezone-data-webpack-pluginパッケージを追加します。

// webpack.config.js
const MomentTimezoneDataPlugin = require('moment-timezone-data-webpack-plugin');
const currentYear = new Date().getFullYear();

module.exports = {
    plugins: [
        // To include only specific zones, use the matchZones option
        new MomentTimezoneDataPlugin({
            matchZones: /^America/
        }),

        // To keep all zones but limit data to specific years, use the year range options
        new MomentTimezoneDataPlugin({
            startYear: currentYear - 5,
            endYear: currentYear + 5,
        }),
    ],
};

あるいは、プリビルドバンドルnpmパッケージに含まれており、直接ロードできます。Node.jsセクションで詳細を参照してください。

また、Momentのバンドルされたロケールデータを削減する方法の例については、主要なMoment.js Webpackドキュメントも参照してください。これらの手法を組み合わせることで、最終的なバンドルサイズを大幅に削減できます(1MB以上の縮小版、または85KBの縮小版+gzip)。

Moment.jsでタイムゾーンを使用するためのインターフェースは2つあります。

moment.tz(..., String)は、指定されたタイムゾーンでのパースを行います。

これはmomentコンストラクタと同じ引数を取りますが、最後の引数をタイムゾーン識別子として使用します。

var a = moment.tz("2013-11-18 11:55", "Asia/Taipei");
var b = moment.tz("2013-11-18 11:55", "America/Toronto");

a.format(); // 2013-11-18T11:55:00+08:00
b.format(); // 2013-11-18T11:55:00-05:00

a.utc().format(); // 2013-11-18T03:55Z
b.utc().format(); // 2013-11-18T16:55Z

これらのモーメントは異なるタイムゾーンで作成されたため、UTC時間が異なることに注意してください。

moment().tz(String)は、指定されたタイムゾーンへの変換を行います。

var a = moment.utc("2013-11-18 11:55").tz("Asia/Taipei");
var b = moment.utc("2013-11-18 11:55").tz("America/Toronto");

a.format(); // 2013-11-18T19:55:00+08:00
b.format(); // 2013-11-18T06:55:00-05:00

a.utc().format(); // 2013-11-18T11:55Z
b.utc().format(); // 2013-11-18T11:55Z

この例では、最初にUTCでmoment.utc("2013-11-18 11:55")オブジェクトを作成し、その後、指定されたタイムゾーンに変更します。これは、デフォルトのタイムゾーンでオブジェクトを作成した場合(moment("2013-11-18 11:55"))にも機能します。

これらのモーメントはデフォルトのタイムゾーンで作成されたため、UTC時間が等しいことに注意してください。

ゾーンでのパース

編集
moment.tz(..., String);

moment.tzコンストラクタは、momentコンストラクタと同じ引数を取りますが、最後の引数をタイムゾーン識別子として使用します。

var a = moment.tz("2013-11-18 11:55", "America/Toronto");
var b = moment.tz("May 12th 2014 8PM", "MMM Do YYYY hA", "America/Toronto");
var c = moment.tz(1403454068850, "America/Toronto");
a.format(); // 2013-11-18T11:55:00-05:00
b.format(); // 2014-05-12T20:00:00-04:00
c.format(); // 2014-06-22T12:21:08-04:00

このコンストラクタはDSTを認識しており、パース時に正しいオフセットを使用します。

moment.tz("2013-12-01", "America/Los_Angeles").format(); // 2013-12-01T00:00:00-08:00
moment.tz("2013-06-01", "America/Los_Angeles").format(); // 2013-06-01T00:00:00-07:00

オフセットは、配列、オフセットのない文字列、またはオブジェクトで構築する場合にのみ考慮されます。

var arr = [2013, 5, 1],
    str = "2013-12-01",
    obj = { year : 2013, month : 5, day : 1 };

moment.tz(arr, "America/Los_Angeles").format(); // 2013-06-01T00:00:00-07:00
moment.tz(str, "America/Los_Angeles").format(); // 2013-12-01T00:00:00-08:00
moment.tz(obj, "America/Los_Angeles").format(); // 2013-06-01T00:00:00-07:00

moment.tz(arr, "America/New_York").format();    // 2013-06-01T00:00:00-04:00
moment.tz(str, "America/New_York").format();    // 2013-12-01T00:00:00-05:00
moment.tz(obj, "America/New_York").format();    // 2013-06-01T00:00:00-04:00

入力文字列にオフセットが含まれている場合、パースにはそれが代わりに使用されます。その後、パースされたモーメントはターゲットゾーンに変換されます。

var zone = "America/Los_Angeles";
moment.tz('2013-06-01T00:00:00',       zone).format(); // 2013-06-01T00:00:00-07:00
moment.tz('2013-06-01T00:00:00-04:00', zone).format(); // 2013-05-31T21:00:00-07:00
moment.tz('2013-06-01T00:00:00+00:00', zone).format(); // 2013-05-31T17:00:00-07:00

UnixタイムスタンプとDateオブジェクトは特定の時点を参照するため、構築時にタイムゾーンオフセットを使用することは意味がありません。moment.tz(Number|Date, zone)を使用することは、moment(Number|Date).tz(zone)と機能的に同等です。

var timestamp = 1403454068850,
    date = new Date(timestamp);

moment.tz(timestamp, "America/Los_Angeles").format(); // 2014-06-22T09:21:08-07:00
moment(timestamp).tz("America/Los_Angeles").format(); // 2014-06-22T09:21:08-07:00

moment.tz(date, "America/Los_Angeles").format();      // 2014-06-22T09:21:08-07:00
moment(date).tz("America/Los_Angeles").format();      // 2014-06-22T09:21:08-07:00

フォーマット引数の直後にブール値を指定して、厳密な構文解析を使用できます。厳密な構文解析では、フォーマットと入力が区切り記号を含めて完全に一致する必要があります。

moment.tz('It is 2012-05-25', 'YYYY-MM-DD', "America/Toronto").isValid();       // true 
moment.tz('It is 2012-05-25', 'YYYY-MM-DD', true, "America/Toronto").isValid(); // false
moment.tz('2012-05-25', 'YYYY-MM-DD', true, "America/Toronto").isValid();       // true
moment.tz('2012-05.25', 'YYYY-MM-DD', true, "America/Toronto").isValid();       // false

曖昧な構文解析

編集

サマータイムのため、時刻が存在しない場合や、2回存在する場合があります。

スプリングフォワード(サマータイム開始)

春、サマータイム開始時には、時計が1時間進みます。しかし実際には、時間が動いているのではなく、オフセットが動いているのです。

オフセットを前に進めることで、1時間が消えたという錯覚が生じます。時計の針が1:58から1:59に、そして3:00に進む様子を見ればわかります。オフセットを含めると、何が実際に起こっているのかがより分かりやすくなります。

1:58 -5
1:59 -5
3:00 -4
3:01 -4

その結果、1:59:59から3:00:00の間の時間は、実際には存在しませんでした。Moment Timezoneはこれを考慮しています。存在しなかった時間を解析しようとすると、DSTのずれ分(通常は1時間)だけスキップされます。

moment.tz("2012-03-11 01:59:59", "America/New_York").format() // 2012-03-11T01:59:59-05:00
moment.tz("2012-03-11 02:00:00", "America/New_York").format() // 2012-03-11T03:00:00-04:00
moment.tz("2012-03-11 02:59:59", "America/New_York").format() // 2012-03-11T03:59:59-04:00
moment.tz("2012-03-11 03:00:00", "America/New_York").format() // 2012-03-11T03:00:00-04:00

この例では、2時の時間は存在しないため、3時の時間と等価として扱われます。

フォールバック(サマータイム終了)

秋、サマータイム終了時には、時計が1時間戻ります。これも、時間が逆戻りしているのではなく、オフセットだけが戻っているのです。この場合、1時間が繰り返されたという錯覚が生じます。

繰り返しますが、オフセットを含めると、何が実際に起こっているのかがより分かりやすくなります。

1:58 -4
1:59 -4
1:00 -5
1:01 -5

Moment Timezoneは、重複した時間のうち常に早い方のインスタンスを使用することでこれを処理します。

moment.tz("2012-11-04 00:59:59", "America/New_York"); // 2012-11-04T00:59:59-04:00
moment.tz("2012-11-04 01:00:00", "America/New_York"); // 2012-11-04T01:00:00-04:00
moment.tz("2012-11-04 01:59:59", "America/New_York"); // 2012-11-04T01:59:59-04:00
moment.tz("2012-11-04 02:00:00", "America/New_York"); // 2012-11-04T02:00:00-05:00

構文解析時にオフセットを含めない限り、重複した時間の遅い方のインスタンスを持つモーメントを作成することはできません。

moment.tz("2012-11-04 01:00:00-04:00", "America/New_York"); // 2012-11-04T01:00:00-04:00
moment.tz("2012-11-04 01:00:00-05:00", "America/New_York"); // 2012-11-04T01:00:00-05:00

ゾーンへの変換

編集
moment().tz(String);
moment().tz(String, Boolean);

moment#tzミューテーターはタイムゾーンを変更し、オフセットを更新します。

moment("2013-11-18").tz("America/Toronto").format('Z'); // -05:00
moment("2013-11-18").tz("Europe/Berlin").format('Z');   // +01:00

この情報は、1日の開始時刻の計算など、他の操作でも一貫して使用されます。

var m = moment.tz("2013-11-18 11:55", "America/Toronto");
m.format();                     // 2013-11-18T11:55:00-05:00
m.startOf("day").format();      // 2013-11-18T00:00:00-05:00
m.tz("Europe/Berlin").format(); // 2013-11-18T06:00:00+01:00
m.startOf("day").format();      // 2013-11-18T00:00:00+01:00

引数なしでmoment#tzを呼び出すと、

  • モーメントインスタンスに割り当てられたタイムゾーン名、または
  • タイムゾーンが設定されていない場合はundefinedが返されます。
var m = moment.tz("2013-11-18 11:55", "America/Toronto");
m.tz();  // America/Toronto
var m = moment.tz("2013-11-18 11:55");
m.tz() === undefined;  // true

第2のパラメーターをtrueとして渡すと、タイムゾーン(とオフセット)のみが更新され、ローカル時刻は変わりません。そのため、オフセットが変更された場合は、異なる時点を指すようになります。

var m = moment.tz("2013-11-18 11:55", "America/Toronto");
m.format();                           // 2013-11-18T11:55:00-05:00
m.tz('Europe/Berlin', true).format()  // 2013-11-18T11:55:00+01:00

フォーマットの追加

編集
moment.tz(String).format("Z z"); // -08:00 PST
moment.tz(String).zoneAbbr();    // PST
moment.tz(String).zoneName();    // PST

+00:00のフォーマット情報に加えて、Moment Timezoneは省略されたタイムゾーン名に関する情報も含まれています。

moment.tz([2012, 0], 'America/New_York').format('z');    // EST
moment.tz([2012, 5], 'America/New_York').format('z');    // EDT
moment.tz([2012, 0], 'America/Los_Angeles').format('z'); // PST
moment.tz([2012, 5], 'America/Los_Angeles').format('z'); // PDT

これらの略語は、タイムゾーンオフセットによって変わる可能性があることに注意してください。これは、DSTを使用するかどうかにかかわらず、場所間のオフセットを区別するのに役立ちます。

// Denver observes DST
moment.tz([2012, 0], 'America/Denver').format('Z z');  // -07:00 MST
moment.tz([2012, 5], 'America/Denver').format('Z z');  // -06:00 MDT
// Phoenix does not observe DST
moment.tz([2012, 0], 'America/Phoenix').format('Z z'); // -07:00 MST
moment.tz([2012, 5], 'America/Phoenix').format('Z z'); // -07:00 MST

また、これらの略語はグローバルに一意ではないことに注意してください。以下に示すように、米国中部標準時と中国標準時は同じ略語を使用しています。

moment.tz('2016-01-01', 'America/Chicago').format('z');    // CST
moment.tz('2016-01-01', 'Asia/Shanghai').format('z');      // CST

moment#zoneAbbrを使用して、ゾーンの略語を取得することもできます。これは、zトークンをフォーマットする際にmoment.jsが使用するものです。

moment.tz([2012, 0], 'America/New_York').zoneAbbr(); // EST
moment.tz([2012, 5], 'America/New_York').zoneAbbr(); // EDT

Moment.jsは、長時間形式のタイムゾーン名のためのフックも提供しています。これらの文字列は一般的にローカライズされているため、Moment Timezoneはゾーンの長時間形式の名前を提供しません。

長時間形式の名前を提供するには、moment.fn.zoneNameをオーバーライドしてzzトークンを使用できます。

var abbrs = {
    EST : 'Eastern Standard Time',
    EDT : 'Eastern Daylight Time',
    CST : 'Central Standard Time',
    CDT : 'Central Daylight Time',
    MST : 'Mountain Standard Time',
    MDT : 'Mountain Daylight Time',
    PST : 'Pacific Standard Time',
    PDT : 'Pacific Daylight Time',
};

moment.fn.zoneName = function () {
    var abbr = this.zoneAbbr();
    return abbrs[abbr] || abbr;
};

moment.tz([2012, 0], 'America/New_York').format('zz');    // Eastern Standard Time
moment.tz([2012, 5], 'America/New_York').format('zz');    // Eastern Daylight Time
moment.tz([2012, 0], 'America/Los_Angeles').format('zz'); // Pacific Standard Time
moment.tz([2012, 5], 'America/Los_Angeles').format('zz'); // Pacific Daylight Time

zフォーマットトークンは、常に省略されたタイムゾーン名を表示するとは限らず、代わりに各地域のタイムオフセットを表示することに注意してください。

moment.tz('America/Los_Angeles').format('z')  // "PDT"     (abbreviation)
moment.tz('Asia/Magadan').format('z')         // "+11"     (3-char offset)
moment.tz('Asia/Colombo').format('z')         // "+0530"   (5-char offset)

デフォルトのタイムゾーン

編集
moment.tz.setDefault(String);

デフォルトでは、momentオブジェクトはローカルタイムゾーンで作成されます。ローカルタイムゾーンは、ブラウザやNode.jsなどのサーバーのようなJS環境によって決定されます。

デフォルトのタイムゾーンを変更するには、有効なタイムゾーンを指定してmoment.tz.setDefaultを使用します。

moment.tz.setDefault("America/New_York");

デフォルトのタイムゾーンをローカルにリセットするには、引数なしでmoment.tz.setDefaultを使用します。

moment.tz.setDefault();

これはグローバル設定です(すべてのモジュールで共有されます)。

後続のmoment.tz.setDefault呼び出しは、既存のmomentオブジェクトまたはそのクローンには影響しません。

ユーザーゾーンの推測

編集
moment.tz.guess();
moment.tz.guess(Boolean);

Moment Timezoneは、対応しているブラウザで国際化API(Intl.DateTimeFormat().resolvedOptions().timeZone)を使用して、ユーザーのタイムゾーンを判別します。

その他のブラウザでは、タイムゾーンの検出は非常に困難です。これらのブラウザでは、提供される情報が少ないためです。そのため、現在の年の周りのいくつかの時点についてDate#getTimezoneOffsetDate#toStringを使用して、ブラウザ環境に関するできるだけ多くの情報を収集します。次に、その情報をロードされたすべてのタイムゾーンデータと比較し、最も近い一致を返します。同点の場合は、人口の多い都市のタイムゾーンが返されます。

デフォルトでは、Moment Timezoneは検出されたタイムゾーンをキャッシュします。つまり、後続のmoment.tz.guess()呼び出しは常に同じ値を返します。

オプションのブール引数「ignoreCache」を指定してmoment.tz.guess()を呼び出すことができます。これをtrueに設定すると、キャッシュが無視され、新しい値で上書きされます。

moment.tz.guess(); // America/Chicago
// suppose the client's timezone changes to Europe/Berlin
moment.tz.guess(); // America/Chicago
moment.tz.guess(true); // Europe/Berlin
moment.tz.guess(); // Europe/Berlin

すべてのゾーンの取得

編集
moment.tz.names(); // String[]

使用可能なすべてのタイムゾーン名のリストを取得するには、moment.tz.namesを使用します。

moment.tz.names(); // ["Africa/Abidjan", "Africa/Accra", "Africa/Addis_Ababa", ...]

国別のゾーンの取得

編集
moment.tz.zonesForCountry(String); // String[]
moment.tz.zonesForCountry(String, Boolean);

特定の国に関するタイムゾーンのリストを取得するには、moment.tz.zonesForCountry()を使用します。

moment.tz.zonesForCountry('US');

デフォルトでは、このメソッドはアルファベット順にソートされたゾーン名を返します。

["America/Adak", "America/Anchorage", ... "Pacific/Honolulu"]

オフセットも取得するには、第2のパラメーターとしてtrueを渡します。

moment.tz.zonesForCountry('CN', true);

名前とオフセットを持つオブジェクトの配列を返します。

[
   { name: "Asia/Shanghai", offset: -480 },
   { name: "Asia/Urumqi", offset: -360 }
]

オフセットでタイムゾーンをソートする必要がある場合に役立ちます。

すべての国コードは、メソッドmoment.tz.countries()を使用して取得できます。

タイムスタンプとオフセットを一致させるために、Moment TimezoneはZoneオブジェクトを使用します。

使用する必要はないでしょうが、このオブジェクトのコンストラクターはmoment.tz.Zone名前空間で使用できます。

このオブジェクトには5つのプロパティがあります。

{
    name       : 'America/Los_Angeles',          // the unique identifier
    abbrs      : ['PDT', 'PST'],                 // the abbreviations
    untils     : [1414918800000, 1425808800000], // the timestamps in milliseconds
    offsets    : [420, 480],                     // the offsets in minutes
    population : 15000000                        // a rough population count for the largest city in this zone
}

名前

編集
zone.name; // America/Los_Angeles

タイムゾーンを一意に識別する名前です。命名規則の詳細については、IANAタイムゾーンデータベースの命名ガイドラインを参照してください。

ガイドラインでは、これらのゾーン識別子をエンドユーザーに直接表示しないように記述されていることにも注意してください。

経験の浅いユーザーがこれらの名前を無支援で選択することは想定されていません。配布者は、マップまたは「チェコ共和国」のようにタイムゾーン名「Europe/Prague」の代わりに説明的なテキストを使用して、各名前を説明するドキュメントや簡単な選択インターフェースを提供する必要があります。

すべてのロケールについて翻訳されたゾーン名の完全なリストを提供することは、Moment Timezoneの範囲外です。Unicode CLDRプロジェクトには、この目的のためのロケール対応マッピングが含まれています。

略語

編集
zone.abbr(timestamp); // PST

Zoneから指定されたタイムスタンプ(ミリ秒単位)の略語を取得します。

moment.tz.zone('America/Los_Angeles').abbr(1403465838805); // PDT
moment.tz.zone('America/Los_Angeles').abbr(1388563200000); // PST

オフセット

編集
zone.utcOffset(timestamp); // 480

Zoneから指定されたタイムスタンプ(ミリ秒単位)のオフセットを取得します。

moment.tz.zone('America/Los_Angeles').utcOffset(1403465838805); // 420
moment.tz.zone('America/Los_Angeles').utcOffset(1388563200000); // 480

POSIXとの互換性のため、オフセットは反転しています。したがって、Etc/GMT-Xのオフセットは+Xになり、Etc/GMT+Xのオフセットは-Xになります。これは、IANAのタイムゾーンデータベースの結果であり、Moment.jsによる任意の選択ではありません。したがって、固定オフセット識別子よりも、地域ベースの識別子の使用が推奨されます。

これはデータベースに関するWikipediaのエントリにも記載されています。

"Etc"の特別な領域は、特に協定世界時を表す"Etc/UTC"などの管理ゾーンに使用されます。POSIXスタイルに準拠するために、「Etc/GMT」で始まるゾーン名は、標準のISO 8601規則とは逆に符号が反転します。「Etc」領域では、GMTの西側のゾーンは正の符号を持ち、東側のゾーンは名前の中に負の符号を持ちます(例:「Etc/GMT-14」はGMTより14時間進んでいます)。

たとえば、Europe/Madrid識別子を使用すると、Etc/GMT+1とは異なる結果が得られます。

moment().tz('Etc/GMT+1').format('YYYY-MM-DD HH:mm ZZ');
// '2014-12-18 11:22 -0100'
moment().tz('Europe/Madrid').format('YYYY-MM-DD HH:mm ZZ');
// '2014-12-18 13:22 +0100'

オフセットの解析

編集
zone.parse(timestamp); // 480

そのゾーンでDate.UTCから構築されたタイムスタンプのオフセットを解析します。

これは、Moment Timezoneがタイムゾーンに入力を解析するために使用する方法です。このプロセスは、概念的には次のものと似ています。

ニューヨークで2014年3月19日午前8時30分の正確な瞬間を見つけたいと仮定します。ニューヨークではオフセットが-04:00-05:00の間で変化するため、3月19日のオフセットが何であったか分かりません。

代わりに、UTCでタイムスタンプを作成し、それをzone.parseに渡します。これにより、その時点でのオフセットが返されます。

var zone = moment.tz.zone('America/New_York');
zone.parse(Date.UTC(2012, 2, 19, 8, 30)); // 240

これは、上記の曖昧な構文解析セクションで参照されているケースを処理するコードです。

var zone = moment.tz.zone('America/New_York');
zone.parse(Date.UTC(2012, 2, 11, 1, 59)); // 300
zone.parse(Date.UTC(2012, 2, 11, 2, 0)); // 240

Moment Timezoneは2つのデータ形式を使用します。計算用の展開形式と、圧縮された転送用の圧縮形式です。

展開形式

編集

展開形式は、ゾーンオブジェクトとまったく同じように見えます。

以下のデータは、2014年から2018年までのロサンゼルスのデータです。

{
    name       : 'America/Los_Angeles',
    abbrs      : ['PST', 'PDT','PST', 'PDT', 'PST', 'PDT', 'PST', 'PDT', 'PST', 'PDT', 'PST'],
    untils     : [1394359200000, 1414918800000, 1425808800000, 1446368400000, 1457863200000, 1478422800000, 1489312800000, 1509872400000, 1520762400000, 1541322000000, null],
    offsets    : [480, 420, 480, 420, 480, 420, 480, 420, 480, 420, 480],
    population : 15000000,
    countries  : ['US']
}

abbrs、untils、offsetsの長さはすべて同じです。任意のインデックスのoffsetabbrは、タイムスタンプがそのインデックスのuntilよりも小さい間のみアクティブです。

これを簡単に説明すると、「untils[n-1]untils[n]の間は、abbrはabbrs[n]、オフセットはoffsets[n]になります」となります。

untilsはミリ秒単位で測定され、offsetsは分単位で測定されることに注意してください。

圧縮形式

編集

圧縮形式は、展開されたゾーンを1つの文字列で表します。

以下のデータは、2014年から2018年までのロサンゼルスのデータです。その他のタイムゾーンは、圧縮されたソースファイルで見ることができます。

'America/Los_Angeles|PST PDT|80 70|01010101010|1Lzm0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0|15e6'

できるだけ多くのバイト数を節約するために、非常にコンパクトな形式を使用してデータを保存しました。

データは、パイプで区切られた6つのセクションに分割されています。

#タイプ
0名前America/Los_Angeles
1略語マップPST PDT
2オフセットマップ80 70
3略語/オフセットインデックス01010101010
4タイムスタンプの差1Lzm0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0
5人口15e6

名前:タイムゾーンの標準名。

略語マップ:このタイムゾーンで使用されたすべての略語をスペースで区切ったリスト。

オフセットマップ:このタイムゾーンで使用されたすべてのオフセットを、60進数で分単位でスペースで区切ったリスト。

略語/オフセットインデックス:オフセットと略語マップへのインデックスを密に詰めた配列。これらも60進数です。

タイムスタンプの差:タイムスタンプが保存されている場所。

ソートされたタイムスタンプのリストを扱っているため、完全なタイムスタンプを保存するのではなく、最後のタイムスタンプからの差を保存するだけです。

配列の最初の要素は、分単位のUnixタイムスタンプです。最初の要素以降のすべての要素は、アンパック時に前の値に加算する分数を表します。すべての要素は60進数で格納されています。

上記の例で見たように、タイムスタンプの差分は、年々同じ値を繰り返す傾向があります。これらの重複により、完全なタイムスタンプを使用した場合よりも、gzipによるデータ圧縮率が向上します。

人口:ゾーンの名前の由来となった都市のおおよその人口。

これは60進数ではなく、科学的指数表記を使用しています。たとえば、値15e6は15 * 106(15の後に6個のゼロが付いた数)を表し、数値15,000,000を表します。

この値は、推測機能を使用する場合に、ほぼ同一のゾーンを比較するためにのみ使用されるため、正確である必要はありません。

一部のゾーンでは、この値が空の場合があることに注意してください。

60進数?

なぜ60進数を使用するのか疑問に思われるかもしれません。62進数はASCIIデータ圧縮のための一般的なツールであり、a-z10-35A-Z36-61として表します。

62進数を使用することで数バイト節約できたかもしれませんが、Moment Timezoneのデータの多くは60の倍数にきれいに対応しています。

1時間には60分、1分には60秒あります。3時間は、10進数では180分、10800秒、62進数では2U分、2Oc秒であるのに対し、60進数では30分、300秒となります。

リンク形式

編集

重複を減らすために、Moment Timezoneデータパッカーは、まったく同じデータを持つ2つのゾーンからリンクを作成します。

このデータは、パイプで区切られた2つのゾーン名です。

moment.tz.add('America/Los_Angeles|PST PDT|80 70|01010101010|1Lzm0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0');
moment.tz.link('America/Los_Angeles|US/Pacific');
moment.tz("2013-12-01", "America/Los_Angeles").format(); // 2013-12-01T00:00:00-08:00
moment.tz("2013-12-01", "US/Pacific").format();          // 2013-12-01T00:00:00-08:00

データがパックされ、クライアントに転送された後、Moment Timezoneに追加する必要があります。

これはNode.jsとプリビルドバンドルでは自動的に行われます。別の読み込み方法を使用している場合は、自分でデータを読み込む必要があるかもしれません。

ゾーンの追加

編集
moment.tz.add(PackedZoneString)
moment.tz.add(PackedZoneString[])

Moment Timezoneにゾーンデータを追加するには、moment.tz.addを使用します。

moment.tz.add('America/Los_Angeles|PST PDT|80 70|0101|1Lzm0 1zb0 Op0');

複数のゾーンを追加するには、パックされたデータの配列を渡します。

moment.tz.add([
    'America/Los_Angeles|PST PDT|80 70|0101|1Lzm0 1zb0 Op0',
    'America/New_York|EST EDT|50 40|0101|1Lz50 1zb0 Op0'
]);

注:上記のゾーンデータはサンプルデータであり、最新のものではありません。最新のデータについては、moment-timezoneソースを参照してください。

リンクの追加

編集
moment.tz.link(PackedLinkString)
moment.tz.link(PackedLinkString[])

2つのゾーン名を同じデータにリンクするには、moment.tz.linkを使用します。

渡される文字列は、リンク形式である必要があります。つまり、パイプで区切られた2つのゾーン名です。

moment.tz.link('America/Los_Angeles|US/Pacific');

一度に複数のリンクを追加するには、リンク文字列の配列を渡します。

moment.tz.link([
    'America/Los_Angeles|US/Pacific',
    'America/New_York|US/Eastern'
]);

データバンドルの読み込み

編集
moment.tz.load({
    zones : [],
    links : [],
    version : '2014e'
});

Moment Timezoneのデータは、IANAタイムゾーンデータベースから取得されます。さまざまな国のタイムゾーン法が変更されるにつれて、定期的に新しいバージョンがリリースされます。

バージョンは、年と増加する文字で命名されます。2014a 2014b 2014c...

バージョンをまとめて管理するために、Moment Timezoneにはバンドルされたオブジェクト形式も用意されています。

{
    version : '2014e',
    zones : [
        'America/Los_Angeles|PST PDT|80 70|0101|1Lzm0 1zb0 Op0',
        'America/New_York|EST EDT|50 40|0101|1Lz50 1zb0 Op0'
    ],
    links : [
        'America/Los_Angeles|US/Pacific',
        'America/New_York|US/Eastern'
    ]
}

バンドルをMoment Timezoneに読み込むには、moment.tz.loadを使用します。

moment.tz.load({
    version : '2014e',
    zones : [...],
    links : [...]
})

ゾーンの存在確認

編集
moment.tz.zone(name); // Zone or null

ゾーンが存在するかどうかを確認するには、moment.tz.zoneを使用します。ロードされている場合はゾーンが返され、ロードされていない場合はnullが返されます。

moment.tz.zone("UnloadedZone"); // null
moment.tz.add("UnloadedZone|UZ|0|0|");
moment.tz.zone("UnloadedZone"); // Zone { name : "UnloadedZone", ...}

ゾーン名の取得

編集
moment.tz.names(); // String[]

使用可能なすべてのタイムゾーン名のリストを取得するには、moment.tz.namesを使用します。

moment.tz.names(); // ["Africa/Abidjan", "Africa/Accra", "Africa/Addis_Ababa", ...]

パックおよびアンパックされたデータ形式の複雑さのため、Moment Timezoneには、データの処理のための厳密にテストされたユーティリティ関数がいくつか用意されています。

データのアンパックのためのメソッドは、ライブラリを使用するために必要であるため、コアライブラリに含まれています。

データのパックとサブセット化のためのメソッドは、追加のmoment-timezone-utils.jsファイルに含まれています。このファイルは、moment.tz名前空間にいくつかのメソッドを追加します。

// in moment-timezone.js
moment.tz.unpack
moment.tz.unpackBase60
// in moment-timezone-utils.js
moment.tz.pack
moment.tz.packBase60
moment.tz.createLinks
moment.tz.filterYears
moment.tz.filterLinkPack

パック

編集
moment.tz.pack(UnpackedObject); // PackedString

これは、アンパック形式のデータをパック形式に変換します。

var unpacked = {
    name       : 'Indian/Mauritius',
    abbrs      : ['LMT', 'MUT', 'MUST', 'MUT', 'MUST', 'MUT'],
    offsets    : [-230, -240, -300, -240, -300, -240],
    untils     : [-1988164200000, 403041600000, 417034800000, 1224972000000, 1238274000000, null],
    population : 150000
};
moment.tz.pack(unpacked); // "Indian/Mauritius|LMT MUT MUST|-3O -40 -50|012121|-2xorO 34unO 14L0 12kr0 11z0|15e4"

アンパック

編集
moment.tz.unpack(PackedString); // UnpackedObject

これは、パック形式のデータをアンパック形式に変換します。

var packed = "Indian/Mauritius|LMT MUT MUST|-3O -40 -50|012121|-2xorO 34unO 14L0 12kr0 11z0|15e4";

moment.tz.unpack(packed);
// {
//     name       : 'Indian/Mauritius',
//     abbrs      : ['LMT', 'MUT', 'MUST', 'MUT', 'MUST', 'MUT'],
//     offsets    : [-230, -240, -300, -240, -300, -240],
//     untils     : [-1988164200000, 403041600000, 417034800000, 1224972000000, 1238274000000, null],
//     population : 150000
// };

60進数パック

編集
moment.tz.packBase60(Number); // Base60String

10進数を60進数の文字列に変換します。

moment.tz.packBase60(9);    // 9
moment.tz.packBase60(10);   // a
moment.tz.packBase60(59);   // X
moment.tz.packBase60(1337); // mh

Number.prototype.toFixedと同様に、moment.tz.packBase60は、精度の桁数を指定する第2引数を受け入れます。

moment.tz.packBase60(1.1667,   1); // 1.a
moment.tz.packBase60(20.12345, 3); // k.7op
moment.tz.packBase60(59,       1); // X

小数点の前に単独の0がある場合は削除されます。

moment.tz.packBase60(1.1667, 1); // 1.a
moment.tz.packBase60(0.1667, 1); // .a

小数点以下の末尾のゼロは削除されます。

moment.tz.packBase60(1/6, 1); // .a
moment.tz.packBase60(1/6, 5); // .a
moment.tz.packBase60(59, 5);  // X

60進数アンパック

編集
moment.tz.unpackBase60(Base60String); // Number

60進数の文字列を10進数の数値に変換します。

moment.tz.unpackBase60('9');     // 9
moment.tz.unpackBase60('a');     // 10
moment.tz.unpackBase60('X');     // 59
moment.tz.unpackBase60('mh');    // 1337
moment.tz.unpackBase60('1.9');   // 1.15
moment.tz.unpackBase60('k.7op'); // 20.123449074074074

リンクの作成

編集
moment.tz.createLinks(UnpackedBundle); // UnpackedBundle

重複を減らすために、データが共通する2つのゾーンからリンクを作成できます。

var unlinked = {
    zones : [
        {name:"Zone/One",abbrs:["OST","ODT"],offsets:[60,120],untils:[403041600000,417034800000]},
        {name:"Zone/Two",abbrs:["OST","ODT"],offsets:[60,120],untils:[403041600000,417034800000]}
    ],
    links : [],
    version : "2014x-doc-example"
};

moment.tz.createLinks(unlinked);

{
    zones : [
        {name:"Zone/One",abbrs:["OST","ODT"],offsets:[60,120],untils:[403041600000,417034800000]}
    ],
    links : ["Zone/One|Zone/Two"],
    version : "2014x-doc-example"
}

これは、moment.tz.filterYearsと組み合わせると特に便利です。古いルールでは2つのゾーンを区別していた場合でも、フィルタリングされた年の範囲に含まれていない可能性があり、リンクすることで容量を節約できます。

年のフィルタリング

編集
moment.tz.filterYears(UnpackedZone, Number, Number); // UnpackedZone

デフォルトでは、Moment TimezoneにはIANAタイムゾーンデータベースのすべてのデータが含まれています。これには、少なくとも1900年から2038年までのデータが含まれています。バージョン0.5.37以降のリリースには、2400年以降のデータも含まれています。これらの年のデータは、使用ケースによっては必要ない場合があります。

moment.tz.filterYearsを使用して、特定の範囲外の年のデータをフィルタリングできます。

var all    = { name : "America/Los_Angeles", abbrs : [...], offsets : [...] untils : [...]};
var subset = moment.tz.filterYears(all, 2012, 2016);
all.untils.length;    // 186
subset.untils.length; // 11

1つの年のみが渡された場合は、開始年と終了年として使用されます。

var all    = { name : "America/Los_Angeles", abbrs : [...], offsets : [...] untils : [...]};
var subset = moment.tz.filterYears(all, 2012);
all.untils.length;    // 186
subset.untils.length; // 3

あるいは、ホームページで利用可能なより小さいプリビルドバンドルのいずれかが、すでにニーズに合致している可能性があります。

年のフィルタリング、リンクの作成、パック

編集
moment.tz.filterLinkPack(UnpackedBundle, Number, Number); // PackedBundle

パック、リンクの作成、年のサブセット化は、クライアントに転送するデータを圧縮するためのツールです。

moment.tz.filterLinkPackメソッドは、これらを1つのシンプルなインターフェースにまとめています。アンパックされたバンドル、開始年、終了年を渡すと、フィルタリングされ、リンクされ、パックされたバンドルが返されます。

これは、ホームページ上のバンドルされたデータとライブラリファイルの出力の圧縮に使用されている方法です。