前回の記事で日付の続きでもあります。
日付処理は有用なライブラリがありますが、経験値積むためなのでお許しを。
目的
Dateを継承して以下のようなメソッドチェーンにしたかった。
const time = new Time(1999,7,7,16,30,30,500);
const f = 'YYYY/MM/DD H:mm:ss.fff(DDD)';
console.log( time.term(1990, 2, 3) ); // -297621030500
console.log( time.getWeekday() ); // Sat
console.log( time.getWeekday('ja') ); // 土
console.log( time.format(f) ); // 1999/08/07 16:30:30.500(Sat)
console.log( time.advance(1).format(f) ); // 2000/08/07 16:30:30.500(Mon)
console.log( time.advanceDays(-3,5).format(f) ); // 2000/08/04 21:30:30.500(Fri)
console.log( time.reset().format(f) ); // 1999/08/07 16:30:30.500(Sat)
コード
- 追記1:
time.term()
のミリ秒以外で出力するメソッドを追加。
- 追記2:
time.reset()
関連の修正。引数nowを追加。
- 追記3:
time.termDays()
系の結果を四捨五入から切り上げに変更。**time.splitTerm()**を追加
class Time extends Date {
constructor(...args) {
super(...args);
this.default = super.toISOString();
}
reset(now) {
const d = now===true ? new Date() : new Date(this.default);
super.setFullYear(d.getFullYear());
super.setMonth(d.getMonth());
super.setDate(d.getDate());
super.setHours(d.getHours());
super.setMinutes(d.getMinutes());
super.setSeconds(d.getSeconds());
super.setMilliseconds(d.getMilliseconds());
return this
}
advance() {
if (arguments[0]) super.setFullYear(super.getFullYear() + arguments[0]);
if (arguments[1]) super.setMonth(super.getMonth() + arguments[1]);
if (arguments[2]) super.setDate(super.getDate() + arguments[2]);
if (arguments[3]) super.setHours(super.getHours() + arguments[3]);
if (arguments[4]) super.setMinutes(super.getMinutes() + arguments[4]);
if (arguments[5]) super.setSeconds(super.getSeconds() + arguments[5]);
if (arguments[6]) super.setMilliseconds(super.getMilliseconds() + arguments[6]);
return this
}
advanceDays() {
if (arguments[0]) super.setDate(super.getDate() + arguments[0]);
if (arguments[1]) super.setHours(super.getHours() + arguments[1]);
if (arguments[2]) super.setMinutes(super.getMinutes() + arguments[2]);
if (arguments[3]) super.setSeconds(super.getSeconds() + arguments[3]);
if (arguments[4]) super.setMilliseconds(super.getMilliseconds() + arguments[4]);
return this
}
term() {
return new Date(...arguments) - this;
}
termSeconds() {
return Math.ceil((new Date(...arguments) - this) / 1000);
}
termMinuts() {
return Math.ceil((new Date(...arguments) - this) / 60000);
}
termHours() {
return Math.ceil((new Date(...arguments) - this) / 3600000);
}
termDays() {
return Math.ceil((new Date(...arguments) - this) / 86400000);
}
splitTerm() {
const term = new Date(...arguments) - this;
const res = term < 0 ? [-term, '-'] : [term, '+'];
for (const div of [86400000, 3600000, 60000, 1000]) {
res.push( Math.floor(res[0]/div) );
res[0] %= div;
}
res.push( res.shift() );
return res
}
getWeekday(langStr) {
const n = super.getDay();
switch (langStr){
case 'ja': return '日月火水木金土'.charAt(n);
default: return ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'][n];
}
}
format(formatStr) {
const weekdays = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
const pad = (num, dig) => ('000' + num).slice(-dig);
return formatStr.replace(/([YMDHhmsf])\1*/g, match => {
switch (match) {
case 'YYYY':return super.getFullYear();
case 'YY': return pad(super.getFullYear(), 2);
case 'M': return super.getMonth()+1;
case 'MM': return pad(super.getMonth()+1, 2);
case 'D': return super.getDate();
case 'DD': return pad(super.getDate(), 2);
case 'H': return super.getHours();
case 'HH': return pad(super.getHours(), 2);
case 'm': return super.getMinutes();
case 'mm': return pad(super.getMinutes(), 2);
case 's': return super.getSeconds();
case 'ss': return pad(super.getSeconds(), 2);
case 'fff': return pad(super.getMilliseconds(), 3);
case 'DDD': return weekdays[super.getDay()];
default: return match;
}
})
}
}
メソッド解説
reset
|
time.reset( boolean now ) |
引数 |
true or other |
返値 |
date date |
説明 |
後述のadvance/advanceDayの処理で変化した日付をインスタンス生成時のものに戻す。引数をtrueにした場合のみ、このメソッドを実行した時間に上書きする。 |
advance
|
time.advance( number [y,[m,[d,[h,[mm,[s,[ms]]]]]]]] ) |
引数 |
number 第一引数を年、月,日,時,分,秒,ミリ秒と続く |
返値 |
date date |
説明 |
time.advance(0,1,1)で一月一日分加算され、time.advance(-1)で1年戻る |
advanceDays
|
time.advanceDays( number [d,[mm,[s,[ms]]]] ) |
引数 |
number 第一引数を日、時,分,秒,ミリ秒と続く |
返値 |
date date |
説明 |
advance()の年月を省いたもの |
term
|
time.term() |
引数 |
new Date()に指定する引数と同じもの |
返値 |
number milliseconds |
説明 |
インスタンス生成した日付と、ここで指定した日付の差が何ミリ秒かを出力 |
termSeconds...
|
time.termSeconds() / time.termMinutes() / time.termHours() / time.termDays() |
引数 |
new Date()に指定する引数と同じもの |
返値 |
number seconds/minutes/hours/days |
説明 |
各単位の対応版 |
splitTerm
|
time.splitTerm() |
引数 |
new Date()に指定する引数と同じもの |
返値 |
Array [string '+'|'-'、number days, number hr, mi, sc, ms] |
説明 |
ミリ秒を日数を最大にした各単位で分割して配列に出力。['+', 7, 1, 0, 3, 555]で7日と1時間3秒555ミリ秒 後。**+は基準より後、-**は基準より前。 |
getWeekday
|
time.getWeekday( string lang ) |
引数 |
string 言語指定 |
返値 |
string weekday |
説明 |
**'ja'**を指定すれば日本の曜日、それ以外は英語の曜日 |
format
|
time.format( string format ) |
引数 |
string 出力形式 |
返値 |
string date |
説明 |
詳細は前回の記事。'YYYY/MM/DD'と指定すれば2000/08/04のように返す。 |
私感
super
の使い方これでいいのかとか、他のメソッドでも使いたいweekdaysのような曜日の配列をconstructor
に置いても良いのか(外から書き換えられそう)とか、他にも多分色々おかしいところがあるかもしれない。