我的生活笔记会记录游记,为了更好地发挥双链笔记,自然也给朋友们存了个档。
存都存了,干脆把生日这些信息也存一下。于是我需要一个能汇总这些生日的表格,便于观察。
如果用原生的 Query 语句,能简单达到效果,但是无法排序:
path:"人类/" content: "生日:"
而 DataView,最简单的方式是按它的格式在 Metadata 里填写基本信息,但这样太耦合了,我不能接受。
不过了解到它的 dataviewjs
是可以自定义对笔记查询和排序的。
我对 JS 并不熟悉,网上搜了一通也没现成的,无奈找了几个类似的功能,在 ChatGPT 的鼎力支持下实现了。分享给有需要的人。
效果如下:
相关代码为:
const files = app.vault.getMarkdownFiles().filter(file => file.path.includes("人类") && !file.path.includes("统计"));
let arr = files.map(async(file) => {
// 读取文件并将内容作为字符串获取
const content = await app.vault.cachedRead(file);
const lines = content.split("\n").filter(line => line.includes("- 生日:"));
for (let i = 0; i < lines.length; i++) {
lines[i] = lines[i].replace("- ", '');
}
// 正则解析出生日信息
const birthdates = lines.map(line => {
const match = line.match(/(\d{4})?年?(\d{2})月(\d{2})日/); // 匹配年份(可选),月份和日期
if (match) {
const year = match[1] || new Date().getFullYear(); // 如果没有年份,使用当前年份
const month = parseInt(match[2], 10) - 1; // 月份从 0 开始
const day = parseInt(match[3], 10);
const date = new Date(year, month, day); // 创建日期对象
return date;
}
return null; // 如果没有匹配到,返回 null
}).filter(date => date !== null); // 过滤掉没有生日信息的
return { filename: "[["+file.name.split(".")[0]+"]]", birthdates };
});
Promise.all(arr).then(values => {
// 过滤掉没有生日信息的项
const validValues = values.filter(v => v.birthdates.length > 0);
// 将所有有效的结果按月份和日期排序
validValues.sort((a, b) => {
// 按月份和日期排序,不比较年份
const monthDayA = a.birthdates[0].getMonth() * 100 + a.birthdates[0].getDate();
const monthDayB = b.birthdates[0].getMonth() * 100 + b.birthdates[0].getDate();
return monthDayA - monthDayB;
});
dv.table(["名字", "生日"], validValues.map(v => [v.filename, v.birthdates.map(date => {
// 格式化日期,只有月份和日期
return `${date.getMonth() + 1}月${date.getDate()}日`;
}).join(", ")]));
});