アルゴリズム

生年月日から計算


和暦元号Y年M月D日 W曜日
満年齢N歳
干支干支(えと)
星座星座(せいざ)
閏年
ラッキーナンバー

アルゴリズムの解説

  • 年齢
  • 和暦
  • 干支
  • 星座
  • 閏年
  • ラッキーナンバー

「○歳○ヶ月と○日」まで求めました。

年月…現在年月から生まれ年月を引きます。まだ現在年の誕生日を迎えていない場合、1歳減らし、11ヶ月足します。

日…現在日から生まれ日を引きます。差がマイナスになった場合、1か月減らし、①現在年の誕生日から当月末までの日数と②現在日付の月初日から当日までの日数を算出し、合計します。さらに、月ごとに日数は異なるため、現在日・生年月日ともに月末日であれば、差は0日として1か月足します。

※うるう日を考慮していないため、うるう日前後の日数カウントが不正確です。

/// <summary>
/// 年齢
/// </summary>
/// <params name="birthday">生年月日</params>
/// <returns>年齢</returns>
function getAge(birthday) {
  // 今日
  let today = new Date(document.getElementById('today').value);
  // 今年の誕生日
  let thisBirthday = new Date(today.getFullYear(), birthday.getMonth(), birthday.getDate());
  // 年月日の差分
  let y = today.getFullYear() - birthday.getFullYear();
  let m = today.getMonth() - birthday.getMonth();
  let d = today.getDate() - birthday.getDate();
  // 今年の誕生日前
  if (today < thisBirthday) {
    y--;
    m += 11;
  }
  if (d < 0) {
    m--;
    let endDay = new Date(thisBirthday.getFullYear(), thisBirthday.getMonth() + 1, 0);
    d = endDay.getDate() - thisBirthday.getDate();
    d += today.getDate();
    // 月末日
    if (isMonthEndDay(thisBirthday) == true) {
      if (isMonthEndDay(today) == true) {
        m++;
        d = 0;
      }
    }
  }
  // 単位
  y += '歳';
  m += 'ヶ月';
  d += '日';
  // 今日が誕生日
  let happyBirthday = '';
  if (today.toDateString() == thisBirthday.toDateString()) {
    happyBirthday = '🎂';
  }
  return y + m + d + happyBirthday;
}

/// <summary>
/// 月末日判定
/// </summary>
/// <params name="date">日付</params>
/// <returns>真偽値</returns>
function isMonthEndDay(date) {
  let endDay = new Date(date.getFullYear(), date.getMonth() + 1, 0);
  if (endDay.getDate() == date.getDate()) {
    return true;
  }
  return false;
}

日付のプロパティに、和暦フォーマット「元号Y年M月D日 W曜日」があります。

和暦 = 日付.toLocaleDateString('ja-JP-u-ca-japanese', {dateStyle: 'full'});

ちなみに、「yyyy-MM-dd」形式の日付フォーマットは、下記のように取得します。

日付 = new Date().toLocaleDateString('sv-SE');

年を12で割った余りを、十二支の配列に当てはめます。※詳細は「干支」を参照

/// <summary>
/// 干支
/// </summary>
const etos = [
  '🐵 申(さる)',
  '🐔 酉(とり・にわとり)',
  '🐶 戌(いぬ)',
  '🐗 亥(い・いのしし)',
  '🐭 子(ね・ねずみ)',
  '🐮 丑(うし)',
  '🐯 寅(とら)',
  '🐰 卯(う・うさぎ)',
  '🐉 辰(たつ・りゅう)',
  '🐍 巳(み・へび)',
  '🐴 午(うま)',
  '🐏 未(ひつじ)'
];
干支 = etos[年 % 12];

生年月日が、どの星座の期間(開始月日、終了月日)に該当するかを判定します。
JavaScriptの日付.getMonth()関数は、月の数字名ではなく、インデックスを返すので、+1する必要がある点に注意が必要です。月名を数字で呼ぶ国は日本だけです。

01234567891011
1月2月3月4月5月6月7月8月9月10月11月12月
/// <summary>
/// 星座
/// </summary>
/// <params name="birthday">生年月日</params>
/// <returns>星座</returns>
function getZodiac(birthday) {
  const zodiacs = [
    ['♓ 魚座(うおざ)', 2, 19, 3, 20],
    ['♈ 牡羊座(おひつじざ)', 3, 21, 4, 19],
    ['♉ 牡牛座(おうしざ)', 4, 20, 5, 20],
    ['♊ 双子座(ふたござ)', 5, 21, 6, 21],
    ['♋ 蟹座(かにざ)', 6, 22, 7, 22],
    ['♌ 獅子座(ししざ)', 7, 23, 8, 22],
    ['♍ 乙女座(おとめざ)', 8, 23, 9, 22],
    ['♎ 天秤座(てんびんざ)', 9, 23, 10, 23],
    ['♏ 蠍座(さそりざ)', 10, 24, 11, 22],
    ['♐ 射手座(いてざ)', 11, 23, 12, 21],
    ['♑ 山羊座(やぎざ)', 12, 22, 1, 19],
    ['♒ 水瓶座(みずがめざ)', 1, 20, 2, 18],
  ];
  let zodiac = '';
  for (let i = 0; i < 12; i++) {
    var m = birthday.getMonth() + 1;
    var d = birthday.getDate();
    if (m == zodiacs[i][1]) {
      if (d >= zodiacs[i][2]) {
        zodiac = zodiacs[i][0];
      }
    }
    if (m == zodiacs[i][3]) {
      if (d <= zodiacs[i][4]) {
        zodiac = zodiacs[i][0];
      }
    }
  }
  return zodiac;
}

論理演算子が文字化けするため、if文を入れ子にしています。※詳細は「閏年の判定アルゴリズム」を参照

/// <summary>
/// 閏年
/// </summary>
/// <params name="year">西暦</params>
/// <returns>真偽値</returns>
function isLeapYear(year) {
  if (year % 400 == 0) {
    return true;
  }
  if (year % 100 != 0) {
    if (year % 4 == 0) {
      return true;
    }
  }
  return false;
}

ラッキーナンバーとは、数秘術による誕生日占いです。生年月日を数字に分解し、1桁になるまで足し算を繰り返します。(例:「2019年1月31日」→「20190131」→「2+0+1+9+0+1+3+1」→「17」→「1+7」→「8」)

2桁の数字がぞろ目になった場合は、ぞろ目がラッキーナンバーになります。

/// <summary>
/// 1桁になるまで、各桁の数字の足し算を繰り返す
/// </summary>
/// <params name="num">数値文字列</params>
/// <returns>1桁の数字</returns>
function getLuckyNumber(num) {
  var str = String(num).replace(/[^0-9]/g, '');
  do {
    var arr = str.split('');
    var sum = 0;
    for (let i = 0; i < arr.length; i++) {
      sum += Number(arr[i]);
    }
    str = String(sum);
    // ぞろ目判定
    if (str.length == 2) {
      if (str[0] == str[1]) {
        break;
      }
    }
  } while(str.length > 1);
  return str;
}

「数字を分解し、1桁になるまで、各位の数字を足し算する」というロジックは、チェックデジットのアルゴリズムなどにも応用できます。



コメント