JavaScript tips - Date.prototype に簡易 format 機能を実装する方法

phi phi on javascript

JavaScript のコアクラスである Date のメンバメソッドに簡易 format を追加する方法を紹介します.

具体的には, 他の言語によくある d.format('yyyy/MM/dd') とするとその記号に応じて 2016/01/14 といった形にフォーマットした時間文字列を返すメソッドを定義します.

jQuery や underscore, AngularJS なんかでも大抵実装されている便利なメソッドです.

ES6 でいれてくれぇ〜

Runstant Demo

上部分で Date.prototype を拡張して format クラスを定義しています.

下記部分ではその使用例と結果を出力しています. console パネルに結果として今日の日付が表示されているのが分かるかと思います.

Code

コードはこれだけです.

Object.defineProperty(Date.prototype, 'format', {  
  value: function(pattern) {
    var MONTH = [
      'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'
    ];
    var WEEK = [
      'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'
    ];

    var year    = this.getFullYear();
    var month   = this.getMonth();
    var date    = this.getDate();
    var day     = this.getDay();
    var hours   = this.getHours();
    var minutes = this.getMinutes();
    var seconds = this.getSeconds();
    var millseconds = this.getMilliseconds();

    var patterns = {
      'yyyy': String('0000' + year).slice(-4),
      'yy': year.toString().substr(2, 2),
      'y': year,

      'MMMM': MONTH[month],
      'MMM': MONTH[month].substr(0, 3),
      'MM': String('00' + (month+1)).slice(-2),
      'M': (month+1),

      'dd': String('00' + date).slice(-2),
      'd': date,

      'EEEE': WEEK[day],
      'EEE': WEEK[day].substr(0, 3),

      'HH': String('00' + hours).slice(-2),
      'H': hours,

      'mm': String('00' + minutes).slice(-2),
      'm': minutes,

      'ss': String('00' + seconds).slice(-2),
      's': seconds,
    };

    var regstr = '(' + Object.keys(patterns).join('|') + ')';
    var re = new RegExp(regstr, 'g');

    return pattern.replace(re, function(str) {
      return patterns[str];
    });
  },
});

window.onload = function() {  
  var d = new Date();
  console.log('test : ' + d.format('yyyy/MM/dd HH:mm:ss'));
  console.log('year : ' + d.format('yyyy/yy/y'));
  console.log('month: ' + d.format('MMMM/MMM/MM/M'));
  console.log('date : ' + d.format('dd/d'));
  console.log('time : ' + d.format('HH/H mm/m ss/s'));
};

Flow

format の中身の流れについて簡単に解説します.

1. 一通り date の値を取得

使いまわせるようにローカル変数に格納しておきます.

var MONTH = [  
  'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'
];
var WEEK = [  
  'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'
];

var year    = this.getFullYear();  
var month   = this.getMonth();  
var date    = this.getDate();  
var day     = this.getDay();  
var hours   = this.getHours();  
var minutes = this.getMinutes();  
var seconds = this.getSeconds();  
var millseconds = this.getMilliseconds();  

2. 正規表現用のパターンマップを作成

パターン用のマップを作成します. こういった形でデータ化しておくと, 後々パターンの追加も楽にできます!

var patterns = {  
  'yyyy': String('0000' + year).slice(-4),
  'yy': year.toString().substr(2, 2),
  'y': year,

  'MMMM': MONTH[month],
  'MMM': MONTH[month].substr(0, 3),
  'MM': String('00' + (month+1)).slice(-2),
  'M': (month+1),

  'dd': String('00' + date).slice(-2),
  'd': date,

  'EEEE': WEEK[day],
  'EEE': WEEK[day].substr(0, 3),

  'HH': String('00' + hours).slice(-2),
  'H': hours,

  'mm': String('00' + minutes).slice(-2),
  'm': minutes,

  'ss': String('00' + seconds).slice(-2),
  's': seconds,
};

3. フォーマット用の正規表現オブジェクトを作成

Object.keys を使って 2 で作成したマップからキーのみを取得します. それを '|' で join して繋いでカッコで囲います.

var regstr = '(' + Object.keys(patterns).join('|') + ')';  
var re = new RegExp(regstr, 'g');  

4. 正規表現を適用

pattern に対して適用させます.
マッチしたら, マッチした文字列を key として 2 で作成したマップから対応する値を取得し置換します.

return pattern.replace(re, function(str) {  
  return patterns[str];
});

5. あとは使うだけ♪

var d = new Date();  
console.log(d.format('yyyy/MM/dd')); // 今日の日付  

Finally

JavaScript は, このメソッドってないの!? ってことが多々ありますが,
柔軟な言語仕様を活かせば使いやすい言語にしていくことができます!

楽しいですよ♪