Upupoo网页壁纸自定义扩展:农历显示与每日一句

Upupoo の HTML ベースの壁紙機能は、自由にカスタマイズできる点が魅力的です。其中广泛关注的一个 HTML 壁紙では、日付や時間の表示に加え、もっと凝った機能を追加したくなる場面があります。ここでは、农历(旧暦)情報を表示する機能と、曜日ごとに異なるメッセージ(「今日の一言」)を表示する実装について解説します。

农历変換ロジックの導入

まず、HTML 内に农历変換用の JavaScript 関数を追加します。これらの関数は、西暦日付を农历年月日に変換します。

// 天干地支・数字・月名・干支等相关定義
var tgString = "甲乙丙丁戊己庚辛壬癸";
var dzString = "子丑寅卯辰巳午未申酉戌亥";
var numString = "一二三四五六七八九十";
var monString = "正二三四五六七八九十冬腊";
var sx = "鼠牛虎兔龙蛇马羊猴鸡狗猪";

// 旧暦データ(1921〜2020年の各月の大小・閏月情報を圧縮)
var CalendarData = [
  0xA4B,0x5164B,0x6A5,0x6D4,0x415B5,0x2B6,0x957,0x2092F,0x497,0x60C96,0xD4A,0xEA5,
  0x50DA9,0x5AD,0x2B6,0x3126E,0x92E,0x7192D,0xC95,0xD4A,0x61B4A,0xB55,0x56A,0x4155B,
  0x25D,0x92D,0x2192B,0xA95,0x71695,0x6CA,0xB55,0x50AB5,0x4DA,0xA5B,0x30A57,0x52B,
  0x8152A,0xE95,0x6AA,0x615AA,0xAB5,0x4B6,0x414AE,0xA57,0x526,0x31D26,0xD95,0x70B55,
  0x56A,0x96D,0x5095D,0x4AD,0xA4D,0x41A4D,0xD25,0x81AA5,0xB54,0xB6A,0x612DA,0x95B,
  0x49B,0x41497,0xA4B,0xA164B,0x6A5,0x6D4,0x615B4,0xAB6,0x957,0x5092F,0x497,0x64B,
  0x30D4A,0xEA5,0x80D65,0x5AC,0xAB6,0x5126D,0x92E,0xC96,0x41A95,0xD4A,0xDA5,0x20B55,
  0x56A,0x7155B,0x25D,0x92D,0x5192B,0xA95,0xB4A,0x416AA,0xAD5,0x90AB5,0x4BA,0xA5B,
  0x60A57,0x52B,0xA93,0x40E95
];

var madd = [0,31,59,90,120,151,181,212,243,273,304,334];

// ビット操作用補助関数
function getBit(num, pos) {
  return (num >> pos) & 1;
}

// 西暦から旧暦の年月日を計算
function updateLunarDate(y, m, d) {
  var total = 0, k, n, loopEnd = false;
  var baseYear = (y < 1900) ? y + 1900 : y;
  
  // 西暦1921年からの経過日数を算出
  total = (baseYear - 1921) * 365 + Math.floor((baseYear - 1921) / 4) + madd[m] + d - 38;
  
  if ((baseYear % 4 === 0 && m > 1)) total++;

  for (var i = 0; i < CalendarData.length; i++) {
    k = (CalendarData[i] < 0xfff) ? 11 : 12;
    for (var j = k; j >= 0; j--) {
      if (total <= 29 + getBit(CalendarData[i], j)) {
        loopEnd = true;
        break;
      }
      total -= 29 + getBit(CalendarData[i], j);
    }
    if (loopEnd) break;
  }
  
  var lunarYear = 1921 + i;
  var lunarMonth = k - j;
  var lunarDay = total;
  
  // 閏月判定処理
  if (k === 12) {
    var leapMonth = Math.floor(CalendarData[i] / 0x10000) + 1;
    if (lunarMonth === leapMonth) {
      lunarMonth = -lunarMonth;
    } else if (lunarMonth > leapMonth) {
      lunarMonth--;
    }
  }
  
  // 表示用に構築
  var ganzhi = tgString.charAt((lunarYear - 4) % 10) + dzString.charAt((lunarYear - 4) % 12);
  var zodiac = sx.charAt((lunarYear - 4) % 12);
  
  var monthStr = (lunarMonth < 0) ? "(閏)" + monString.charAt(-lunarMonth - 1) : monString.charAt(Math.abs(lunarMonth) - 1);
  
  var dayStr = (lunarDay < 11) ? "初" :
               (lunarDay < 20) ? "十" :
               (lunarDay < 30) ? "廿" : "三十";
  
  if (lunarDay % 10 !== 0 || lunarDay === 10) {
    dayStr += numString.charAt((lunarDay - 1) % 10);
  }
  
  return ganzhi + "(" + zodiac + ")年 " + monthStr + "月 " + dayStr;
}

HTML 上で农历表示用要素を追加します。

<div id="lunar-display" style="font-size:24px; font-weight:bold;"></div>

JavaScript で农历情報を定期更新します(毎秒1回)。

// タイマーで毎秒更新
function updateAll() {
  var now = new Date();
  var year = now.getFullYear();
  var month = now.getMonth(); // 0〜11
  var day = now.getDate();

  // 表示用农历
  var lunarText = updateLunarDate(year, month, day);
  document.getElementById("lunar-display").textContent = lunarText;
  // ...他の内容(時刻や曜日など)もここで更新
}

setInterval(updateAll, 1000);

曜日別メッセージ表示

さらに、「曜日ごとに自動で変わる一言」を追加します。このためには、メッセージ配列を曜日に応じて選択するように実装します。

// 素朴な一言リスト(7日分)
var dailyQuotes = [
  "月曜日ですね、気を鼓舞して!",
  "新しい挑戦の始まりです。",
  "水曜日、週の半ばを乗り越えました。",
  " slogans tomorrow!明日はもう一歩。",
  "金曜日、モチベーションを維持!",
  "週末への準備を始めましょう。",
  "_dt=曰:今日も一日おつかれさまだ!"
];

// 内部で使っていた変数と競合しないよう、説明のため簡略化
function updateDailyShout() {
  var today = new Date().getDay(); // 0:日, 1:月, ..., 6:土
  document.getElementById("quote-display").textContent = dailyQuotes[today];
}

既存の HTML に表示エリアを追加して、先ほどの `updateAll()` 関数 inside で呼び出せば OK です。

<div id="quote-display" class="text" style="margin-top:20px;"></div>

実装上の注意点

  • 旧暦付帯データ(十二支・六十干支)は、1921〜2020年までを前提として定義されています。範囲外年月の処理を Silkily 無視しているため、必要に応じて拡張してください。
  • 配列のインデックスや文字列長さの範囲外アクセスを防ぐため、十分なテストを実施してください。
  • `Math.floor` やビット演算の挙動は環境によって差異が出ないよう、意図を明確に保つことが望ましいです。

タグ: javascript 农历 旧暦 HTML壁紙 Upupoo

8月7日 10:57 投稿