Chrono Mock
语言简体中文

不动系统时钟,让 Windows 应用在任意日期运行

把某个应用的时钟调到明年、让它停住,或者加速运转,让 30 天的试用期在你泡咖啡的工夫里到期。机器上的其他部分仍然使用真实时间——域登录、证书和其他所有程序都照常工作。

然后它会告诉你,这次替换是否真的生效了。

免费开源,GPL-3.0 便携版或安装版 运行无需管理员权限 从不连接互联网

一次会话的样子

应用看到的时间
2027-12-31
23:59:50
会话时区 -05:00
机器仍然看到的时间
2026-09-04
18:12:33
宿主时区 +02:00
生效——替换已经作用到这个进程
监视的时间通道 最多 44 个 · 每个都附调用次数
Chrono Mock 的会话面板。应用的时钟显示 2038-01-19 03:14:14,旁边的真实时钟显示 2026-09-22 15:50:30,两者各自带有已运行时间。下方是从 x1 到 x1440 的速度档和一个 Freeze 按钮,接着是相对跳转和跳转到输入日期的选项,页脚处一个绿色对勾标着 Works,旁边是红色的 Stop session 按钮。
一次正在运行的会话。应用身处 2038 年,机器却不是,判定结果表明替换已经作用到它。

为什么需要它

测试任何与日期相关的功能,都得拨动时间。常见的两种做法都不好。

许可证到期、试用期、订阅续费、证书有效期、令牌寿命、月末与年末报表、利息计提、提醒。

做法一:修改系统时钟

它会破坏域登录和 Kerberos,让 TLS 证书失效、浏览器无法使用,扰乱 Windows 更新,还会让这台机器上其他所有应用写出错误的时间戳。在加入域的机器上,组策略通常会直接禁止修改,或者几分钟后又把时间改回去,于是测试连重复执行都做不到。

做法二:等

也就是说:不测。与日期相关的用例就这样被跳过,“许可证永不过期”的版本也就这样交到了客户手里。

它能做什么

只有一个进程穿越时间,机器上的其他一切都不受影响。

任意时刻

一个具体的日期和时间,或者一个相对的时间——+30 days、-1 year。

流动、冻结或加速

正常速度、停住的时钟,或者一个整数倍率。x1440 让一天只需一分钟。

独立的时区

只对该进程生效的固定偏移量,系统时区则原封不动。

子进程一并跟随

安装程序和启动器都会派生子进程。没有这一点,测试只覆盖了实际运行内容的一半。

会话中途跳转

向前或向后都可以——包括笔记本与时间服务器重新同步后发生的那种向后跳变。

同样支持 Electron 和 Chromium

通过另一种机制实现,因为它们的时钟位于沙盒渲染进程中,注入够不到那里。

别人都没做的部分

你怎么知道它生效了?

用其他任何工具,你都无从知道。应用启动了,显示出某个日期,而你只能假定一切正常。可它也许是通过工具从未拦截的通道读取时钟的——来自服务器、来自数据库、来自某个运行时层——到那时,“测试通过”就毫无意义。

  • →在真正的测试开始之前就给出判定:生效 / 部分生效 / 未生效
  • →在 44 个时间通道中,哪些已被覆盖,应用对每个通道各查询了多少次
  • →哪些通道没有被覆盖——如实写明,绝不省略
  • →附带后果说明的警告:“该应用会从网络读取时间——仅做本地替换可能不够”

时间源审计是如何工作的 →

两分钟上手

用窗口来探索,用命令行跑 CI。两者背后是同一个引擎。

# 让应用以 2027 年的最后一秒来运行
chrono run "C:\apps\test.exe" --at 2027-12-31T23:59:59

# 在你泡咖啡时看着 30 天试用期到期:x1440 就是一分钟一天
chrono run "C:\apps\test.exe" --mode x1440

# 用命名场景代替日期,并把证据写入文件
chrono run "C:\apps\test.exe" --preset year-rollover --report session.txt

计算器回答日期测试的另一半——该用哪个日期:

$ chrono calc --preset year-2038 --zone +00:00
Chrono Mock - date calculator
  preset:   year-2038 - 2038 boundary
  explains: Does the app survive the 32-bit Unix time boundary (2038-01-19T03:14:07Z)?
  base:    2038-01-19T03:14:07
  result:  2038-01-19T03:14:07
  formats:
    ISO date      2038-01-19
    ISO datetime  2038-01-19T03:14:07+00:00
    US            01/19/2038
    PL            19.01.2038
    epoch (s)     2147483647
    epoch (ms)    2147483647000
    FILETIME      137919572470000000
    RFC 1123      Tue, 19 Jan 2038 03:14:07 GMT
  ...
  what this date lands on:
    at or past the 2038-01-19T03:14:07Z 32-bit time_t limit (Y2038)

与你可能正在用的工具对比

像 RunAsDate,但补上了缺失的部分

RunAsDate 拦截五个挂钟时间函数,并且做得很好。下面是两者的差异——完整页面还会说明 RunAsDate 在哪些情况下仍是更好的选择。

 RunAsDateChrono Mock
让一个应用以虚拟日期运行是是
被拦截的时间通道544(30 个被偏移,14 个仅计数)
加快时钟否是
独立的时区文档中未提及是
跟随子进程文档中未提及是
告诉你是否生效否是,逐个通道
可获取源代码免费软件,闭源GPL-3.0

完整对比,包括 RunAsDate 更胜一筹的地方 →

获取

解压到任意位置即可运行,也可以安装已签名的 .msi,供这台计算机上的每个账户使用。运行不需要管理员权限,zip 包也不会向注册表写入任何内容。