開始日からの経過年月を自動で計算する機能をJavaScriptで実装する方法【ポートフォリオに最適】

ポートフォリオサイトなどで自身のスキルを示したい時、経験年月を合わせて記載することが多いかと思います。

参考:筆者のポートフォリオサイト

HTMLで年月をベタ書きしてしまうと、1ヶ月おきに手動で更新する必要があるので、手間がかかりますね。

そこで今回の記事では、経験年月日を自動で計算して表示するJavaScriptコードを紹介します。

この記事を読むことで、以下のような機能を実装することができます。

  • ページをロードするたびに自動で経験年・月・日数を表示
  • 開始日を入力するだけなので、更新の必要はなし

ポートフォリオサイトなどで経験年数を表示したいという方には特に役に立つかと思いますので、ぜひ参考にしてみてください。

目次

経過年月を自動計算する機能の実装DEMO

日本語版と英語版を用意しましたので、以下からご確認ください。

CSSは最低限にしていますので、見た目を変更したい場合は自身でカスタマイズしてください。

日本語版のDEMO

HTML & CSS

JavaScript

PHP

英語版のDEMO

HTML & CSS

JavaScript

PHP

以上、日本語版と英語版のDEMOを紹介しました。

年月の部分は、HTMLに直書きではなくJavaScriptで生成しています。

【コピペ用】経過年月を自動計算する機能の実装コード一式

HTML・CSS・JavaScriptの実装コードを一式用意しましたので、コピペしてお使いください。

HTML

<div class="skill-card js-skill-card">
  <p class="skill-name">HTML & CSS</p>
  <p class="skill-exp" data-started-date="2018-01-01"></p>
</div>

<div class="skill-card js-skill-card">
  <p class="skill-name">JavaScript</p>
  <p class="skill-exp" data-started-date="2020-08-01"></p>
</div>

<div class="skill-card js-skill-card">
  <p class="skill-name">PHP</p>
  <p class="skill-exp" data-started-date="2021-11-12"></p>
</div>

data-started-dateには、サンプルコードと同じフォーマットで開始日を記入してください。

CSS

/* スキルを囲うカード部分 */
.skill-card {
  border: 1px solid #333;
  margin-top: 20px;
  padding: 10px;
}

/* スキル名 */
.skill-name {
  font-size: 16px;
  font-weight: bold;
}

/* スキルの経験年月 */
.skill-exp {
  font-size: 16px;
}

JavaScript

JavaScriptは日本語版と英語版でコード内容が異なるので、お好きな方をお使いください。

日本語版のJavaScriptコード

window.addEventListener("DOMContentLoaded", () => {
  // スキルの要素を全て取得
  const skillCards = document.querySelectorAll(".js-skill-card");

  skillCards.forEach((card) => {
    // 経験年数を表示するpタグを取得
    const skillTextEl = card.querySelector(".skill-exp");

    // data-started-dateに設定した開始日のミリ秒数を取得
    const skillStartedDate = new Date(skillTextEl.dataset.startedDate);
    // 現在時間のミリ秒数を取得
    const currentDate = new Date();
    // 開始日と現在の時間差を計算
    const diff = currentDate - skillStartedDate;

    // 年の数値を計算
    const year = Math.floor(diff / 1000 / 60 / 60 / 24 / 30 / 12);
    // 月の数値を計算
    const month = Math.floor(diff / 1000 / 60 / 60 / 24 / 30) % 12;

    // 文字列を格納するための変数
    let outputStr = "";

    // 年のテキストを生成(0の場合は表示しない)
    if (year !== 0) {
      outputStr += `${year}年`;
    }

    // 月のテキストを生成(0の場合は表示しない)
    if (month !== 0) {
      outputStr += `${month}ヶ月`;
    }

    // 年と月が両方0のとき、"1ヶ月未満"を表示
    if (year == 0 && month == 0) {
      outputStr += "1ヶ月未満";
    }

    // 完成したテキストをpタグに挿入
    skillTextEl.innerHTML = outputStr;
  });
});

英語版のJavaScriptコード

window.addEventListener("DOMContentLoaded", () => {
  // スキルの要素を全て取得
  const skillCards = document.querySelectorAll(".js-skill-card");
  skillCards.forEach((card) => {
    // 経験年数を表示するpタグを取得
    const skillEl = card.querySelector(".skill-exp");

    // data-started-dateに設定した開始日のミリ秒数を取得
    const skillStartedDate = new Date(skillEl.dataset.startedDate);
    // 現在時間のミリ秒数を取得
    const currentDate = new Date();
    // 開始日と現在の時間差を計算
    const diff = currentDate - skillStartedDate;

    // 年の数値を計算
    const year = Math.floor(diff / 1000 / 60 / 60 / 24 / 30 / 12);
    // 月の数値を計算
    const month = Math.floor(diff / 1000 / 60 / 60 / 24 / 30) % 12;

    // 文字列を格納するための変数
    let outputStr = "";

    // 文字列' and 'の表示/非表示を判別するための変数
    let showAnd;

    // 年か月のどちらかが0の場合、'and'を表示しない
    if (year === 0 || month === 0) {
      showAnd = false;
    } else {
      showAnd = true;
    }

    // 年のテキストを生成
    if (year === 0) {
      // 0の場合は非表示
      outputStr += "";
    } else if (year === 1) {
      // 1の場合は単数形(year)
      outputStr += `${year}year`;
    } else {
      // 1以上の場合は複数形(years)
      outputStr += `${year}years`;
    }

    // showAndがtrueの時、文字列' and 'を追加
    if (showAnd) {
      outputStr += " and ";
    }

    // 月のテキストを生成
    if (month === 0) {
      // 0の場合は非表示
      outputStr += "";
    } else if (month === 1) {
      // 1の場合は単数形(month)
      outputStr += `${month}month`;
    } else {
      // 1以上の場合は複数形(months)
      outputStr += `${month}months`;
    }

    // 年と月が両方0のとき
    if (year === 0 && month === 0) {
      outputStr += "Less than 1 month";
    }

    // pタグにテキストを挿入
    skillEl.innerHTML = outputStr;
  });
});

以上でコピペ用コードの紹介は終わりです。

次からはコードを理解したい・カスタマイズしたい方に向けて解説していきますので、興味がある方は読み進めてください。

【解説】経過年月を自動計算する機能の解説

ここからは実装コードの解説をしていきます。

  1. HTMLでタグを用意&data属性に開始日を記入
  2. CSSで見た目を装飾
  3. JavaScriptで経過年月を計算してDOMに表示

上記の順番で説明していきますね。

HTMLの解説

まずはHTMLから見ていきます。

<div class="skill-card js-skill-card">
  <p class="skill-name">HTML & CSS</p>
  <p class="skill-exp" data-started-date="2018-01-01"></p>
</div>

スキルの要素を囲うdivを用意し、skill-cardjs-skill-cardクラスを付与します。

ここでは、

  • skill-card…CSSでスタイルを指定する用
  • js-skill-card…JavaScriptで取得する用

という風に分けています。

次のポイントとしては、data属性に開始日の日付を入力するところです。

<p class="skill-exp" data-started-date="2018-01-01"></p>

data-started-dateの中には、スキルの開始日の日付を同じフォーマットで記入してください。

この値をJavaScriptで取得して操作することで、最終的には経験年月を計算して表示することができます。

CSSの解説

続いてはCSSをみていきましょう。

/* スキルを囲うカード部分 */
.skill-card {
  border: 1px solid #333;
  margin-top: 20px;
  padding: 10px;
}

/* スキル名 */
.skill-name {
  font-size: 16px;
  font-weight: bold;
}

/* スキルの経験年月 */
.skill-exp {
  font-size: 16px;
}

CSSは今回は必要最低限にしてあるので、特に解説することはありません。

スタイル用のクラスは付けてあるので、自身でカスタマイズしてみてください。

自身のポートフォリオサイトでも使用していますので、よければそちらのスタイルを参考にしてみてください。

JavaScriptの解説

最後はJavaScriptの解説をしていきます。

日本語版と英語版で少しコードが異なりますが、基本的なロジックは同じなので、日本語版の解説をベースに進めていきます。

window.addEventListener("DOMContentLoaded", () => {
  // スキルの要素を全て取得
  const skillCards = document.querySelectorAll(".js-skill-card");

  skillCards.forEach((card) => {
    // 経験年数を表示するpタグを取得
    const skillTextEl = card.querySelector(".skill-exp");

    // data-started-dateに設定した開始日のミリ秒数を取得
    const skillStartedDate = new Date(skillTextEl.dataset.startedDate);
    // 現在時間のミリ秒数を取得
    const currentDate = new Date();
    // 開始日と現在の時間差を計算
    const diff = currentDate - skillStartedDate;

    // 年の数値を計算
    const year = Math.floor(diff / 1000 / 60 / 60 / 24 / 30 / 12);
    // 月の数値を計算
    const month = Math.floor(diff / 1000 / 60 / 60 / 24 / 30) % 12;

    // 文字列を格納するための変数
    let outputStr = "";

    // 年のテキストを生成(0の場合は表示しない)
    if (year !== 0) {
      outputStr += `${year}年`;
    }

    // 月のテキストを生成(0の場合は表示しない)
    if (month !== 0) {
      outputStr += `${month}ヶ月`;
    }

    // 年と月が両方0のとき、"1ヶ月未満"を表示
    if (year == 0 && month == 0) {
      outputStr += "1ヶ月未満";
    }

    // 完成したテキストをpタグに挿入
    skillTextEl.innerHTML = outputStr;
  });
});

上記のコードを大まかに分けると、

  1. カード要素を全て取得する
  2. 経験年月を表示するためのpタグを取得する
  3. data-started-dateに記述した開始日データを利用して、経過年月を計算する
  4. 出力するテキストを調整する
  5. pタグに完成したテキストを挿入する

となるので、分割して解説していきます。

①カード要素(js-skill-card)を全て取得する

まずはカード要素をJavaScriptで操作するために、querySelectorAllで要素を取得します。

HTMLで、js-skill-cardというクラスをカード部分に付与したので、このクラスがついた要素を全て選択します。

const skillCards = document.querySelectorAll(".js-skill-card");

次に、取得した全てのカードひとつひとつに対して処理を実行するために、forEachで以下のように記述します。

skillCards.forEach((card) => {
  // 個々のカードに対しての処理を記述
});

個々のカードはcardという変数に格納されるので、次でカードに対して処理を実行していきます。

②経験年月を表示するためのpタグを取得する

HTMLで用意していた、経験年月を表示するための空のpタグを取得します。

const skillTextEl = card.querySelector(".skill-exp");

HTMLでいう以下の部分ですね。

<p class="skill-exp" data-started-date="2018-01-01"></p>

次でdata-started-dateに入っている数値を取得して経験年数を計算します。

③data属性に設定した開始日を利用して、経験年月を計算する

続いては、経験年月を計算していきます。

経験年月は、

現在の日付 – 開始日の日付

という式で求めることができますね。

これらはJavaScriptのDateオブジェクトを利用することで簡単に取得することができます。

// data-started-dateに設定した開始日のミリ秒数を取得
const skillStartedDate = new Date(skillTextEl.dataset.startedDate);

// 現在時間のミリ秒数を取得
const currentDate = new Date();

// 開始日と現在の時間差を計算
const diff = currentDate - skillStartedDate;

まず開始日のミリ秒数を取得するために、Dateオブジェクトに開始日の時刻値を渡します。

HTMLのデータ属性data-started-dateに指定した値は、以下のようにしてJSで取得することができます。

const skillStartedDate = new Date(skillTextEl.dataset.startedDate);

これで開始日のミリ秒数を取得することができました。

次に現在時刻のミリ秒数を取得するために、引数を渡さないままDateオブジェクトを生成します。

const currentDate = new Date();

これで現在時刻のミリ秒数を取得することができました。

あとは2つの差分を求めることで、ミリ秒単位で開始日から現在時刻までの経過時間がわかります。

const diff = currentDate - skillStartedDate; // 現在の日付 - 開始日の日付

diffに入っている数値はミリ秒なので、これを年と月に変換するため、以下の計算式を記述します。

// 年の数値を計算
const year = Math.floor(diff / 1000 / 60 / 60 / 24 / 30 / 12);
// 月の数値を計算
const month = Math.floor(diff / 1000 / 60 / 60 / 24 / 30) % 12;

1000ミリ秒は1秒なので、

  • 1000で割って秒に変換↓
  • 60で割って分に変換↓
  • 60で割って時間に変換↓
  • 24で割って日に変換↓
  • 30で割って月に変換↓
  • 12で割って年に変換

上記の計算で年と月の値を計算することができます。

これで変数yearには経験年数が、monthには月数が入っている状態になりました。

以上で経験年月のデータは準備できたので、次はアウトプットするためのテキストを生成していきます。

④出力するテキストを調整する

経験年月のテキストは、実際はJavaScript1行で生成することができます。

let outputStr = `${year}年${month}ヶ月`;

しかしこのままだと0が来た場合にも不必要な文字が表示されてしまいます。

  • 年の値が0のとき:0年○ヶ月
  • 月の値が0のとき:○年0ヶ月
  • 年と月の値が0のとき:0年0ヶ月

今回は”0年”や”0ヶ月”を非表示にしたいので、以下のコードを記述します。

// 文字列を格納するための変数
let outputStr = "";

// 年のテキストを生成(0の場合は表示しない)
if (year !== 0) {
  outputStr += `${year}年`;
}

// 月のテキストを生成(0の場合は表示しない)
if (month !== 0) {
  outputStr += `${month}ヶ月`;
}

// 年と月が両方0のとき、"1ヶ月未満"を表示
if (year == 0 && month == 0) {
  outputStr += "1ヶ月未満";
}

これで年か月の値が0の場合に、不必要な文字が表示されなくなりました。

また、年と月どちらも0の場合は、”1ヶ月未満”という文字列を出力するようにしています。

  • 例) 0年6ヶ月→6ヶ月
  • 例) 1年0ヶ月→1年
  • 例) 0年0ヶ月→1ヶ月未満

これで文字列の調整は終わりです!

今回はシンプルな構成にしたかったのでoutputStrには文字列を格納していますが、HTMLタグを使用することもできます。

// HTMLを記述した例
outputStr += `<span class="year-num">${year}</span>年`;

数字部分に特定のスタイルを付与したい場合は、上記のように書いてもOKです。

⑤pタグに完成したテキストを挿入する

経験年月のテキストが完成したので、あとは用意していた空のpタグに挿入します。

skillTextEl.innerHTML = outputStr;

outputStrには完成したテキストが入っているので、innerHTMLプロパティでskillTextElの中身を置き換えます。

これで完成したテキストをpタグ内に表示することができました。

ここまでのコードで、DEMOと同じようなスキルカードを実装することができます!

■完成版(日本語)

HTML & CSS

JavaScript

PHP

以上で日本語版のJavaScriptの解説は終わりなので、次は英語版をみていきましょう。

英語版のJavaScriptコードの解説

英語版と日本語版の違いは、以下の通りです。

  • 年月のテキストを単数形・複数形で分ける必要がある
  • 年と月がどちらも1以上の場合、文字列’and’を追加する

これらを実装するために、テキスト調整部分を書き加える必要があります。

window.addEventListener("DOMContentLoaded", () => {
  // スキルの要素を全て取得
  const skillCards = document.querySelectorAll(".js-skill-card");
  skillCards.forEach((card) => {
    // 経験年数を表示するpタグを取得
    const skillEl = card.querySelector(".skill-exp");

    // data-started-dateに設定した開始日のミリ秒数を取得
    const skillStartedDate = new Date(skillEl.dataset.startedDate);
    // 現在時間のミリ秒数を取得
    const currentDate = new Date();
    // 開始日と現在の時間差を計算
    const diff = currentDate - skillStartedDate;

    // 年の数値を計算
    const year = Math.floor(diff / 1000 / 60 / 60 / 24 / 30 / 12);
    // 月の数値を計算
    const month = Math.floor(diff / 1000 / 60 / 60 / 24 / 30) % 12;

    // 文字列を格納するための変数
    let outputStr = "";

    // 文字列' and 'の表示/非表示を判別するための変数
    let showAnd;

    // 年か月のどちらかが0の場合、'and'を表示しない
    if (year === 0 || month === 0) {
      showAnd = false;
    } else {
      showAnd = true;
    }

    // 年のテキストを生成
    if (year === 0) {
      // 0の場合は非表示
      outputStr += "";
    } else if (year === 1) {
      // 1の場合は単数形(year)
      outputStr += `${year}year`;
    } else {
      // 1以上の場合は複数形(years)
      outputStr += `${year}years`;
    }

    // showAndがtrueの時、文字列' and 'を追加
    if (showAnd) {
      outputStr += " and ";
    }

    // 月のテキストを生成
    if (month === 0) {
      // 0の場合は非表示
      outputStr += "";
    } else if (month === 1) {
      // 1の場合は単数形(month)
      outputStr += `${month}month`;
    } else {
      // 1以上の場合は複数形(months)
      outputStr += `${month}months`;
    }

    // 年と月が両方0のとき
    if (year === 0 && month === 0) {
      outputStr += "Less than 1 month";
    }

    // pタグにテキストを挿入
    skillEl.innerHTML = outputStr;
  });
});

まずは文字列’and’の表示/非表示のロジックから確認していきます。

// 文字列' and 'の表示/非表示を判別するための変数
let showAnd;

// 年か月のどちらかが0の場合、'and'を表示しない
if (year === 0 || month === 0) {
  showAnd = false;
} else {
  showAnd = true;
}

変数showAndの値がtrueなら”and”を表示、falseなら非表示にしたいので、yearmonth両方とも1以上の場合はtrueを代入します。

この状態で以下のコードを記述することで、”and”の表示/非表示を切り替えることができます。

// showAndがtrueの時、文字列' and 'を追加
if (showAnd) {
  outputStr += " and ";
}

続いては、単数形・複数形に応じてテキストを変更する方法を見ていきます。

手順は簡単で、if文で数値が0・1もしくはそれ以上かどうかを判別し、それぞれの場合に合わせてテキストを書き換えるだけです。

// 年のテキストを生成
if (year === 0) {
  // 0の場合は非表示
  outputStr += "";
} else if (year === 1) {
  // 1の場合は単数形(year)
  outputStr += `${year}year`;
} else {
  // 1以上の場合は複数形(years)
  outputStr += `${year}years`;
}

このコードで、0の場合は非表示に、1の場合はyearに、1以上の場合はyearsになるようテキストを変更することができました。

これで以下のようなスキルカードを実装することが可能です。

HTML & CSS

JavaScript

PHP

以上でJavaScriptコードの解説は終わりです!

【まとめ】開始日からの経過年月を自動で計算する機能をJavaScriptで実装する方法

今回の記事では、開始日から経験年月を表示する機能の実装方法を紹介しました。

ポートフォリオでスキルの経験年月をアピールしたい場合に使えるかと思いますので、ぜひ試してみてください。

これに合わせて、画面内に表示されると横に伸びるスキルバーを設置するとよりカッコ良くなるかと思いますので、以下の記事も合わせてご覧ください。

記事が役に立ったらサポートしてください

Web制作に関する
記事案を募集中!

Web制作について知りたいこと、質問等ありましたら、以下のフォームから気軽に投稿してください。
要望が多かったものは解説記事を作成します。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメント一覧 (2件)

  • はじめまして!
    こちらのコードを参考にさせていただきました!
    私はあまりjsに詳しくないのですが、詳しく説明していただき大変助かっています。
    1点、こちらの場合は、年月まで記載してくれるのですが、1年未満は「○ヶ月」のみ、1年以上は「○年」のみにするのはできるのでしょうか?
    もしよろしければ教えてもらえると嬉しいです!

    • 返事が遅くなり大変申し訳ないです・・!もう解決されているかもしれませんが、JSを以下のコードに差し替えると実装可能です!


      window.addEventListener("DOMContentLoaded", () => {
      // スキルの要素を全て取得
      const skillCards = document.querySelectorAll(".js-skill-card");

      skillCards.forEach((card) => {
      // 経験年数を表示するpタグを取得
      const skillTextEl = card.querySelector(".skill-exp");

      // data-started-dateに設定した開始日のミリ秒数を取得
      const skillStartedDate = new Date(skillTextEl.dataset.startedDate);
      // 現在時間のミリ秒数を取得
      const currentDate = new Date();
      // 開始日と現在の時間差を計算
      const diff = currentDate - skillStartedDate;

      // 年の数値を計算
      const year = Math.floor(diff / 1000 / 60 / 60 / 24 / 30 / 12);

      // 月の数値を計算
      const month = Math.floor(diff / 1000 / 60 / 60 / 24 / 30) % 12;

      // 文字列を格納するための変数
      let outputStr = "";

      if (year >= 1) {
      outputStr += `${year}年`;
      } else if (month > 0) {
      outputStr += `${month}ヶ月`;
      } else {
      outputStr += "1ヶ月未満";
      }

      // 完成したテキストをpタグに挿入
      skillTextEl.innerHTML = outputStr;
      });
      });

      簡単に説明すると、
      ・yearの値が1以上の時は、year + 年を表示
      ・yearの値が1以下の時は、month + 月を表示
      ・yearの値が1以下 & monthの値が1以下の時は、’1ヶ月未満’を表示
      というロジックになります。

コメントする

目次