前回の記事で日付の続きでもあります。
日付処理は有用なライブラリがありますが、経験値積むためなのでお許しを。
#目的
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
に置いても良いのか(外から書き換えられそう)とか、他にも多分色々おかしいところがあるかもしれない。