警告
この取説は現状の FOT.Time の仕様に基づくものです。
今後 FOT.Time の仕様が変更される可能性があります。
入力した時刻を、別の形式に変換します。
概念的には、JavaScript の Date クラスの類似品だと考えてください。
Date では setTime(ミリ秒) で時刻を設定し、getFullYear() や toUTCString() で時刻を取り出しますが、
このクラスも同様に、unix(秒) で時刻を設定して、year() や toString("UTC") で取り出すといった操作をします。
Date と違うのは、Date が UNIX時間( getTime )、西暦の世界時( getUTCFullYear, getUTCMonth ... )、
西暦の地方時( getFullYear, getMonth ... ) の3つの時間形式を扱うのに対して、
こちらはその他にいくつかの入出力が可能となっています。
また、設定可能な時刻の範囲が実用上十分な程度(*1)に広いです。なお、ミリ秒は扱えません。
入出力可能な形式は、西暦(グレゴリオ暦)の世界時/地方時、旧西暦(ユリウス暦)の世界時/地方時、 基準時刻からの秒数(UNIX時間/環境依存)、ユリウス日/修正ユリウス日、天晶暦(FINAL FANTASY XI)です。
基本的には「日付の変換(*2)」を行うクラスなので、
「日付の演算(*3)」は用意していませんが、一部、日付操作用のメソッドが存在します。
その他、ごく単純な書式化出力が可能です。
(*1) 限界値は環境依存。現在の一般的なブラウザであれば±1億8千万年は保証。詳細は後述。
(*2) 「日本時間○○日○○時はドイツで何時?」などの、時刻→時刻の変換。
(*3) 「○○日○○時の○○時間後は?」などの、時刻+時間量や時間量+時間量の計算。
// time.js を読み込んで、FOT.Time を使えるようにしておきます。
// ※ 変数 FOT 以外の名前空間への汚染はありません。
let time = FOT.Time();
// 世界時1970年1月1日0時のUNIX時間を取得
// ( sec = 0 )
let sec = time.ce([1970, 1, 1, 0, 0, 0], "UTC").unix();
// 修正ユリウス日0日の世界時を取得
// ( date = [1858, 11, 17, 0, 0, 0] )
let date = time.mjd(0).ce("UTC");
// 日本時間2001年2月3日4時5分6秒のアメリカ太平洋標準時間を取得
// ( pst = [2001, 2, 2, 11, 5, 6] )
let pst = time.ce([2001, 2, 3, 4, 5, 6], "JST").ce("PST");
やたら多いように見えますが、最も基本になるのが set / get / format で、 他の大半は構文糖(基本メソッドに特定引数を渡す場合の別名)です。
FOT.Time のインスタンスを生成します。引数がない場合は現在時刻が設定されます。
引数として set メソッドと同じ引数を受け取ることができ、その場合は引数を set メソッドに渡して実行した上で返します。
詳細は set メソッドの項目を参照して下さい。
time = FOT.Time();
time = FOT.Time( mixed value [, string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
// 以下の3つの動作は全て等価です。
time = FOT.Time( value [, time_name [, time_zone ]] );
time = FOT.Time().set( value [, time_name [, time_zone ]] );
time = FOT.Time().time_name( value [, time_zone ] );
特定の時間名文字列と、各時間名ごとの引数を渡して時刻を設定します。
戻り値として、(時刻が設定された)インスタンス自身が返ります。
time = time.set( mixed value [, string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
value:設定する時間の値。
実際に渡すものは第2引数に渡す時間名によって異なります。
time_name:時間名。以下のいずれかの文字列です。
time_zone:時間帯。時間名に西暦/旧西暦( "ce", "gc", "jc" )を指定した場合のみ入力します。
世界時との時差を、数値(秒単位), UTC±hh:mm, UTC±h, 時間帯名("JST"など)のいずれかで指定します。
戻り値time:時刻が設定された FOT.Time。
(*1) 全て「その時刻そのもの」を入力します。
たとえば、1998年4月3日20時5分33秒を設定する場合、[1998, 4, 3, 20, 5, 33] を渡します。
西暦4ケタを下2ケタ入力で認識したりはできません。
また、月は 1~12 です。0~11 ではありません。 0を入力すると、前年12月と解釈されます。
紀元前の年を入力する場合は、単純に通算年数で数えます。つまり紀元前1年が0、紀元前2年が-1となります。
(*2) 現在はUNIX時間と全く同じです。この仕様は変更される可能性があります。非推奨。
特定の時間名文字列を渡して時刻を取得します。
mixed value = time.get( [ string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
time_name:時間名。set メソッドと全く同じです。
time_zone:時間帯。set メソッドと全く同じです。
戻り値value:それぞれの時間名での時刻。
戻り値の形式は set メソッドの第1引数の形式と同じです。
たとえば時間名が "ce" の場合、戻り値として6要素を持つ配列 [年,月,日,時,分,秒] が返ります。
set / get メソッドは、引数として時間名を受け取りますが、各時間名と同名のメソッドが存在します。
これらのメソッドは、引数に応じて set / get のいずれかになります。
つまり、time.set( value, time_name [, time_zone ] ) は、
time.time_name( value [, time_zone ] ) として記述でき、
time.get( time_name [, time_zone ] ) は、
time.time_name( [ time_zone ] ) として記述できるわけです。
set メソッドの場合
time = time.ce( array value [, mixed time_zone = this.tz() ] ); // 西暦(グレゴリオ暦 / ユリウス暦)
time = time.gc( array value [, mixed time_zone = this.tz() ] ); // 西暦(グレゴリオ暦)
time = time.jc( array value [, mixed time_zone = this.tz() ] ); // 旧西暦(ユリウス暦)
time = time.unix( number value ); // UNIX時間
time = time.time( number value ); // 環境依存の秒数
time = time.jd( number value ); // ユリウス日
time = time.mjd( number value ); // 修正ユリウス日
time = time.ffxi( array value ); // 天晶暦(FINAL FANTASY XI)
get メソッドの場合
array value = time.ce( [ mixed time_zone = this.tz() ] ); // 西暦(グレゴリオ暦 / ユリウス暦)
array value = time.gc( [ mixed time_zone = this.tz() ] ); // 西暦(グレゴリオ暦)
array value = time.jc( [ mixed time_zone = this.tz() ] ); // 旧西暦(ユリウス暦)
number value = time.unix(); // UNIX時間
number value = time.time(); // 環境依存の秒数
number value = time.jd(); // ユリウス日
number value = time.mjd(); // 修正ユリウス日
array value = time.ffxi(); // 天晶暦(FINAL FANTASY XI)
現在設定されている時刻を元にして、引数で指定された特定の時刻を設定します。
これらのメソッドは全て、内部で set を呼んで、自身に設定されている時刻を再設定します。
また、戻り値として set と同様に、インスタンス自身を返します。
setNowTime 以外の9つのメソッドは、 [年,月,日,時,分,秒] の概念がある時間名("ce", "gc", "jc", "ffxi")でのみ利用可能です。 特定時刻メソッドにこれ以外の時間名を渡した場合、設定は行われず戻り値が undefined になります。
実行された時点の( JavaScript の実行環境の )現在時刻を設定します。
time = time.setNowTime();
戻り値time:時刻が設定された FOT.Time。
それぞれ、引数で指定された暦における、今日/昨日/明日の0時0分0秒に設定します。
time = time.setToday( [ string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
time = time.setYesterday( [ string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
time = time.setTomorrow( [ string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
time_name:時間名。"ce", "gc", "jc", "ffxi" のいずれかの文字列です。
time_zone:時間帯。set メソッドと全く同じです。
戻り値time:時刻が設定された FOT.Time。
それぞれ、引数で指定された暦における、今月/先月/来月の1日0時0分0秒に設定します。
time = time.setThisMonth( [ string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
time = time.setLastMonth( [ string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
time = time.setNextMonth( [ string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
time_name:時間名。"ce", "gc", "jc", "ffxi" のいずれかの文字列です。
time_zone:時間帯。set メソッドと全く同じです。
戻り値time:時刻が設定された FOT.Time。
それぞれ、引数で指定された暦における、今年/去年/来年の1月1日0時0分0秒に設定します。
time = time.setThisYear( [ string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
time = time.setLastYear( [ string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
time = time.setNextYear( [ string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
time_name:時間名。"ce", "gc", "jc", "ffxi" のいずれかの文字列です。
time_zone:時間帯。set メソッドと全く同じです。
戻り値time:時刻が設定された FOT.Time。
設定されている時間を、引数に基づいて文字列(一部は数値)として返すメソッドです。
これらのメソッドは全て、内部で get を呼んで、自身に設定されている時刻から文字列を組み立てて返します。 呼び出しによって設定されている時刻が書き換わることはありません。
いずれも、引数として時間名を受け取りますが、
[年,月,日,時,分,秒] の概念がある時間名("ce", "gc", "jc", "ffxi")でのみ利用可能です。
書式化出力メソッドに無効な時間名を渡した場合、戻り値は undefined になります。
第1引数に "%Y年%M月%D日(%jW) %2h:%2m:%2d" といった文字列を渡して、それを元に組み立てた文字列を返します。
置換部分の処理がかなり適当なので、複雑な文字列を組み立てると予期せぬ置換を行うかもしれません。
string value = time.format( string value_template [, string time_name = this.ceType() [, mixed time_zone = this.tz() ]] );
value_template:書式化文字列。
文字列中に専用の置換文字が含まれていると、それぞれ置換されます。
書式化文字列の中に "%" を記述する場合は "%%" としてください。
置換文字:%Y (年)、%M (月)、%D (日)、%h (時)、%m (分)、%s (秒)、%W (曜日)、%% (%)
% と後続文字の間にオプション1文字を指定することができます。
オプションがない場合は数値に置換されます。
"1" ~ "9" : オプションとして数値1文字を指定すると、数値がそのケタ数に足りなければ前方0埋めされ、 ケタ数が多すぎる場合は上位ケタを切り詰めます。
"e" : %M / %W のみ指定可能です。英名に置換されます。
"s" : %M / %W のみ指定可能です。英名短縮に置換されます。
"j" : %M / %W のみ指定可能です。日本語名に置換されます。
time_name:時間名。"ce", "gc", "jc", "ffxi" のいずれかの文字列です。
time_zone:時間帯。set メソッドと全く同じです。
戻り値value:置換された文字列
format の内部で呼んでいる関数を直接呼ぶためのメソッドです。
format で使用可能なオプションを指定して値を取りだすことができます。
mixed value = time.date( string time_type [, mixed value_type = "n" [, string time_name = this.ceType() [, mixed time_zone = this.tz() ]]] );
time_type:時間種類。以下のいずれかの文字列です。
value_type:戻り値の形式
ケタ数を表す数値 1 ~ 9 を指定するか、または以下のいずれかの文字です。
format で "e", "s", "j" のオプションが指定できるのは %M / %W のみです。
このメソッドでも同じなので注意して下さい。
"n" を指定した(または省略した)場合は、文字列ではなく数値を返します。
time_name:時間名。"ce", "gc", "jc", "ffxi" のいずれかの文字列です。
time_zone:時間帯。set メソッドと全く同じです。
戻り値value:文字列あるいは数値
date メソッドは、第1引数として時間種類を受け取りますが、各時間種類と同名のメソッドが存在します。
これらのメソッドは、date メソッドと同等です。
つまり、time.date( time_type [, value_type [, time_name [, time_zone ]]] ) は、
time.time_type( [ value_type [, time_name [, time_zone ]]] ) として記述できるわけです。
mixed value = time.year( [ mixed value_type = "n" [, string time_name = this.ceType() [, mixed time_zone = this.tz() ]]] );
mixed value = time.month( [ mixed value_type = "n" [, string time_name = this.ceType() [, mixed time_zone = this.tz() ]]] );
mixed value = time.day( [ mixed value_type = "n" [, string time_name = this.ceType() [, mixed time_zone = this.tz() ]]] );
mixed value = time.hour( [ mixed value_type = "n" [, string time_name = this.ceType() [, mixed time_zone = this.tz() ]]] );
mixed value = time.min( [ mixed value_type = "n" [, string time_name = this.ceType() [, mixed time_zone = this.tz() ]]] );
mixed value = time.sec( [ mixed value_type = "n" [, string time_name = this.ceType() [, mixed time_zone = this.tz() ]]] );
mixed value = time.wday( [ mixed value_type = "n" [, string time_name = this.ceType() [, mixed time_zone = this.tz() ]]] );
設定されている時刻を元に、文字列化したものを返します。時間名は常に西暦(グレゴリオ暦)になります。
JavaScript の Date.toUTCString とほぼ同じです。
string value = time.toString( [ string time_zone_name = "GMT" ] );
time_zone_name:時間帯名。"UTC", "GMT", "JST"など。
戻り値value:文字列
時間帯を "UTC±hh:mm" 形式の文字列にして返します。
このメソッドには、他のメソッドと同様にインスタンスから呼び出すメソッドの他に、同名の静的メソッドが存在します。
前者は引数を取らず、tz() で設定されている時間帯を文字列にして返しますが、
後者は引数として時間帯を受け取り、それを文字列にして返します。
戻り値の文字列は、他のメソッドの引数に指定する時間帯として有効な UTC±hh:mm 形式の文字列です。
string value = time.tzString();
string value = FOT.Time.tzString( mixed time_zone );
time_zone:時間帯。set メソッドと全く同じです。
戻り値value:"UTC±hh:mm" 形式の時間帯文字列
時間名に ce を指定、または時間名を省略した場合、ceType() に設定されている値が時間名の省略値となります。
同様に、時間帯を省略した場合は tz() に設定されている値が時間帯の省略値となります。
これらのメソッドは必ずしも使用する必要はありません。
時間名/時間帯を受け取る全ての操作において、値を直接指定することで、これらの省略値に関わり無くメソッドを利用できます。
これらのメソッドは、FOT.Time クラスの使い方を十分に理解した上で、 毎回同じ引数を指定する煩雑さを軽減するために、省略値を設定できるようにしたものです。
setter として扱うか getter として扱うかで挙動が変わります。
getter として扱う場合、このメソッドは現在 ceType に設定されている時間名を返します。
初期値は "gc" です。
setter として扱う場合、このメソッドは引数として "gc" と "jc" のどちらかを受け取り、 戻り値としてインスタンス自身を返します。
setter として扱うか getter として扱うかで挙動が変わります。
getter として扱う場合、このメソッドは現在 tz に設定されている時間帯を秒単位で返します。
初期値は (JavaScriptの) Date.getTimezoneOffset() * -60 です。
(※ JavaScript の実行環境の時間帯が設定されるということです。)
setter として扱う場合、このメソッドは引数として時間帯(set メソッドと全く同じ形式)を受け取り、 戻り値としてインスタンス自身を返します。
同じ時刻を設定した別のインスタンスを生成して返します。
time2 = time.clone();
戻り値time2:時刻が設定された FOT.Time。
動作としては以下のようになります。
// 日本時間 2001-01-01 00:00:00 でインスタンスを作成
let time_a = FOT.Time([2001, 1, 1, 0, 0, 0], "gc", "JST");
// 同じ時刻を設定した別のインスタンスを生成する
let time_b = time_a.clone();
// 以下とほぼ同等(*)
// let time_b = FOT.Time(time_a.unix(), "unix").ceType(time_a.ceType()).tz(time_a.tz());
(*) 厳密には、後述する限界値の関係で、実行環境における数値の限界を超えた範囲の時間を扱っている場合に限って、 このサンプルの操作ではズレが生じます。clone メソッドは、このクラスで維持可能な最大精度での複製を行います。
2つの時刻を比較して、-1 / 0 / 1 のいずれかを返します。
Perlにある <=> 演算子のようなものです。
number value = time.cmp( time2 );
time2:比較対象の FOT.Time。
戻り値value:比較結果(-1 / 0 / 1 のいずれか)
// 日本時間 2001-01-01 00:00:00 でインスタンスを作成
let time_a = FOT.Time([2001, 1, 1, 0, 0, 0], "gc", "JST");
// 日本時間 2000-01-02 00:00:00 でインスタンスを作成
let time_b = FOT.Time([2000, 1, 2, 0, 0, 0], "gc", "JST");
let x = time_a.cmp(time_b);
if (x < 0)
{
// time_a の方が早い(時間が前)
}
else if (x > 0)
{
// time_a の方が遅い(時間が後)
// このサンプルではここが実行される
}
else
{
// 2つは同じ時刻
}
"ce", "gc", "jc" の時間帯(time_zone)は、下記のいずれかの形式で指定します。
tz() の戻り値は数値(秒単位)、tzString() の戻り値は UTC±hh:mm です。範囲外の値は全て0として扱われます。
時間帯名は、原則としてPostgreSQLのマニュアルを元にしています(*)。
文字列 | 時差 | 地域名 | 英名 |
GMT | 00:00 | グリニッジ標準時 | Greenwich Mean Time |
---|---|---|---|
UT | 00:00 | 世界時 | Universal Time |
UTC | 00:00 | 協定世界時 | Coordinated Universal Time |
ZULU | 00:00 | Zulu | UTC ISO-8601 |
Z | 00:00 | Zulu | UTC ISO-8601 |
IDLE | +12:00 | 国際日付変更線(東側) | International Date Line, East |
IDLW | -12:00 | 国際日付変更線(西側) | International Date Line, West |
JST | +09:00 | 日本標準時間 | Japan Standard Time |
KST | +09:00 | 韓国標準時間 | Korea Standard Time |
CCT | +08:00 | 中国湾岸時間 | China Coastal Time |
MMT | +06:30 | ミャンマー時間 | Myanmar Time |
JT | +07:30 | ジャワ島時間 | Java Time |
MT | +08:30 | モルッカ諸島時間 | Moluccas Time |
IOT | +05:00 | インドチャゴス時間 | Indian Chagos Time |
MVT | +05:00 | モルディブ島時間 | Maldives Island Time |
IRT | +03:30 | イラン時間 | Iran Time |
IT | +03:30 | イラン時間 | Iran Time |
BT | +03:00 | バグダッド時間 | Baghdad Time |
IST | +02:00 | イスラエル標準時間 | Israel Standard Time |
AFT | +04:30 | アフガニスタン時間 | Afganistan Time |
EET | +02:00 | 東ヨーロッパ時間 | Eastern Europe Time |
CET | +01:00 | 中央ヨーロッパ時間 | Central European Time |
MET | +01:00 | 中央ヨーロッパ時間 | Middle Europe Time |
WET | 00:00 | 西ヨーロッパ時間 | Western Europe Time |
EETDST | +03:00 | 東ヨーロッパ夏時間 | Eastern Europe Daylight Savings Time |
CETDST | +02:00 | 中央ヨーロッパ夏時間 | Central European Daylight Savings Time |
METDST | +02:00 | 中央ヨーロッパ夏時間 | Middle Europe Daylight Time |
WETDST | +01:00 | 西ヨーロッパ夏時間 | Western Europe Daylight Savings Time |
CEST | +02:00 | 中央ヨーロッパ夏時間 | Central European Daylight Savings Time |
MEWT | +01:00 | 中央ヨーロッパ冬時間 | Middle Europe Winter Time |
MEST | +02:00 | 中央ヨーロッパ夏時間 | Middle Europe Summer Time |
MEZ | +01:00 | 中央ヨーロッパ地域時間 | Middle Europe Zone |
BST | +01:00 | イギリス夏時間 | British Summer Time |
BDST | +02:00 | イギリス二重標準時間 | British Double Standard Time |
FWT | +02:00 | フランス冬時間 | French Winter Time |
FST | +01:00 | フランス夏時間 | French Summer Time |
HMT | +03:00 | ギリシャ/ヘラ地中海時間 | Hellas Mediterranean Time |
DST | +01:00 | デンマーク標準時間 | Dansk Standard Time |
DNT | +01:00 | デンマーク時間 | Dansk Normal Time |
SWT | +01:00 | スウェーデン冬時間 | Swedish Winter Time |
SST | +02:00 | スウェーデン夏時間 | Swedish Summer Time |
NOR | +01:00 | ノルウェー標準時間 | Norway Standard Time |
ALMT | +06:00 | アルマトイ時間 | Almaty Time |
ALMST | +07:00 | アルマトイ夏時間 | Almaty Summer Time |
EAT | +03:00 | アンタナナリボ、コモロ時間 | Antananarivo, Comoro Time |
SCT | +04:00 | マーヘ島時間 | Mahe Island Time |
RET | +04:00 | レユニオン島時間 | Reunion Island Time |
MUT | +04:00 | モーリシャス島時間 | Mauritius Island Time |
SET | +01:00 | セイシェル時間 | Seychelles Time |
WAT | -01:00 | 西アフリカ時間 | West Africa Time |
EST | -05:00 | アメリカ東部標準時間 | Eastern Standard Time |
CST | -06:00 | アメリカ中部標準時間 | Central Standard Time |
MST | -07:00 | アメリカ山岳部標準時間 | Mountain Standard Time |
PST | -08:00 | アメリカ太平洋標準時間 | Pacific Standard Time |
EDT | -04:00 | アメリカ東部夏時間 | Eastern Daylight Time |
CDT | -05:00 | アメリカ中部夏時間 | Central Daylight Time |
MDT | -06:00 | アメリカ山岳部夏時間 | Mountain Daylight Time |
PDT | -07:00 | アメリカ太平洋夏時間 | Pacific Daylight Time |
NST | -03:30 | ニューファンドランド標準時間 | Newfoundland Standard Time |
NFT | -03:30 | ニューファンドランド時間 | Newfoundland Time |
NDT | -02:30 | ニューファンドランド夏時間 | Newfoundland Daylight Time |
YST | -09:00 | ユーコン標準時間 | Yukon Standard Time |
YDT | -08:00 | ユーコン夏時間 | Yukon Daylight Time |
AKST | -09:00 | アラスカ標準時間 | Alaska Standard Time |
AKDT | -08:00 | アラスカ夏時間 | Alaska Daylight Time |
CAT | -10:00 | 中央アラスカ時間 | Central Alaska Time |
AHST | -10:00 | アラスカ-ハワイ標準時間 | Alaska-Hawaii Standard Time |
BRT | -03:00 | ブラジリア時間 | Brasilia Time |
BRST | -02:00 | ブラジリア夏時間 | Brasilia Summer Time |
FNT | -02:00 | フェルナンド・デ・ノローニャ時間 | Ferdinand De Norornya Time |
FNST | -01:00 | フェルナンド・デ・ノローニャ夏時間 | Ferdinand De Norornya Summer Time |
HST | -10:00 | ハワイ標準時間 | Hawaii Standard Time |
HDT | -09:00 | ハワイ夏時間 | Hawaii Daylight Time |
GST | +10:00 | グアム標準時間 | Guam Standard Time |
AEST | +10:00 | オーストラリア東部標準時間 | Australia Eastern Standard Time |
ACST | +09:30 | オーストラリア中部標準時間 | Australia Central Standard Time |
AWST | +08:00 | オーストラリア西部標準時間 | Australia Western Standard Time |
AESST | +11:00 | オーストラリア東部夏時間 | Australia Eastern Summer Standard Time |
ACSST | +10:30 | オーストラリア中部夏時間 | Australia Central Summer Standard Time |
AWSST | +09:00 | オーストラリア西部夏時間 | Australia Western Summer Standard Time |
EAST | +10:00 | オーストラリア東部標準時間 | East Australian Standard Time |
CAST | +09:30 | オーストラリア中部標準時間 | Central Australia Standard Time |
WAST | +08:00 | オーストラリア西部標準時間 | West Australian Standard Time |
EADT | +11:00 | オーストラリア東部夏時間 | East Australian Daylight Time |
CADT | +10:30 | オーストラリア中部夏時間 | Central Australia Daylight Time |
WADT | +09:00 | オーストラリア西部夏時間 | West Australian Daylight Time |
LIGT | +10:00 | オーストラリア/メルボルン時間 | Melbourne, Australia |
NZT | +12:00 | ニュージーランド時間 | New Zealand Time |
NZST | +12:00 | ニュージーランド標準時間 | New Zealand Standard Time |
NZDT | +13:00 | ニュージーランド夏時間 | New Zealand Daylight Time |
CXT | +07:00 | クリスマス島時間 | Christmas Island Time |
MART | -09:30 | マルケサス諸島時間 | Marquesas Time |
MHT | +09:00 | マーシャル群島、クワジュリン時間 | Kwajalein Time |
ACT | -05:00 | 大西洋/ポルトアクリ標準時間 | Atlantic/Porto Acre Standard Time |
AST | -04:00 | (カナダ)大西洋標準時間 | Atlantic Standard Time (Canada) |
ADT | -03:00 | 大西洋夏時間 | Atlantic Daylight Time |
NT | -11:00 | ノーム時間 | Nome Time |
TFT | +05:00 | ケルゲレン諸島時間 | Kerguelen Time |
MAWT | +06:00 | モーソン時間(南極大陸) | Mawson (Antarctica) Time |
AWT | -03:00 | (不明) | (Unknown) |
(*) そもそも時間帯名は非常に重複が多く、しかも、どうやら統一された標準が存在しないようです。
たとえば、PostgreSQLではISTをイスラエル標準時間としているので、このクラスでもそれに準じていますが、
ウィキペディアでは、
ISTをインド標準時間として表記していますし、あるいは両方の名前として載せてるサイトもあったりします。
よって、このクラスで使用している時間帯名は、必ずしも他で通用するとは限らないことにご注意ください。
(*1) わたしがざっと探した限り、EADTという時間帯名は一般的には使われていないようです。 少なくとも、それっぽいサイトをググって見つかる範囲で、 普通に使ってるらしいのはCiscoのIP電話くらいです。
(*2) アメリカでは、EST, CST, MST, PST をそれぞれ自国の時間帯名として使用しているようです。
一方、オーストラリアでは、EST, CST, WST をそれぞれ自国の時間帯名として使用しているようです。
EST, CST が重複するので、これらの記号はアメリカ側に合わせ、重複しないWSTも、整合性の点から削除しました。
オーストラリアは AEST, ACST, AWST を使用してください。
(*3) SAST, SADT(オーストラリア南部標準時間/夏時間)は、それぞれCAST, CADT(オーストラリア中部標準時間/夏時間) と同一です。 SAST, SADTを入力可能にすると、整合性の点から、ASST, ASSST(笑) も入力可能にするべき、なんてことになりそうなので削除しました。
このクラスを使用する際に留意しておくべき事柄など。
かなり適当です。このマニュアルに明記されている以外の引数を渡せば、エラーが発生したり、想定外の動作をすることになります。
たとえば set に時間名として "hasOwnProperty" という文字列を渡せば、エラーで実行停止するはずです。
また、get に"hasOwnProperty" を渡すと、意味不明な値を返します。
止まってはいけないプログラムで利用するのであれば、自分で try-catch するなり、引数と戻り値を完全にチェックするなりしてください。
最も適切な対応として、大切なプログラムでは、このライブラリを利用しないことをオススメします。
このクラスで扱える時間の範囲は、
JavaScript の実行環境に依存します。
現在の一般的なブラウザでは、JavaScript の数値を IEEE754 に準拠した変数で扱います。
それらのブラウザであれば、西暦(グレゴリオ暦)で±1億8千万年程度が、
全ての時間名について、精度を保証できる限界になります。
IEEE754 で整数の加減算の精度が保証できるのは ±9007199254740991(=0x1FFFFFFFFFFFFF) の範囲であるため、 これをUNIX時間に換算して、グレゴリオ暦世界時で B.C.285424813-02-21 01:23:29 ~ A.D.285428751-11-12 16:36:31 が、 UNIX時間の限界ということになります。
しかし、あまりに大きな数に対しては小数点以下の精度が悪くなることから、
小数を扱うユリウス日/修正ユリウス日は、この範囲ぎりぎりでは精度が維持できません。
ユリウス日/修正ユリウス日で ±1億8千万年を超える時刻を扱うと、
小数点以下のケタ数が少なすぎて精度を維持できず、時間が秒単位でズレるようになります。
よって、±1億8千万年程度が秒単位の精度を保証できる限界です。
逆に言うと、秒単位の精度が必要ない場合は、これ以上の時間に対して計算しても正しい値が得られます。
たとえば当日の世界時午前0時ジャストのユリウス日/修正ユリウス日を求めるだけなら、
小数点以下は 0 か 0.5 だけなので、±12兆年の範囲で精度が保証できます。
なお、地方時を扱う場合は分単位での精度が必要なので、範囲はこれよりも小さくなります。
単純計算で、±108億年(=1億8000万年×60)ほどです。
UNIX時間/ユリウス日/修正ユリウス日のいずれも扱わない場合、 時間を単一の数値として扱う必要がなくなるので、精度が保証できる限界は飛躍的に大きくなります。
前述の時間以外で、精度の保証が可能な範囲が最も小さいのは天晶暦ですが、
他の時間を天晶暦に変換する、または天晶暦を他の時間に変換する場合は、
西暦換算で ±350兆年 がおおよその目安となります。
UNIX時間/ユリウス日/修正ユリウス日/天晶暦のいずれでもなく、
単に西暦(グレゴリオ暦/ユリウス暦の世界時/地方時)同士の変換を行う場合は±9千兆年程度です。
まとめると、精度が保証できる限界は以下の通りです。
なお、内部計算に使用している "total" は ±360京年(=9千兆年の400倍) 程度の精度があります。 内部の処理は全て「入力された時間を "total" に変換」「"total"を指定された時間に変換して出力」という操作なので、 変換時の内部計算における精度落ちを考慮する必要はありません。
この説明ページはやたら長いですが、慣れれば使い方は単純なはずです。
要するに、複数の時間名( "gc", "jc", "unix" ... )を set で設定して、
それを複数の時間名( "gc", "jc", "unix" ... )として get で取り出すことができると、それだけです。
曜日のみ、get では取り出すことができないので、wday か format を使う必要があります。
元々の設計方針は、時間変換の書式の汎用化です。
たとえば UNIX時間から西暦への変換、あるいはその逆を行う場合、以下のように記述します。
let arr = time.unix(0).gc("UTC"); // arr = [1970, 1, 1, 0, 0, 0]
let unix = time.gc([1970, 1, 1, 0, 0, 0], "UTC").unix(); // unix = 0
ここで、UNIX時間ではなく修正ユリウス日を扱いたい場合には、このようになります。
let arr = time.mjd(0).gc("UTC"); // arr = [1858, 11, 17, 0, 0, 0]
let mjd = time.gc([1858, 11, 17, 0, 0, 0], "UTC").mjd(); // mjd = 0
UNIX時間をグレゴリオ暦に(unix → gc)という変換は、unix(引数).gc() と記述でき、
グレゴリオ暦を修正ユリウス日に(gc → mjd)という変換は、gc(引数).mjd() と記述できるわけです。
このクラスで扱える全ての時間名で、このような記述が可能になるように設計しています。
コンストラクタの引数は set メソッドと同様なので、いちいちインスタンスを作りたくない場合には、 コンストラクタに引数を渡して直後にgetすることも可能です。
let arr = FOT.Time(0, "unix").gc("UTC"); // arr = [1970, 1, 1, 0, 0, 0]
let unix = FOT.Time([1970, 1, 1, 0, 0, 0], "gc", "UTC").unix(); // unix = 0
また、setter になるメソッドは、全てインスタンス自身を返すように設計しているので、
たとえばユーザーが入力した時刻(グレゴリオ暦)の当日午前0時(日本時間)のUNIX時間を求める場合は、
間に setToday を挟んで、以下のように記述できます。
let date = [year, month, day, hour, min, sec]; // ユーザーが入力した時刻
let unix = time.gc(date, "JST").setToday("gc", "JST").unix();
ここで、一連の操作で gc や JST が複数回出てくる場合があることが分かったと思います。
ceType や tz による省略値の設定は、これを軽減するためのもので、以下のように記述しても同じになります。
time.ceType("gc").tz("JST");
let unix = time.ce(date).setToday().unix();
時間の仕組み自体が複雑なので、時間を扱うための基本メソッドを網羅するように設計したこのクラスも複雑に見えるかと思います。
実際、ある程度時間の仕組みを把握していないと、とても扱いきれるものではないと思います。
ただ、その把握さえできてしまえば、適切な省略値を設定することで十分に単純な書式で利用できるように設計しているつもりです。
最初に『「日付の演算」機能はない』と書きましたが、もちろん「日付とはなにか」を正しく理解している方なら、
「日付の変換」さえできれば、演算なんて楽勝だということはお分かりのはずです。
秒差を求めるなら、
let time_diff = FOT.Time([年,月,日,時,分,秒]).unix() - FOT.Time([年,月,日,時,分,秒]).unix();
で、全く問題なく計算できます。
では、なぜ演算関係のメソッドを作らないのかというと、西暦の加減算というものは、秒単位で定義することができないからです。
たとえば「1月30日の1か月後は何月何日ですか?」という話です。
一般に、1月1日の1か月後は2月1日、1月10日の1か月後は2月10日、1月25日の1か月後は2月25日ですが、
1月30日の1か月後は「だいたい2月末」としか表現できません。
『1か月』や『1年』という期間は、日数にすると値が可変なのです。
このクラスで、2001年1月30日の1か月後を単純に+1で入力すると、3月2日になります。
計算過程は以下の通り。
一般的には、1月30日の1か月後は3月2日にはなりません。3月2日の1か月前は2月2日です。
でも、[1月30日の1か月後]→[1月1日の29日後の1か月後]→[1月1日の1か月後の29日後]→[2月1日の29日後]→[3月2日]。
ある意味では、これも正しい計算です。
間違っているのは『1か月』の日数が不定であることを考慮せずに1か月後を求めようとしていることです。
日数差(日の加減算)であれば、1日=86400秒で不変なので計算可能です。
また、400年の加減算も、グレゴリオ暦400年=14万6097日=126億2278万800秒なので計算可能です(*)。
しかし、年差や月差は可変なので計算不可能です。
利用者がこれを踏まえた上で、引数に適当な値を入れるのは問題ありません。 日付の計算を理解せずに変な値を入れると、変な数字にしかなりません。
なお、たとえば(現在設定されている時刻を維持したまま)今月末の日付を求めたいのであれば、last_day = obj.clone().setNextMonth().setYesterday().day()
(同時刻のインスタンスを作り、来月1日の前日に設定して、その日付を返す)といった応用ができます。
同様に、来年の2月末日の日付であれば feb_last_day = obj.clone().setNextYear().setNextMonth().setNextMonth().setYesterday().day()
(同時刻のインスタンスを作り、来年1月1日の翌々月の前日に設定して、その日付を返す) という操作で可能です。
このように、『先月の○日』や『来年の○月』といった概念は、特定時刻設定メソッドとの組み合わせで求めることができる場合があります。
内部では set に対して引数を適切に設定しているだけなので、特定時刻メソッドを使って表現可能な操作は、
これらのメソッドを使わず自分で引数を設定することでも全て実行可能です。
(*) ユリウス暦の場合は4年単位(うるう年周期)で加減算が可能ですが、 ユリウス暦で4年単位の加減算を行うと曜日のズレが生じます。 曜日周期も考慮した加減算を行う場合は4*7=28年周期となります。
このクラスでは、UNIX時間(unix)と環境依存の秒数(time)を区別していますが、
わたしの知る限り、JavaScriptで 1970-01-01 00:00:00 以外の時刻を基準にしている環境は存在しないので、
現在は、この2つは実質的に同じモノの別名に過ぎません。
ECMAScript で明確に仕様化されたので、今後、基準時刻が違う環境が実装されることもおそらくないでしょう。
これは、このクラスが元々Perlからの移植であり、
Perlでは過去のMacOSで基準時刻が違うモノがあったため、それに対応した名残りです。
このクラスでも内部の実装はしてあるので、
unix はどんな環境であっても 1970-01-01 を基準にした秒数を返しますし、
time はその環境の time 値を正しく受け取ることができます。
今後、このクラスでミリ秒を扱えるような仕様変更を行うことになった場合、 time が秒単位からミリ秒単位に変更されて、JavaScript の Date.getTime を直接受け取るようになる可能性があります。
内部の処理としては、入力された時間は全て独自の内部形式 "total" に変換して保持しておき、
呼び出された時にはその都度 "total" からそれぞれの形式に変換しています。
"total" は、[400年を1とする単位, 日単位, 秒単位] の3要素を持つ配列で、精度保証限界は±360京年です。
total がミリ秒を保持するように設計していないために、このクラスではミリ秒を扱うことはできません(*)。
説明する意味があまりない(上に説明するのも面倒な)ので省略していますが、
実は set / get ともに、時間名として "total" を受け付けることができますし、
メソッドとして total も存在しています。
扱い方を理解していれば、time.total().join(",") で360京年の精度を維持したまま時間を文字列化しておいて、
time.total(str.split(",")) で戻すという操作などに使えます。
(*) なお、ミリ秒を扱えるように修正することは可能なのですが、その場合 format 用の指定子を %m にできないので、
イマイチ綺麗な作りにできず、修正する気が起きません :-)
ちなみに、仮にミリ秒を扱えるようにした場合、ce / gc / jc で入出力する配列の要素数が7になったり、
time が Date.getTime に合わせてミリ秒になったりと、大幅な仕様の変更も発生することになります。
一切考えていません。clone メソッドが存在し、new を隠している以上、内部の実装に依存しない限りは継承による拡張は不可能なはずです。
インスタンスにメソッドを直接突っ込めば、それで大抵は何とかなるでしょうし、 それでは無理だというのであれば、継承ではなく包含でクラス設計してください。
再三書いたように、time メソッドは非推奨です。
現状では後方互換のために存在していますが、いずれ仕様変更される可能性があります。
あえて外しましたが、format の %Y も、オプションとして esj を受け付けています。
また、%Y に限り、k オプションも存在しています。
これらを指定すると、先頭に認識文字がついて、1未満の年数は紀元前表記になります。
たとえば %eY なら "A.D.(年)" / "B.C.(年)" に置換され、
%jY なら "西暦 (年)" / "紀元前 (年)" に置換されます。
month や wday と違い、文字列化の法則が特殊なので扱いに注意が必要です。基本的には非推奨と考えてください。
現在の設定を文字列化する serialize() と、その文字列を元に時刻を設定する unserialize() というメソッドもあります。
仕様が全然固まっていませんし、そもそもスクリプト内で使い捨てる以外の利用は想定していません。
初見で分かる人はいないだろーってぐらいの我流の極みです。
これを読んでみようなんて思う酔狂な人がいるとは思いませんが、
万一、間違ってそんな気を起こした方がいるのなら、先にFOT.Colorを見てみることをオススメします。
あちらが後発で、このFOT.Timeの基本構造をそのまま流用して組み上げたものです。
あちらの方がやってることが少ないので構造が分かりやすいかと。
あちらの構造を把握してからであれば、こちらの把握も幾分容易になる、かもしれません。
元々は PerlCGI の掲示板プログラムをいじっていた時の副産物です。
要するに、自分が欲しくなったモノを作っただけです。