サイトアイコン わんすけに聞いてみる

JavascriptでVBAのFormat(日付)みたいなことをやってみる。

JavascriptのDateオブジェクトが使いにくかったのでOffice VBAで良く使うFormat関数みたいな処理ができるものを書いてみました。

主な書式は、MSDNを参考にしてExcelマクロの実行結果と見比べながら作ってます。

formatDate_vba(date, format)

dateに日付型object、formatに書式設定文字を入れて使います。

 

ポイント

(firstweekofyear の設定は、(規定)のvbFirstJan1と同じ結果になってると思います。)

※ 対応しているのは日付のフォーマットのみです。

曜日と月の英語表記がd とか m、nと被ってて変になるとこあったのでごちょごちょと置換して体裁を保っています。

コード
function formatDate_vba(date, format){
  // 定義済み書式への対応
  switch(format) {
    case '': format = 'yyyy/mm/dd hh:nn:ss';
      break;
    case 'Long Date': format = 'yyyy年m月d日';
      break;
    case 'Medium Date': format = 'mm-dd-yy';
      break;
    case 'Short Date': format = 'yyyy/mm/dd'
      break;
    case 'Long Time': format = 'hh:nn:ss';
      break;
    case 'Medium Time': format = 'AMPM:nn apj';
      break;
    case 'Short Time': format = 'hh:nn';
      break;
  }
  // まず他の定義に置換できる定義
  format = format.replace(/c/g, 'ddddd ttttt');
  format = format.replace(/dddddd/g, 'mmmm dd,yyyy');
  format = format.replace(/ddddd/g, 'yyyy/mm/dd');
  format = format.replace(/ttttt/g, 'h:nn:ss');
  // 曜日と月の文字が他の置換文字と競合するので代替え文字にして最後に復帰
  // 曜日
  var w = date.getDay();
  var aaa = ["日", "月", "火", "水", "木", "金", "土"][w];
  format = format.replace(/aaaa/g, aaa + "曜日");
  format = format.replace(/aaa/g, aaa);
  var $dddd$ = ["$Z0$", "$Z1$", "$Z2$", "$Z3$", "$Z4$", "$Z5$", "$Z6$"][w];
  var dddd = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][w];
  format = format.replace(/dddd/g, $dddd$);
  var $ddd$ = ["$X0$", "$X1$", "$X2$", "$X3$", "$X4$", "$X5$", "$X6$"][w];
  var ddd = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][w];
  format = format.replace(/ddd/g, $ddd$);
  // 月
  var m = date.getMonth();
  var $mmmm$ = ["$%1$", "$%2$", "$%3$", "$%4$", "$%5$", "$%6$", "$%7$", "$%8$", "$%9$", "$%10$", "$%11$", "$%12$"][m];
  var mmmm = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][m];
  format = format.replace(/mmmm/g, $mmmm$);
  var $mmm$ = ["$!1$", "$!2$", "$!3$", "$!4$", "$!5$", "$!6$", "$!7$", "$!8$", "$!9$", "$!10$", "$!11$", "$!12$"][w];
  var mmm = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][w];
  format = format.replace(/mmm/g, $mmm$);
  // 年 ここから
  var yyyy = date.getFullYear();
  format = format.replace(/yyyy/g, yyyy);
  format = format.replace(/yy/g, String(yyyy).slice(-2));
  // y 年始から何日目か?
  var DAY_MSEC = 24*60*60*1000;
  var y = Math.floor((date.getTime() - new Date(yyyy, 0, 1).getTime()) / DAY_MSEC)+1;
  format = format.replace(/y/g, y);
  // 和暦の年号
  var g_m = new Date(1868, 8, 8);
  var g_t = new Date(1912, 6, 30);
  var g_s = new Date(1926, 11, 25);
  var g_h = new Date(1989, 0, 8);
  var g, gg, ggg, e_base;
  if (date<g_t){
    g="M"; gg="明"; ggg="明治";
    e_base=g_m.getFullYear()-1;
  } else if (date<g_s) {
    g="T"; gg="大"; ggg="大正";
    e_base=g_t.getFullYear()-1;
  } else if (date<g_h) {
    g="S"; gg="昭"; ggg="昭和";
    e_base=g_s.getFullYear()-1;
  } else {
    g="H"; gg="平"; ggg="平成";
    e_base=g_h.getFullYear()-1;
  }
  format = format.replace(/ggg/g, ggg);
  format = format.replace(/gg/g, gg);
  format = format.replace(/g/g, g);
  format = format.replace(/ee/g, ("0" + (yyyy - e_base)).slice(-2));
  format = format.replace(/e/g, yyyy - e_base);
  // 月 ここから
  // 四半期の判定
  var q = (m<3)?1:(m<6)?2:(m<9)?3:4;
  format = format.replace(/q/g, q);
  m++;
  format = format.replace(/mm/g, ('0' + m).slice(-2));
  // m のreplaceは am/pm のreplaceと競合する為、最後に行う。
  format = format.replace(/oooo/g, m + "月");
  // 日 ここから
  var d = date.getDate();
  format = format.replace(/dd/g, ('0' + d).slice(-2));
  format = format.replace(/d/g, d);
  // ww 1年の何週目か?
  var WEEK_MSEC = DAY_MSEC*7;
  var ww = Math.floor((date.getTime() - new Date(yyyy, 0, 1).getTime()) / WEEK_MSEC)+1;
  format = format.replace(/ww/g, ww);
  format = format.replace(/w/g, w + 1);
  // 時 ここから
  var h = date.getHours();
  var hh = ('0' + h).slice(-2);
  format = format.replace(/hh/g, hh);
  format = format.replace(/h/g, h);
  // 分 ここから
  var n = date.getMinutes();
  format = format.replace(/nn/g, ('0' + n).slice(-2));
  format = format.replace(/n/g, n);
  // 秒 ここから
  var s = date.getSeconds();
  format = format.replace(/ss/g, ('0' + s).slice(-2));
  format = format.replace(/s/g, s);
  // AM PM 小文字の m は月の m と被るから代替文字で退避
  var aphh = h > 12 ? h-12:h ;
  format = format.replace(/AMPM/g, aphh);
  if (h > 12) {
    format = format.replace(/apj/g, "午後");
    format = format.replace(/AM\/PM/g, "PM");
    format = format.replace(/am\/pm/g, "pz\\");
    format = format.replace(/A\/P/g, "P");
    format = format.replace(/a\/p/g, "p");
  } else {
    format = format.replace(/apj/g, "午前");
    format = format.replace(/AM\/PM/g, "AM");
    format = format.replace(/am\/pm/g, "az\\");
    format = format.replace(/A\/P/g, "A");
    format = format.replace(/a\/p/g, "a");
  }
  // 競合文字の復帰 am/pm で被る m を置換してから代替文字を戻す。
  format = format.replace(/m/g, m);
  format = format.replace(/az\\/g, "am");
  format = format.replace(/pz\\/g, "pm");
  format = format.replace($dddd$, dddd);
  format = format.replace($ddd$, ddd);
  format = format.replace($mmmm$, mmmm);
  format = format.replace($mmm$, mmm);
  return format;
}
使い方の一例
rslt = formatDate_vba(new Date(2018, 0 ,1, 10, 30), '');
console.log(rslt);
// コンソール出力 → 2018/01/01 10:30:00
rslt = formatDate_vba(new Date(2018, 0 ,1, 10, 30), "Long Date");
console.log(rslt);
// コンソール出力 → 2018年1月1日
rslt = formatDate_vba(new Date(2018, 5 ,9, 10, 30), "Medium Date");
console.log(rslt);
// コンソール出力 → 06-09-18
rslt = formatDate_vba(new Date(2018, 0 ,1, 10, 30), "Medium Time");
console.log(rslt);
// コンソール出力 → 10:30 午前
rslt = formatDate_vba(new Date(2018, 0 ,1, 10, 30), "Short Date");
console.log(rslt);
// コンソール出力 → 2018/01/01
rslt = formatDate_vba(new Date(2018, 0 ,1, 10, 30), "Long Time");
console.log(rslt);
// コンソール出力 → 10:30:00
rslt = formatDate_vba(new Date(2018, 0 ,1, 10, 30), "Short Time");
console.log(rslt);
// コンソール出力 → 10:30
rslt = formatDate_vba(new Date(2018, 0 ,1, 10, 30), "c");
console.log(rslt);
// コンソール出力 → 2018/01/01 10:30:00
rslt = formatDate_vba(new Date(2018, 0 ,1, 15, 30), "ggge年m月d日(aaa) AMPM:nn AM/PM");
console.log(rslt);
// コンソール出力 → 平成30年1月1日(月) 3:30 PM
rslt = formatDate_vba(new Date(2018, 0 ,1, 10, 30), "dddddd");
console.log(rslt);
// コンソール出力 → January 01,2018
rslt = formatDate_vba(new Date(2018, 10 , 6, 10, 30), "yyyy年 y日目、ww週目、q期目");
console.log(rslt);
// コンソール出力 → 2018年 310日目、45週目、4期目
rslt = formatDate_vba(new Date(2018, 10 , 6, 10, 30), "mmmm dddd ddd");
console.log(rslt);
// コンソール出力 → November Tuesday Tue

今度は、逆にいろんな日付フォーマットをDate型に解釈できる関数でも用意してみようかな?

 

モバイルバージョンを終了