用 QuickAdd 一键更新 Obsidian 笔记的 YAML date 时间戳
在用 Obsidian 记笔记、写博客或者管理知识库时,很多人都会遇到一个很实际的问题:笔记内容改了,但 YAML 里的 date 时间没有更新。时间一旦不准,后面无论是做排序、建索引、生成博客页面,还是配合 Dataview 统计,都会变得很别扭。
如果你每次都手动去改,那么短时间内还能接受,但笔记一多,这件事就会变得机械、重复,而且特别容易忘。更麻烦的是,时间格式如果手动写错,比如少了时区、少了秒数,后续有些插件或者博客系统还可能识别异常。
这篇文章讲的,就是怎么在 Obsidian 里用一个很短的小脚本,实现“一键更新当前笔记的 YAML date 字段”。你不需要懂编程,也不需要系统学 JavaScript,只要跟着做,就能把这个功能装到自己的笔记系统里。
这个脚本到底解决了什么问题¶
先说人话。
很多 Obsidian 笔记顶部会有这样一段内容:
---
title: 我的笔记
date: 2026-03-09T10:20:30+08:00
tags:
- obsidian
---
这段内容叫 YAML Frontmatter,也常被简称为 YAML 头信息。它的作用,有点像给笔记贴“属性标签”。比如标题、日期、标签、分类、作者这些信息,通常都写在这里。
而这次这个脚本做的事情非常单纯:当你运行它时,它会自动检查当前正在编辑的这篇笔记,然后把里面的 date 字段更新成当前时间,而且格式是标准的:
2026-03-09T21:35:18+08:00
如果这篇笔记原本就有 date,它会把旧值替换掉。
如果原本没有 date,它会自动补上一行。
如果这篇笔记连 YAML 头都没有,它也会帮你创建出来。
也就是说,你不需要关心这篇笔记现在是什么状态,只要点一下命令,它就会尽量帮你处理好。
先理解一下:什么是 YAML,什么又是 date¶
对于零基础来说,这里最容易迷糊,所以先讲清楚。
在 Obsidian 里,一篇 Markdown 笔记最上方如果出现两条 ---,中间夹着几行“键: 值”的内容,这一整块就是 YAML Frontmatter。
比如:
---
title: QuickAdd 使用记录
date: 2026-03-09T21:35:18+08:00
tags:
- Obsidian
- 自动化
---
这里的 title、date、tags 都是字段名。冒号后面就是对应的值。
其中 date 一般表示这篇笔记的某个时间信息。你可以把它理解成“发布时间”“最后更新时间”或者“记录时间”,具体看你自己的用法。但不管它代表什么,只要你希望它始终准确,那自动更新就会很有价值。
这个脚本是怎么工作的¶
虽然你不需要会写代码,但知道它大概在做什么,会更安心。
这个脚本运行时,首先会获取你当前打开的那篇笔记。如果你现在没有打开任何笔记,它就会弹出一句提示,告诉你“没有检测到当前活动笔记”。
接着,它会读取当前笔记的全部内容,然后生成一个北京时间格式的当前时间。这里脚本专门处理成了 +08:00 时区,也就是东八区时间。这个细节很重要,因为很多人电脑系统时区、部署环境时区、博客构建环境时区不一定完全一致。脚本直接把结果固定成东八区,可以减少很多时间混乱问题。
之后,脚本会分三种情况处理:
第一种情况,是你的笔记已经有 YAML 头,而且里面也已经有 date 字段。那么它就直接把原来的 date 替换成新的当前时间。
第二种情况,是你的笔记有 YAML 头,但里面没有 date。那它就会在 YAML 区域里新增一行 date: 当前时间。
第三种情况,是你的笔记压根没有 YAML 头。那它就会在文章最前面自动插入一整块 YAML,并写入 date 字段。
最后,它会把修改后的内容重新保存回当前文件,并弹出一条提示,告诉你已经更新成功。
所以从使用者角度看,这个功能本质上就是:打开笔记,执行命令,时间自动更新。
脚本代码¶
你要使用的就是下面这段脚本:
module.exports = async (params) => {
const { app } = params;
const file = app.workspace.getActiveFile();
if (!file) {
new Notice("没有检测到当前活动笔记");
return;
}
const content = await app.vault.read(file);
function formatDateToUTC8(date = new Date()) {
const utc = date.getTime() + date.getTimezoneOffset() * 60 * 1000;
const utc8 = new Date(utc + 8 * 60 * 60 * 1000);
const Y = utc8.getFullYear();
const M = String(utc8.getMonth() + 1).padStart(2, "0");
const D = String(utc8.getDate()).padStart(2, "0");
const h = String(utc8.getHours()).padStart(2, "0");
const m = String(utc8.getMinutes()).padStart(2, "0");
const s = String(utc8.getSeconds()).padStart(2, "0");
return `${Y}-${M}-${D}T${h}:${m}:${s}+08:00`;
}
const newDate = formatDateToUTC8();
let newContent = content;
if (content.startsWith("---\n")) {
const endIndex = content.indexOf("\n---", 4);
if (endIndex !== -1) {
const frontmatter = content.slice(4, endIndex);
const body = content.slice(endIndex + 4);
let updatedFrontmatter;
if (/^date\s*:/m.test(frontmatter)) {
updatedFrontmatter = frontmatter.replace(
/^date\s*:\s*.*$/m,
`date: ${newDate}`
);
} else {
updatedFrontmatter = `${frontmatter}\ndate: ${newDate}`;
}
newContent = `---\n${updatedFrontmatter}\n---${body}`;
} else {
newContent = `---\ndate: ${newDate}\n---\n${content}`;
}
} else {
newContent = `---\ndate: ${newDate}\n---\n${content}`;
}
await app.vault.modify(file, newContent);
new Notice(`已更新 date 字段为:${newDate}`);
};
你可以先不用逐行看懂,后面我会讲怎么把它接到 Obsidian 里用起来。
使用前需要准备什么¶
这个脚本不是直接贴进笔记里就能运行的,它需要借助 Obsidian 的 QuickAdd 插件来执行。
所以你至少需要完成两件事:一是安装 QuickAdd,二是把这段脚本添加为一个可执行命令。
如果你之前没装过插件,也不用紧张。Obsidian 的社区插件安装流程并不复杂。你只需要打开设置,找到社区插件,关闭安全模式后搜索 QuickAdd,然后安装并启用即可。
装好以后,真正的配置才开始。
第一步:把脚本保存成一个 .js 文件¶
你可以在自己的 Obsidian 仓库里专门建一个文件夹,名字随意,比如叫:
Scripts
然后在里面新建一个文件,命名为:
update-date.js
注意,这个文件后缀必须是 .js,不能写成 .md,也不能只是普通文本文件。
接着,把上面那整段脚本完整复制进去并保存。
这一步的意义很简单:QuickAdd 之后会去执行这个 JavaScript 文件,所以你得先把它放在仓库里某个明确的位置。
第二步:在 QuickAdd 里创建一个 Macro¶
接下来打开 Obsidian 设置,进入 QuickAdd。
在 QuickAdd 里,你会看到可以创建不同类型的命令。这里我们要创建的是一个 Macro。你可以把 Macro 理解成“一个可以一键执行的动作”。
新建 Macro 后,给它起一个容易认出的名字,比如:
更新 YAML 日期
名字本身不会影响功能,但建议取得直白一些,这样以后在命令面板里一眼就知道是干什么的。
创建完这个 Macro 之后,进入它的编辑界面,添加一个动作。这个动作要选择和脚本执行相关的类型。在 QuickAdd 里,一般是选择运行用户脚本,也就是去调用你刚才保存的那个 update-date.js 文件。
然后把脚本路径指向这个文件。
做完这一步,本质上就是告诉 QuickAdd:以后当我执行“更新 YAML 日期”这个命令时,你就去运行这段脚本。
第三步:测试效果¶
现在你可以随便打开一篇笔记测试一下。
先看最理想的情况。假设你有这样一篇笔记:
---
title: 测试笔记
date: 2025-01-01T00:00:00+08:00
---
这里是正文内容
运行命令后,它会变成:
---
title: 测试笔记
date: 2026-03-09T21:35:18+08:00
---
这里是正文内容
如果原来是这样:
---
title: 测试笔记
---
这里是正文内容
运行后会自动补成:
---
title: 测试笔记
date: 2026-03-09T21:35:18+08:00
---
这里是正文内容
如果原来连 YAML 都没有,比如只有正文:
这里是正文内容
运行后会变成:
---
date: 2026-03-09T21:35:18+08:00
---
这里是正文内容
你会发现,这个脚本的好处就在这里:它不挑文件状态,兼容性比较强,能自动补齐缺失部分。
为什么时间格式要写成这样¶
很多人第一次看到这种时间会有点陌生:
2026-03-09T21:35:18+08:00
其实它是非常标准的时间写法。可以拆开理解:
前面的 2026-03-09 是年月日。
中间的 T 只是日期和时间之间的分隔符。
后面的 21:35:18 是时分秒。
最后的 +08:00 表示东八区时区。
这种格式的好处是规范、清晰,而且很多程序和插件都能稳定识别。相比只写“2026-03-09”,它的信息更完整;相比手写“2026年3月9日晚上9点35分”,它更适合机器处理。
如果你后面要把 Obsidian 内容同步到博客系统、静态网站或者 Dataview 统计里,这种格式通常会更稳妥。
这个脚本适合哪些人¶
如果你只是偶尔写几篇简单笔记,而且从来不用 YAML,那它未必是你的刚需。
但只要你属于下面这几种情况,这个脚本通常都会很有用。
第一种,是你写博客,尤其是用 Obsidian 作为内容源,再同步到 Hexo、Hugo、Jekyll、Quartz 或其他静态博客系统。因为这些系统经常依赖 frontmatter 中的日期字段来排序和渲染文章。
第二种,是你平时有维护知识库的习惯,希望笔记的时间信息始终准确,后面再按日期整理、筛选或回顾。
第三种,是你已经开始用 Dataview、Templater、QuickAdd 之类插件做自动化。对这类用户来说,date 字段越统一,后面整个系统越顺手。
使用时要注意什么¶
虽然这个脚本不复杂,但还是有几个地方值得提前知道。
最重要的一点,是它更新的是 date 字段,不是文件系统里的“修改时间”。也就是说,它改的是笔记内容中的 YAML 属性,而不是操作系统层面的文件属性。这两者不是一回事。
另外,这个脚本只处理当前打开的那篇笔记。它不会一次性批量修改整个库,也不会自动遍历文件夹。所以你可以把它理解为一个“当前文件一键更新时间”的工具,而不是批处理工具。
还有一点需要注意:这个脚本固定使用东八区时间。如果你本身就是以北京时间为主来写作和管理内容,这样很合适。但如果你以后想改成跟随系统时区或者改成 UTC,就需要再调整脚本逻辑。
更适合零基础的使用习惯¶
对于刚开始接触自动化的人,我比较建议把这个命令绑定到一个你非常顺手的触发方式上,而不是每次都去翻插件菜单。
最常见的方式有两种。
一种是通过命令面板调用。你按下命令面板快捷键,输入“更新 YAML 日期”,然后回车执行。这种方式最稳,也最容易理解。
另一种是给它绑定快捷键。比如你可以在 Obsidian 的快捷键设置里,给这个命令分配一个组合键。以后每次改完文章,只要按一下快捷键,日期就更新了。这样会非常顺手,尤其适合经常写博客的人。
当你真正把它融入写作流程后,体验会比手动改时间舒服很多。你几乎不需要再想“我是不是忘了更新时间”,因为这个动作已经被自动化了。
一个很实用的写作流程¶
如果你平时会在 Obsidian 里写博客,其实可以把它嵌进一个很自然的流程中。
比如,你写完文章后先检查内容,再运行一次“更新 YAML 日期”,然后再发布到博客仓库。这样发布出去的文章时间就总是新的。
如果你习惯多次修改同一篇文章,也可以在每次准备提交 Git 或部署前执行一次。这样 date 始终反映的是你最后一次整理完成的时间。
很多人做笔记自动化时,一开始总想上来就搞很复杂的系统,比如自动命名、自动分类、自动标签、自动归档。其实更好的方法是先解决一个最频繁、最稳定、最不容易出错的小动作。更新 date 就属于这种非常适合优先自动化的动作。
如果运行失败,通常是什么原因¶
零基础用户第一次配置脚本时,最常见的问题其实不是代码本身,而是配置路径或插件设置。
比如你明明写了脚本,但 QuickAdd 找不到这个 .js 文件,那通常是路径没填对。
又或者你创建了 Macro,但没有把“运行脚本”这个动作真正添加进去。
还有一种情况是你没有打开任何笔记就执行了命令,这时脚本会提示“没有检测到当前活动笔记”,这是正常保护,不算报错。
如果你发现运行后完全没反应,优先检查三件事:QuickAdd 有没有启用,脚本文件是不是 .js,以及路径是不是准确指向了那个脚本文件。
一般来说,这类问题都比代码逻辑本身更常见。
这段脚本为什么值得保留¶
从代码规模看,它并不大,功能也不炫技。但它有一个很明显的优点:足够专注。
它只做一件事,就是把当前笔记的 date 处理好。没有引入额外复杂度,也没有要求你重构整套知识库。对 Obsidian 自动化来说,这类小而稳的脚本反而最实用,因为你能真正每天用上。
很多自动化方案的问题,不是“做不到”,而是“太重了,最后懒得用”。而这个脚本的门槛比较低,收益却很直接。对于刚开始搭建自己工作流的人来说,它是一个很合适的起点。
结语¶
如果你一直在手动维护 YAML 时间,那么这个脚本基本可以帮你把这件事彻底省掉。它最适合的场景,是你已经开始认真管理 Obsidian 笔记,尤其是把它当成博客写作工具、知识库入口或者内容发布源的时候。
你不用先学会编程,才配开始自动化。很多时候,真正有效的自动化,就是先把最常重复、最容易忘、最机械的动作,交给脚本去做。更新 date 正好就是这样一个典型例子。
当你把这一步跑通后,后面再去扩展自动更新时间、自动补全字段、自动生成 slug、自动写入 tags,都会顺很多。因为你已经迈出了最关键的一步:让 Obsidian 开始替你干活,而不是你一直替它善后。