【javascript】日付を指定の形式で出力（追記2個）

#前置き

JavaScript 環境ならどこでも使えそうな短いコードの日付書式出力関数。コピペ用。 - Qiita
https://qiita.com/standard-software/items/fe8dfcbeb3bde37bd2f4

上記記事をきっかけに記事にしました。
詳細は上記記事をご覧ください。

#コード

```javascript:
// d : [0.year, 1.month, 2.date, 3.hour, 4.minute, 5.sec, 6.msec, 7, 8.day]
const dateFormats = {
	'YYYY': d => d[0],
	'YY': d => d[0].slice(-2),
	'MM': d => d[1],
	'M': d => +d[1],
	'DD': d => d[2],
	'D': d => +d[2],
	'HH': d => d[3],
	'H': d => +d[3],
	'mm': d => d[4],
	'm': d => +d[4],
	'ss': d => d[5],
	's': d => +d[5],
	'fff': d => d[6],
	'DDD': d => ['Sun', 'Mon', 'Tue', 'Wed', 'Thr', 'Fri', 'Sat'][d[8]],
	'YMD': d => d.slice(0,3).join(''),
	'Hms': d => d.slice(3,6).join(''),
};
const dateToString = (format, ...args) => {
	const date = new Date(...args);
	//修正：引数が数値一つの時オフセットしない処理を削除
	const d = new Date(date - date.getTimezoneOffset()*60000)
				.toISOString().split(/[^\d]/).concat( date.getDay() );
	return format.replace(/[YMDHhmsf]+/g, m => 	//修正：iフラグを削除
					dateFormats[m] ? dateFormats[m](d) : m);
};

const dfmt = 'YYYY/MM/DD HH:mm:ss.fff(DDD)';
console.log( dateToString(dfmt) );
	// 実行時の時間
console.log( dateToString(dfmt, 0) );
	// 1970/01/01 09:00:00.000(Thr)
console.log( dateToString(dfmt, '1999/12/31 23:59:59') );
	// 1999/12/31 23:59:59.000(Fri)
console.log( dateToString(dfmt, 1999, 11, 31, 23, 59, 59, 999) );
	// 1999/12/31 23:59:59.999(Fri)
```

第1引数は出力形式の指定
第2引数以降は`new Date()`の引数に入れる値と同じ。

#私感

~~**YYYYMMDD**のような区切りなく連なった所は個別で処理できないのが問題点かもしれない。
コードに記したYMDのような形式を作ってしまえば対処は可能。~~

`date.toISOString()`さん、ローカル時間でも出力できるようになりませんかね。。。
そうすれば周辺スッキリするのに。

#区切りのない形式への対応（追記）

**YYYYMMDD**のような形式です。
検索したところ、正規表現に後方参照を用いることで対応できそう。

```javascript:
//この部分を
/[YMDHhmsf]+/g,

//こう変更
/([YMDHhmsf])\1*/g,

```

結果は以下の通り

```javascript:
const dfmt = 'YYYYMMDD HHmmss.fff(DDD)';
console.log( dateToString(dfmt, 0) );
	// 19700101 090000.000(Thr)
console.log( dateToString(dfmt, '1999/12/31 23:59:59') );
	// 19991231 235959.000(Fri)
console.log( dateToString(dfmt, 1999, 11, 31, 23, 59, 59, 999) );
	// 19991231 235959.999(Fri)
```

この場合では、**YMD**のような違う文字の混じった形式は使用できず、同じ文字の連続した形式のみに縛られるようになります。


#初心に帰って（追記）

```javascript:
function zeroPad (num, dig) {
	return ('000' + num).slice(-dig)
}
function dateToString (format, date) {
	var weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
	
	return format.replace(/([YMDHhmsf])\1*/g, function (match) {
		switch (match) {
			case 'YYYY':return date.getFullYear();
			case 'YY':	return zeroPad(date.getFullYear(), 2);
			case 'M':	return date.getMonth()+1;
			case 'MM':	return zeroPad(date.getMonth()+1, 2);
			case 'D':	return date.getDate();
			case 'DD':	return zeroPad(date.getDate(), 2);
			case 'H':	return date.getHours();
			case 'HH':	return zeroPad(date.getHours(), 2);
			case 'm':	return date.getMinutes();
			case 'mm':	return zeroPad(date.getMinutes(), 2);
			case 's':	return date.getSeconds();
			case 'ss':	return zeroPad(date.getSeconds(), 2);
			case 'fff':	return zeroPad(date.getMilliseconds(), 3);
			case 'DDD':	return weekdays[date.getDay()];
			default: return match;
		}
	})
}

var dfmt = 'YYYYMMDD H:mm:ss.fff(DDD)';
console.log( dateToString(dfmt, new Date(1999, 11, 31, 23, 59, 59, 999)) );
	//19991231 23:59:59.999(Fri)
```

残余引数をスプレッド構文を使わずに受け渡しする方法が分からなかったので、引数で`new Date()`しておく形。

`aruguments`を`Array.prototype.slice.call`で切り出して、`new Date`に渡しても配列だと返りは`invalid data`。。。
スプレッド構文、便利です。