Oka Laboratory

DateTime!

日付・時刻の計算をします。開始日時に経過日時を加減算した日時や、終了日時までの経過日時を求めることができます。

日時計算

開始日時
項目 算出値
年月日
曜日
時分秒
ISO8601
指定書式
経過日時
ISO8601
満年数
満月数
経過日数
経過時間
経過分
経過秒

使用方法

日時の書式指定子
書式指定子 説明 表示例
YYYY 西暦年[パディングあり] (0000〜9999)
yyyy 西暦年[パディングなし]
ggg 元号名 (明治、大正、…)
gg 短縮した元号名 (明、大、…)
g 短縮した元号名 (M, T, …)
EE 元号年[パディングあり] (元, 02〜)
E 元号年[パディングなし] (元, 2〜)
eee 神武天皇即位紀元 (皇紀)
ee 元号年[パディングあり] (01〜)
e 元号年[パディングなし] (1〜)
MMMM
jp
和風月名 (睦月、如月、…)
en
月名 (January, February, …)
MMM
jp
MMMMと同じ
en
短縮した月名 (Jan., Feb., …)
MM 月[パディングあり] (01〜12)
M 月[パディングなし] (1〜12)
dddd 年間通算日[パディングあり] (001〜366)
ddd 年間通算日[パディングなし] (1〜366)
dd 日[パディングあり] (01〜31)
d 日[パディングなし] (1〜31)
WWW
jp
曜日 (日曜日、月曜日、…)
en
曜日 (Sunday, Monday, …)
WW
jp
短縮した曜日 (日、月、…)
en
短縮した曜日 (Sun, Mon, …)
W 曜日番号 (1〜7)
wwww 暦週年[パディングあり] (0000〜9999)
www 暦週年[パディングなし]
ww ISO8601形式の暦週番号 (W01〜W53)
w 週番号[パディングなし] (1〜53)
HH 24時制の時[パディングあり] (00〜23)
H 24時制の時[パディングなし] (0〜23)
hh
jp
12時制の時[パディングあり](00〜11)
en
12時制の時[パディングあり](01〜12)
h
jp
12時制の時[パディングなし](0〜11)
en
12時制の時[パディングなし](1〜12)
mm 分[パディングあり] (00〜59)
m 分[パディングなし] (0〜59)
ss 秒[パディングあり] (00〜59)
s 秒[パディングなし] (0〜59)
SSS ミリ秒[パディングあり] (000〜999)
S ミリ秒[パディングなし] (0〜999)
ZZ UTCとの時差 (hh:mm形式)  
Z UTCとの時差 (hhmm形式)  
tt
jp
午前 / 午後
en
AM / PM

利用上の注意

アルゴリズム

日時を指定した書式に整形するFormatDate関数は、書式指定子を含む文字列をreplace()メソッドを用いて対象の値に置換していくという方法で処理をしています。英語の月名や曜日名には一部の書式指定子の文字が含まれていますので、一旦日本語文字列に置換してから最後に再度置換しています。

FormatDate関数の引数は以下の3つで、戻り値は整形後の日時文字列です。

dt
Dateオブジェクト
format
書式指定子を含む文字列
locale
'jp' (日本語) / 'en' (英語)

FormatDate関数のソースコードです。

function FormatDate (dt, format, locale) {
/* 日付を書式文字列に従い整形 */
	locale = locale || 'jp';		// 引数localeが渡されないときは'jp'を設定

	const MSEC_PER_DAY = 86400000;	// 1日あたりのミリ秒数

	var month_name = {
	'jp': ['睦月','如月','弥生','卯月','皐月','水無月','文月','葉月','長月','神無月','霜月','師走'],
	'en': ['January','February','March','April','May','June','July','August','September','October','November','December']
	};
	var dow_name = {
	'jp': ['日','月','火','水','木','金','土'],
	'en': ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday']
	};
	var ampm = {
	'jp': ['午前', '午後'],
	'en': ['AM', 'PM'],
	}
	var era_name = {
	'jp': ['明治','大正','昭和','平成','令和',''],
	'en': ['M','T','S','H','R',''],
	'start': [new Date(1868,9,23),new Date(1912,6,30),new Date(1926,11,25),new Date(1989,0,8),new Date(2019,4,1),new Date(2117,11,31)]
	}

	// Zero Padding
	var zero_padding = function(n, digit) {
		return (Array(digit).join('0') + n).slice(-digit);
	};

	// 1年の日数 (Days of Year)
	var days_of_year = function(year) {
		return (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0) ? 366 : 365;
	};

	var year = dt.getFullYear();			// 西暦年
	var month = dt.getMonth() + 1;			// 月(1〜12)
	var day = dt.getDate();					// 日
	var dow = dt.getDay();					// 曜日番号(0〜6)
	var hour = dt.getHours();				// 時(24時間制)
	var hour12 = hour % 12;					// 時(12時間制)
	if (locale == 'en' && hour12 == 0) hour12 = 12;		// 12時間制(locale = 'en')では0時を12時と表示
	var minute = dt.getMinutes();			// 分
	var second = dt.getSeconds();			// 秒
	var milisec = dt.getMilliseconds();		// ミリ秒
	var tz_off = dt.getTimezoneOffset();	// UTCとの時差(分単位、通常の表記とは符号が逆)

	// 年間通算日(ordinal date)
	var first_day = new Date(year, 0, 1);	// 今年の1月1日
	var ordinal = Math.ceil((dt - first_day) / MSEC_PER_DAY);

	// ISO8601 暦週日付 (week date)
	var dow_iso = dow !== 0 ? dow : 7;		// 曜日番号をISO8601型に変換
	var woy = year;							// 暦週年
	var dt_thu = ordinal + (4 - dow_iso);	// dtと同じ週の木曜日
	if (dt_thu <= 0) dt_thu += days_of_year(--woy);					// 0以下のときは前年
	if (dt_thu > days_of_year(woy)) dt_thu -= days_of_year(woy++);	// 年間日数より大きいときは翌年
	var week_iso = Math.ceil(dt_thu / 7);

	// UTCとの時差
	var timezone = 'Z';
	if (tz_off !== 0) {
		timezone = (tz_off < 0 ? '+' : '-');
		timezone += zero_padding(Math.floor(Math.abs(tz_off) / 60), 2);
		timezone += ':';
		timezone += zero_padding(Math.abs(tz_off) % 60, 2);
	}

	// 元号
	var era = 5;			// era_name[]のindex番号
	var era_year = year;	// 元号年
	for (var i = 0; i < era_name['start'].length - 1; i++) {
		if (dt >= era_name['start'][i] && dt < era_name['start'][i + 1]) {
			era = i;
			era_year -= era_name['start'][i].getFullYear() - 1;
			break;
		}
	}

	// 年
	format = format.replace(/YYYY/g, zero_padding(year, 4));
	format = format.replace(/yyyy/g, year);
	format = format.replace(/eee/g, year + 660);	// 神武天皇即位紀元

	// 元号
	format = format.replace(/ggg/g, era_name['jp'][era]);
	format = format.replace(/gg/g, era_name['jp'][era].slice(0, 1));
	format = format.replace(/g/g, '\元号略称');		// 元号の頭文字に書式文字が含まれるためのEscape
	format = format.replace(/EE?/g, era_year == 1 ? '元' : function(match) {return match.toLowerCase()});
	format = format.replace(/ee/g, zero_padding(era_year, 2));
	format = format.replace(/e/g, era_year);

	// 月
	format = format.replace(/MMMM/g, '\月名称');	// 月の英名に書式文字が含まれるためのEscape
	format = format.replace(/MMM/g, '\月略称');		// 同上
	format = format.replace(/MM/g, zero_padding(month, 2));
	format = format.replace(/M/g, month);

	// 日
	format = format.replace(/dddd/g, zero_padding(ordinal, 3));
	format = format.replace(/ddd/g, ordinal);
	format = format.replace(/dd/g, zero_padding(day, 2));
	format = format.replace(/d/g, day);

	// 曜日
	format = format.replace(/WWW/g, '\曜日名称');	// 曜日の英名に書式文字が含まれるためのEscape
	format = format.replace(/WW/g, '\曜日略称');	// 同上
	format = format.replace(/W/g, dow_iso);			// 曜日番号(ISO8601)
	format = format.replace(/wwww/g, zero_padding(woy, 4));			// 暦週年(ISO8601)
	format = format.replace(/www/g, woy);			// 同上
	format = format.replace(/ww/g, 'W' + zero_padding(week_iso, 2));	// 週番号(ISO8601 format)
	format = format.replace(/w/g, week_iso);		// 週番号(ISO8601)

	// 時刻
	format = format.replace(/HH/g, zero_padding(hour, 2));
	format = format.replace(/H/g, hour);
	format = format.replace(/hh/g, zero_padding(hour12 , 2));
	format = format.replace(/h/g, hour12);
	format = format.replace(/mm/g, zero_padding(minute, 2));
	format = format.replace(/m/g, minute);
	format = format.replace(/ss/g, zero_padding(second, 2));
	format = format.replace(/s/g, second);
	format = format.replace(/SSS/g, zero_padding(milisec, 3));
	format = format.replace(/S/g, milisec);
	format = format.replace(/tt/g, ampm[locale][hour >= 12 ? 1 : 0]);

	// UTCとの時差
	format = format.replace(/ZZ/g, timezone);
	format = format.replace(/Z/g, timezone.replace(/:/, ''));

	// Escape処理の戻し
	month--;
	format = format.replace(/\元号略称/g, era_name['en'][era]);
	format = format.replace(/\月名称/g, month_name[locale][month]);
	format = format.replace(/\月略称/g, month_name[locale][month].slice(0, 3) + ((locale == 'en' && month != 4) ? '.' : ''));
	format = format.replace(/\曜日名称/g, dow_name[locale][dow] + (locale == 'jp' ? '曜日' : ''));
	format = format.replace(/\曜日略称/g, dow_name[locale][dow].slice(0, 3));

	return format;
}

正当なCSSです!