workbuddy-to-dsh 实战:WorkBuddy 工时数据一键转 DSH 日报

发布时间:2026/10/7 13:55:45
workbuddy-to-dsh 实战:WorkBuddy 工时数据一键转 DSH 日报
如果你用过WorkBuddy记工时大概率也经历过我这种尴尬每天的记录都整整齐齐躺在导出的 JSON 文件里可真到写日报、周报的时候这些数据一点忙都帮不上。后来我开始用DSHDaily Status Hub管理每日状态汇总但两边手工搬运的滋味实在不好受直到我拿到workbuddy-to-dsh这个转换器才把整套流程彻底跑顺。workbuddy-to-dsh不复杂核心就是一条命令行、一个配置文件把 WorkBuddy 的嵌套 JSON 转成人类能读、机器也能处理的 DSH Markdown 文件。这篇不是官方文档的复述而是我实际使用它的完整记录从“为什么要转”讲起再把安装、第一条命令、模板定制、踩坑经历和自动化串联起来。适合被工时数据整理折磨的开发者、自由职业者以及有日报周报汇报需求的人。1. WorkBuddy 数据为什么会需要转换成 DSH1.1 WorkBuddy 是好工具但它的导出数据不适合直接阅读WorkBuddy 这类工具的强项是“记录过程”它会记下每个任务的开始时间、结束时间、所属项目、标签甚至还能拆出番茄钟片段。导出文件长这样{ version: 2, exportedAt: 2026-04-18T20:15:0008:00, projects: [ { id: p1, name: 内部工具 } ], tasks: [ { id: t1, projectId: p1, title: 修复登录超时, startedAt: 2026-04-18T09:30:0008:00, endedAt: 2026-04-18T11:00:0008:00, tags: [bug] } ] }这只是最简化的结构。实际数据里还会混着多个项目、多个任务片段、备注、优先级和状态字段。直接打开这种 JSON你根本没法一眼看出“今天到底做了什么、花了多久”。更麻烦的是如果项目跨月、任务跨天、中间还有暂停继续人工整理的时间成本会高到离谱。1.2 DSH 不是新任务系统而是“可阅读的状态快照”DSH 全称 Daily Status Hub它不追求像数据库那样复杂而是把一天的工作压缩成一份带元信息的 Markdown 文件。比如--- date: 2026-04-18 total_minutes: 90 --- ## 内部工具 - 09:30 - 11:00 修复登录超时 (#bug)这种格式的好处很明显人能直接看机器也好解析。date和total_minutes放在头部正文按项目分组列任务每条任务都有时间区间、标题和标签。无论你是把这份文件贴进日报、扔进 git 仓库还是交给脚本统计工时都毫无压力。1.3 转换器真正在做什么workbuddy-to-dsh解决的是三种“表达能力错位”数据形态错位WorkBuddy 是嵌套 JSONDSH 是拍平的 Markdown时间粒度错位WorkBuddy 记录的是精确时间戳DSH 需要的是按天、按项目聚合的可读片段生产流程错位手写日报是结束之后的事有了转换器日报可以在记录结束那一刻自动生成。具体来说它内部做了字段映射、时区归一化、按天分组、项目归类、模板渲染和去重。很多人在命令行里看到的只是“一条命令出结果”但背后这些步骤决定了你能不能直接把产物用于周报和复盘。2. 安装 workbuddy-to-dsh虚拟环境、pip 安装和源码安装2.1 环境准备workbuddy-to-dsh是 Python 写的需要 Python 3.9 及以上版本。我用 Python 3.10 跑得很稳3.8 以下会在解析部分直接报语法错误。装之前先确认版本python --version如果没有这个版本建议先去官网升级解释器而不是硬扛。我见过不少人在 3.7 环境下面折腾半天最后发现是版本问题。同时强烈推荐先建一个虚拟环境。原因很简单这个工具会依赖一些第三方库直接装进全局 Python 环境容易跟其他项目冲突。python -m venv w2d-env source w2d-env/bin/activateWindows 上激活命令是w2d-env\Scripts\activate激活成功后命令行提示符前面会出现(w2d-env)后面所有安装和运行都在这套环境里做。2.2 通过 pip 安装激活虚拟环境后执行pip install workbuddy-to-dsh w2d --version如果安装成功你会看到类似workbuddy-to-dsh 0.4.2的版本号。如果网络慢可以换国内镜像源但要注意镜像同步可能滞后装到的版本不是最新。我的习惯是先用默认源装装不上再临时指定镜像。2.3 源码安装的适用场景如果你打算修改模板解析逻辑、给项目加自定义字段或者想深入跟踪 bug建议直接 clone 源码来装git clone https://github.com/your-repo/workbuddy-to-dsh.git cd workbuddy-to-dsh pip install -e .-e表示可编辑安装源码改动会立即生效不用每次重新 pip install。缺点是源码目录不能随便删删了环境就废了。2.4 安装时最容易翻车的两个点第一是w2d命令找不到。这种情况八成是虚拟环境没激活或者激活后又切到了别的 shell。第二是权限问题。不要在 Linux/macOS 上直接sudo pip install遇到权限不足就说明你的环境策略有问题而不是命令需要加 sudo。把虚拟环境建好通常不会有权限报错。3. 第一次转换用一条命令生成 Daily Status3.1 先检查你的输入数据拿到 WorkBuddy 的导出文件后不要急着转先看一眼数据里到底长什么样。很多报错其实不是工具的问题而是你根本不知道 JSON 里有几个字段。workbuddy-to-dsh提供了一个检查命令w2d inspect -i workbuddy_export.json它会输出文件中包含的字段名、项目数量和任务数量甚至能告诉你最早和最晚的一条记录时间。这个命令我每次升级工具后都会跑一遍毕竟 WorkBuddy 偶尔会调整导出格式。3.2 执行第一条转换命令确认数据没问题后执行w2d convert -i workbuddy_export.json -o dsh/2026-04-18.md这条命令的意思是读取workbuddy_export.json生成dsh/2026-04-18.md。如果dsh目录不存在工具会自动创建。如果用默认模板生成的内容大致是这样--- date: 2026-04-18 total_minutes: 90 --- ## 内部工具 - 09:30 - 11:00 修复登录超时 (#bug)第一次跑完我的第一反应是“就这”但实际用起来会发现简单反而可靠。它不掺杂任何花哨的东西就是一个能贴进日报、能被脚本处理的干净文本。3.3 常用参数速查只靠默认参数还不够因为实际工作里有很多边界情况。下面这几个参数是我用得最多的参数说明默认值-i, --inputWorkBuddy 导出的 JSON 文件路径必填-o, --output输出 DSH 文件路径./dsh/daily.md--date只处理指定日期当前日期--tz时区例如Asia/Shanghai系统时区--tag-filter逗号分隔的标签过滤比如work,meeting不过滤--dedupe按字段合并重复任务比如projecttitle不合并比如你只想导出 2026 年 4 月 17 日的数据并且只保留打上 work 标签的任务w2d convert -i workbuddy_export.json -o dsh/2026-04-17.md --date 2026-04-17 --tag-filter work命令行参数适合临时用。如果你每天都要跑同样的命令把配置写进文件才更合理下一节我会专门讲。提示输出路径不要直接用daily.md时间一长文件会被覆盖。最好的做法是按日期命名或者用配置文件里的${date}占位符动态生成。4. 配置文件模板、过滤规则、字段映射一次说清4.1 为什么需要配置文件命令行参数解决的是“一次性的需求”。但实际场景里你可能每天固定要排除几个项目、固定按项目分组、固定把“内部工具”这个名字映射成“Engineering”这些需求如果全写在命令里命令会变得又长又难记。更别说你还要自定义模板命令行根本塞不下。配置文件默认读取当前目录下的w2d.yaml。如果你把配置放在别处可以用-c指定w2d convert -i workbuddy_export.json -o dsh/2026-04-18.md -c ~/configs/w2d.yaml4.2 一个可以直接抄的配置示例这是我现在用的配置你可以根据自己情况改output: path: dsh/${date}.md template: templates/daily.j2 timezone: Asia/Shanghai filters: exclude_projects: - 个人 - 杂项 include_tags: - work start_hour: 8 end_hour: 22 mapping: 内部工具: Engineering 产品需求: Productoutput.path里的${date}会被自动替换成当天日期比如dsh/2026-04-18.md。timezone控制时间聚合的基准如果你人在东八区但系统时区是 UTC就必须在这里手动指定否则日期会越看越奇怪。filters.exclude_projects用来去掉你不想写进日报的项目比如“个人”和“杂项”。include_tags则是一把白名单筛子只保留打了 work 标签的任务。mapping是做项目名归一化的。WorkBuddy 里的项目命名往往很随意同一个项目可能有“内部工具”“内部工具V2”两种叫法。通过映射把它们统一成Engineering周报汇总时才不会出现一堆相似名字。4.3 自定义模板模板放在templates/daily.j2格式是 Jinja2。默认模板能用但多数人都会有自己偏好的排版。我自己的模板长这样--- date: {{ date }} total_minutes: {{ total_minutes }} --- {% for project in projects %} ## {{ project.name }} {% for task in project.tasks %} - {{ task.start }} - {{ task.end }} {{ task.title }}{% if task.tags %} ({{ task.tags | join(, ) }}){% endif %} {% endfor %} {% endfor %}模板里可用的变量包括date、total_minutes、projects。每个project里有name和tasks每个task里有title、start、end、duration_minutes、tags。如果你只需要展示时长超过 0 的任务可以加条件{% for task in project.tasks %} {% if task.duration_minutes 0 %} - {{ task.start }} - {{ task.end }} {{ task.title }} {% endif %} {% endfor %}Jinja2 的{% for %}和{% if %}逻辑和 Python 很接近没有额外学习成本。唯一要注意的是模板文件本身必须是 UTF-8 编码而且缩进最好别用 tab否则渲染出来的 Markdown 在不同编辑器里会错位。4.4 字段映射解决 WorkBuddy 字段名不统一的问题我在配置里单独留了一节字段别名映射。因为 WorkBuddy 不同版本的导出字段名不完全一样例如旧版用projectId新版用project_id。如果直接硬编码升级一次就崩一次。在w2d.yaml里可以这么配置fields: project_id: - projectId - project_id title: - title - name工具读取 JSON 时会按顺序尝试这些字段名只要有一个存在就采用。这个功能救了我很多次尤其是在处理“新旧版本导出文件混在一个目录”的场景时。5. 我踩过的坑字段缺失、时区错位、中文乱码和重复统计5.1KeyError: projectId不一定是程序 bug我第一次跑转换就遇到了KeyError: projectId第一反应是工具坏了。后来用w2d inspect一看发现导出文件里的字段名根本就是project_id大小写和命名风格跟旧版完全不一样。这个坑的解法是前面说的fields字段映射。遇到这个报错时先不要急着提 issue而是先检查你导出文件里的真实字段。工具不可能预测所有版本的习惯命名给用户留一个字段别名配置是最合理的方案。5.2 日期“少一天”十有八九是时区有一段时间我每天早上生成的 DSH 文件日期总是前一天。后来发现 WorkBuddy 导出的时间戳带08:00偏移但我的服务器系统时区是 UTC。当工具按系统时区把时间戳转成日期时晚上 8 点之后的记录就会“跑”到前一天。解决方式很简单在配置里明确指定时区timezone: Asia/Shanghai不要依赖系统时区尤其是你的机器可能跨地域部署或者本地电脑时区被某些工具改过。命令行里也可以用w2d convert -i data.json -o daily.md --tz Asia/Shanghai这个参数优先级高于配置文件适合临时给某个项目指定不同时区。5.3 Windows 下中文乱码中文乱码分为两种。一种是控制台乱码也就是屏幕上显示乱码但生成的 Markdown 文件没问题。这种情况通常是 Windows 控制台代码页的问题执行chcp 65001切换到 UTF-8 代码页就好。另一种是文件本身乱码这就比较麻烦了。我遇到的主要原因是模板文件不是 UTF-8 编码或者 JSON 文件带 BOM 头。Word 或者一些 Windows 自带编辑器导出的 JSON 容易带 BOM转换时可以把文件另存为 UTF-8 无 BOM 格式然后重新跑一遍。为了保险也可以在环境变量里强制 Python 使用 UTF-8export PYTHONIOENCODINGutf-8Windows PowerShell 里写作$env:PYTHONIOENCODINGutf-85.4 同一个任务被算了两遍WorkBuddy 里有一个常见操作干一件事中途暂停了几分钟再继续时它会生成两个相邻的时间片段。如果直接转换DSH 里就会出现两条几乎一样的任务总时长也翻倍。这个问题的解法是去重。命令行w2d convert -i data.json -o daily.md --dedupe projecttitle或者在配置文件里写成dedupe: key: - project - title merge_window_minutes: 5merge_window_minutes的作用是处理“间隔 5 分钟以内的相邻片段自动合并”的逻辑。间隔 5 分钟以上就视为两条独立任务这样不会误删真正分开的两个动作。配置好之后转换产物干净很多周报统计也准了。5.5 路径里有空格这个坑看起来最基础但踩的人一点都不少。Windows 路径经常出现类似C:\Users\My Documents\workbuddy.json的空格如果不在命令行里加引号工具会收到两个参数直接报“文件找不到”。正确写法w2d convert -i C:\Users\My Documents\workbuddy.json -o D:\Notes\dsh\daily.md配置文件里的路径不需要加引号YAML 本身会处理空格。我把这些常见问题整理成了一张排查表放在手边非常省脑子现象根因处理方式KeyError: projectIdWorkBuddy 字段名变化用w2d inspect核对字段再在fields里补别名日期少一天时区没指定配置timezone: Asia/Shanghai控制台中文乱码代码页不对chcp 65001或设置PYTHONIOENCODING文件内中文乱码模板/JSON 编码问题统一 UTF-8 无 BOM任务时长翻倍暂停片段未合并开启--dedupe并配置merge_window_minutes提示文件不存在路径含空格未加引号命令行参数加引号6. 进阶玩法从每次手敲命令到全自动流水线6.1 用定时任务每天自动转换手动敲命令在新鲜感消退后就会变成负担所以要自动化。Linux/macOS 上用 cron每天 18:30 自动生成当天 DSH 文件0 18 * * * cd ~/work /home/user/w2d-env/bin/w2d convert -i ~/workbuddy/data.json -o ~/notes/dsh/$(date \%F).md注意两点第一cron 里默认环境变量和登录 shell 不一样命令里的w2d要写成虚拟环境里的绝对路径第二date \%F里的百分号需要转义否则 cron 会把它当特殊字符处理。Windows 用户可以用任务计划程序触发条件设为“每天 18:30”执行w2d-env\Scripts\w2d.exe参数照旧。设置好之后我连续几周都没再手动生成过日报。6.2 用 git 管理每日状态DSH 是纯文本 Markdown天然适合放进 git。我专门建了一个notes/dsh仓库每天定时转换后自动提交cd ~/notes/dsh git init git add . git commit -m daily status update $(date \%F)一个月后git log --oneline就是你一整月的工作日历哪天做了什么一目了然。配合git diff还能精确看到某个项目的时间统计变化。这个习惯让我在做月度复盘时省了大量的回忆时间。6.3 汇总生成周报周报不需要重新去翻原始 JSON只需要把一周的 DSH 文件合并起来。我写了一个 20 行不到的小脚本读取每个文件的total_minutes再按项目输出import yaml from pathlib import Path from collections import defaultdict data defaultdict(int) for f in Path(dsh).glob(2026-04-*.md): parts f.read_text(encodingutf-8).split(---) meta yaml.safe_load(parts[1]) data[f.stem] meta.get(total_minutes, 0) for day, minutes in sorted(data.items()): print(f{day}: {minutes // 60}h {minutes % 60}m)这套思路不依赖任何外部服务生成的 Markdown 还能继续被其他工具消费。如果你有更强的统计需求也可以把 DSH 文件继续转成 CSV 或导入表格软件。6.4 DSH 文件本身也能成为工作流的入口因为 DSH 是标准化 Markdown我后来把它接到了本地笔记仓库里。每天的日报在笔记 App 里直接可搜索标签可以展开时间粒度也能被全文检索。等于 WorkBuddy 变成了“记录层”DSH 变成了“表达层”两者各司其职。7. 我目前的工作流和一点体会我现在的工作流程是WorkBuddy 持续记录每天 18:30 由定时任务自动生成 DSH 文件文件落地后 git 自动提交周五下午再跑一次汇总脚本把近 5 天的 DSH 合并成周报草稿。整个过程里我真正动手的时间每天不超过两分钟大部分精力都花在“看数据”而不是“整理数据”上。如果要给刚接触workbuddy-to-dsh的人一条建议我会说不要一上来就追求完美的自定义模板。先用默认配置跑一个星期把每天的产物都打开看一眼搞清楚自己到底需要哪些字段再去改w2d.yaml和模板。很多人的第一次自定义模板之所以失败不是因为语法不会而是因为自己都不知道想要的日报长什么样。另外遇到字段缺失或者格式变化的报错时先跑一次w2d inspect看实际数据这是排查一切问题的基础。工具再怎么智能也猜不到你文件里的真实字段名。让它能把别名映射配好比反复试命令参数管用得多。