329 lines
9.1 KiB
TypeScript
329 lines
9.1 KiB
TypeScript
// pages/date-calc/date-calc.ts
|
|
import { solarToLunar, lunarToSolar, getSolarTerm, getFestival, getLunarFestival } from '../../utils/lunar';
|
|
|
|
Page({
|
|
data: {
|
|
currentTab: 0,
|
|
startDate: '',
|
|
startWeekday: '',
|
|
endDate: '',
|
|
days: 0,
|
|
resultDate: '',
|
|
resultWeekday: '',
|
|
resultLunar: '',
|
|
intervalDays: 0,
|
|
intervalWeeks: 0,
|
|
intervalRemainingDays: 0,
|
|
intervalMonths: 0,
|
|
intervalExtraDays: 0,
|
|
// 农历转换相关
|
|
lunarDirection: 'toL', // 'toL' 公历→农历, 'toS' 农历→公历
|
|
lunarSolarDate: '',
|
|
lunarResult: null as any,
|
|
lunarFestivalText: '',
|
|
solarTermText: '',
|
|
solarFestivalText: '',
|
|
// 农历→公历
|
|
lunarPickerRange: [[] as string[], [] as string[], [] as string[]],
|
|
lunarPickerValue: [0, 0, 0],
|
|
lunarPickerDisplay: '',
|
|
lunarToSolarResult: '',
|
|
lunarToSolarWeekday: '',
|
|
// 今日信息
|
|
todaySolar: '',
|
|
todayLunar: '',
|
|
todayGanZhi: '',
|
|
todayAnimal: '',
|
|
todayTerm: '',
|
|
showHelp: false
|
|
},
|
|
|
|
onShareAppMessage() {
|
|
return {
|
|
title: '实用的日期推算与农历转换工具',
|
|
path: '/pages/date-calc/date-calc'
|
|
}
|
|
},
|
|
|
|
onShareTimeline() {
|
|
return {
|
|
title: '实用的日期推算与农历转换工具'
|
|
}
|
|
},
|
|
|
|
toggleHelp() {
|
|
this.setData({
|
|
showHelp: !this.data.showHelp
|
|
});
|
|
},
|
|
|
|
onLoad() {
|
|
const today = new Date();
|
|
const dateStr = this.formatDate(today);
|
|
this.setData({
|
|
startDate: dateStr,
|
|
endDate: dateStr,
|
|
resultDate: dateStr,
|
|
resultWeekday: this.getWeekday(today),
|
|
startWeekday: this.getWeekday(today),
|
|
lunarSolarDate: dateStr
|
|
});
|
|
|
|
// 初始化农历相关
|
|
this.initLunarPicker();
|
|
this.updateTodayInfo();
|
|
this.convertSolarToLunar(dateStr);
|
|
this.updateResultLunar(today);
|
|
},
|
|
|
|
switchTab(e: any) {
|
|
wx.vibrateShort({ type: 'light' }).catch(() => {});
|
|
this.setData({
|
|
currentTab: parseFloat(e.currentTarget.dataset.index)
|
|
});
|
|
this.calculate();
|
|
},
|
|
|
|
bindDateChange(e: any) {
|
|
const field = e.currentTarget.dataset.field;
|
|
this.setData({
|
|
[field]: e.detail.value
|
|
});
|
|
|
|
if (field === 'startDate') {
|
|
const d = new Date(e.detail.value.replace(/-/g, '/'));
|
|
this.setData({ startWeekday: this.getWeekday(d) });
|
|
}
|
|
|
|
this.calculate();
|
|
},
|
|
|
|
bindDaysInput(e: any) {
|
|
const val = e.detail.value;
|
|
if (val === '-' || val === '') {
|
|
this.setData({ days: val });
|
|
return;
|
|
}
|
|
this.setData({
|
|
days: parseInt(val)
|
|
});
|
|
this.calculate();
|
|
},
|
|
|
|
setDays(e: any) {
|
|
wx.vibrateShort({ type: 'light' }).catch(() => {});
|
|
const days = parseInt(e.currentTarget.dataset.days);
|
|
this.setData({ days: days });
|
|
this.calculate();
|
|
},
|
|
|
|
calculate() {
|
|
if (this.data.currentTab === 0) {
|
|
const start = new Date(this.data.startDate.replace(/-/g, '/'));
|
|
const dayOffset = typeof(this.data.days) === 'number' ? this.data.days : parseInt(this.data.days || '0');
|
|
const target = new Date(start.getTime() + dayOffset * 24 * 60 * 60 * 1000);
|
|
|
|
this.setData({
|
|
resultDate: this.formatDate(target),
|
|
resultWeekday: this.getWeekday(target)
|
|
});
|
|
this.updateResultLunar(target);
|
|
} else if (this.data.currentTab === 1) {
|
|
const start = new Date(this.data.startDate.replace(/-/g, '/'));
|
|
const end = new Date(this.data.endDate.replace(/-/g, '/'));
|
|
const diffTime = Math.abs(end.getTime() - start.getTime());
|
|
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
|
|
const weeks = Math.floor(diffDays / 7);
|
|
const remainingDays = diffDays % 7;
|
|
const months = Math.floor(diffDays / 30);
|
|
const extraDays = diffDays % 30;
|
|
|
|
this.setData({
|
|
intervalDays: diffDays,
|
|
intervalWeeks: weeks,
|
|
intervalRemainingDays: remainingDays,
|
|
intervalMonths: months,
|
|
intervalExtraDays: extraDays
|
|
});
|
|
}
|
|
},
|
|
|
|
// 更新推算结果的农历信息
|
|
updateResultLunar(date: Date) {
|
|
try {
|
|
const lunar = solarToLunar(date.getFullYear(), date.getMonth() + 1, date.getDate());
|
|
this.setData({
|
|
resultLunar: lunar.monthName + lunar.dayName
|
|
});
|
|
} catch (e) {
|
|
this.setData({ resultLunar: '' });
|
|
}
|
|
},
|
|
|
|
// === 农历转换相关 ===
|
|
|
|
setLunarDirection(e: any) {
|
|
wx.vibrateShort({ type: 'light' }).catch(() => {});
|
|
this.setData({ lunarDirection: e.currentTarget.dataset.dir });
|
|
},
|
|
|
|
toggleLunarDirection() {
|
|
wx.vibrateShort({ type: 'light' }).catch(() => {});
|
|
this.setData({
|
|
lunarDirection: this.data.lunarDirection === 'toL' ? 'toS' : 'toL'
|
|
});
|
|
},
|
|
|
|
onLunarSolarDateChange(e: any) {
|
|
const dateStr = e.detail.value;
|
|
this.setData({ lunarSolarDate: dateStr });
|
|
this.convertSolarToLunar(dateStr);
|
|
},
|
|
|
|
convertSolarToLunar(dateStr: string) {
|
|
try {
|
|
const parts = dateStr.split('-');
|
|
const year = parseInt(parts[0]);
|
|
const month = parseInt(parts[1]);
|
|
const day = parseInt(parts[2]);
|
|
|
|
const result = solarToLunar(year, month, day);
|
|
const term = getSolarTerm(year, month, day);
|
|
const solarFest = getFestival(month, day);
|
|
const lunarFest = getLunarFestival(result.month, result.day);
|
|
|
|
this.setData({
|
|
lunarResult: result,
|
|
solarTermText: term || '',
|
|
solarFestivalText: solarFest || '',
|
|
lunarFestivalText: lunarFest || ''
|
|
});
|
|
} catch (e) {
|
|
console.error('农历转换出错:', e);
|
|
}
|
|
},
|
|
|
|
// 初始化农历选择器
|
|
initLunarPicker() {
|
|
const years: string[] = [];
|
|
for (let y = 1901; y <= 2099; y++) {
|
|
years.push(y + '年');
|
|
}
|
|
const months: string[] = [];
|
|
for (let m = 1; m <= 12; m++) {
|
|
months.push(this.getLunarMonthLabel(m));
|
|
}
|
|
const days: string[] = [];
|
|
for (let d = 1; d <= 30; d++) {
|
|
days.push(this.getLunarDayLabel(d));
|
|
}
|
|
|
|
const today = new Date();
|
|
|
|
// Calculate today's lunar date to set default picker value
|
|
const result = solarToLunar(today.getFullYear(), today.getMonth() + 1, today.getDate());
|
|
const yearIdx = result.year - 1901;
|
|
const monthIdx = result.month - 1;
|
|
const dayIdx = result.day - 1;
|
|
|
|
const display = `${result.year}年 ${result.monthName} ${result.dayName}`;
|
|
|
|
this.setData({
|
|
lunarPickerRange: [years, months, days],
|
|
lunarPickerValue: [yearIdx >= 0 ? yearIdx : 0, monthIdx, dayIdx],
|
|
lunarPickerDisplay: display
|
|
});
|
|
|
|
// Also init the reverse calculation result
|
|
this.calcLunarToSolar(result.year, result.month, result.day);
|
|
},
|
|
|
|
getLunarMonthLabel(m: number): string {
|
|
const names = ['正月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '冬月', '腊月'];
|
|
return names[m - 1];
|
|
},
|
|
|
|
getLunarDayLabel(d: number): string {
|
|
const names = [
|
|
'初一', '初二', '初三', '初四', '初五', '初六', '初七', '初八', '初九', '初十',
|
|
'十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十',
|
|
'廿一', '廿二', '廿三', '廿四', '廿五', '廿六', '廿七', '廿八', '廿九', '三十'
|
|
];
|
|
return names[d - 1];
|
|
},
|
|
|
|
onLunarColumnChange(e: any) {
|
|
// 列变化时可以联动更新(简化处理)
|
|
},
|
|
|
|
onLunarPickerChange(e: any) {
|
|
const val = e.detail.value;
|
|
const year = 1901 + val[0];
|
|
const month = val[1] + 1;
|
|
const day = val[2] + 1;
|
|
|
|
const display = `${year}年 ${this.getLunarMonthLabel(month)} ${this.getLunarDayLabel(day)}`;
|
|
|
|
this.setData({
|
|
lunarPickerValue: val,
|
|
lunarPickerDisplay: display,
|
|
});
|
|
|
|
this.calcLunarToSolar(year, month, day);
|
|
},
|
|
|
|
calcLunarToSolar(year: number, month: number, day: number) {
|
|
try {
|
|
const result = lunarToSolar(year, month, day, false);
|
|
const solarDate = new Date(result.year, result.month - 1, result.day);
|
|
const solarStr = this.formatDate(solarDate);
|
|
|
|
this.setData({
|
|
lunarToSolarResult: solarStr,
|
|
lunarToSolarWeekday: this.getWeekday(solarDate)
|
|
});
|
|
} catch (e) {
|
|
this.setData({
|
|
lunarToSolarResult: '无效日期',
|
|
lunarToSolarWeekday: ''
|
|
});
|
|
}
|
|
},
|
|
|
|
// 今日信息
|
|
updateTodayInfo() {
|
|
const today = new Date();
|
|
const y = today.getFullYear();
|
|
const m = today.getMonth() + 1;
|
|
const d = today.getDate();
|
|
|
|
try {
|
|
const lunar = solarToLunar(y, m, d);
|
|
const term = getSolarTerm(y, m, d);
|
|
|
|
this.setData({
|
|
todaySolar: `${y}年${m}月${d}日 ${this.getWeekday(today)}`,
|
|
todayLunar: lunar.monthName + lunar.dayName,
|
|
todayGanZhi: lunar.ganZhi + '年',
|
|
todayAnimal: lunar.animal,
|
|
todayTerm: term || ''
|
|
});
|
|
} catch (e) {
|
|
console.error('获取今日信息出错:', e);
|
|
}
|
|
},
|
|
|
|
formatDate(date: Date): string {
|
|
const y = date.getFullYear();
|
|
const m = (date.getMonth() + 1).toString().padStart(2, '0');
|
|
const d = date.getDate().toString().padStart(2, '0');
|
|
return `${y}-${m}-${d}`;
|
|
},
|
|
|
|
getWeekday(date: Date): string {
|
|
const days = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
|
return days[date.getDay()];
|
|
}
|
|
})
|