timer.makazs.xyz 时间 API
一组返回当前 UTC 时间戳的极简 HTTP 接口,主要面向 AI / LLM / 联网 Agent 场景: 让模型在回答前拿到一个可信的「现在」,而不是凭空猜测日期。
本接口通过普通 HTTP 请求返回服务器当前时间,没有任何往返延迟补偿与时钟漂移校准。 它不适合用于系统时钟同步、分布式一致性、证书校验、定时任务调度等对时间精度敏感的场景。 请使用标准 NTP / PTP 服务完成这类工作(见 系统对时 一节)。
基础信息
| 项目 | 值 |
|---|---|
| 域名 | https://timer.makazs.xyz |
| 协议 | HTTPS(GET) |
| 响应类型 | text/plain,纯数字字符串 |
| 时区 | 返回值为 Unix 时间戳,天然对应 UTC,不含时区信息 |
| 认证 | 无,无需 API Key |
| 限流 | 未公开说明,请自觉控制频率(建议 ≥ 10 秒一次) |
服务时间
站点通常在北京时间(UTC+8)以下区间内稳定运行:
每日 10:00 — 22:00(UTC+8)
- 该区间有时会延长(例如提前到 08:00 或延后到次日 00:00),但不保证。
- 窗口外服务可能不可达、返回 5xx 或长时间无响应。
- 即使窗口内,也不排除因维护、网络抖动导致短暂不可用。
因此任何调用方都必须实现失败兜底:请求超时或解析失败时,回退到本地时钟并在输出中标注「时间来源:本地,未校准」。
接口列表
| 路径 | 返回 | 示例 | 精度 |
|---|---|---|---|
/get/ai-api/ |
13 位毫秒时间戳 | 1794725561250 |
毫秒(字符串层面) |
/get/api32 |
10 位秒级时间戳 | 1794725875 |
秒 |
/get/api64 |
13 位毫秒时间戳 | 1794725877884 |
毫秒(字符串层面) |
这里的精度仅指返回字符串的位数,不代表真实时间准确度。 真实误差取决于网络往返延迟与服务器自身时钟,见 准确性说明。
接口详情
通用端点,返回毫秒级 Unix 时间戳。路径带结尾斜杠。
GET https://timer.makazs.xyz/get/ai-api/
1794725561250
返回秒级 Unix 时间戳(10 位)。适合只需精确到秒的场景,也便于直接喂给 date -d @…。
GET https://timer.makazs.xyz/get/api32
1794725875
返回毫秒级 Unix 时间戳(13 位)。适合需要计算延迟、测量耗时差的场景。
GET https://timer.makazs.xyz/get/api64
1794725877884
响应体是裸数字字符串,不是 JSON,也不带任何包装字段。
解析前请先 strip() 去除可能存在的空白或换行,再转成整数。
快速上手
命令行(curl)
# 毫秒时间戳
curl -s https://timer.makazs.xyz/get/api64
# → 1794725877884
# 秒级时间戳并转成可读时间(UTC)
date -u -d @"$(curl -s https://timer.makazs.xyz/get/api32)"
# 转成本地时区
date -d @"$(curl -s https://timer.makazs.xyz/get/api32)"
Python
import time, urllib.request
def server_time():
"""返回 (Unix 秒, 往返延迟秒)。失败抛异常,调用方需自行兜底。"""
t0 = time.time()
with urllib.request.urlopen("https://timer.makazs.xyz/get/api64", timeout=5) as r:
raw = r.read().decode("utf-8").strip()
t1 = time.time()
server_s = int(raw) / 1000.0
rtt = t1 - t0
# 服务器时间对应「本地请求中点」那一瞬间
offset = server_s - (t0 + t1) / 2
return time.time() + offset, rtt
ts, rtt = server_time()
print(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(ts)), "UTC")
print(f"往返延迟 {rtt*1000:.0f} ms,误差上界约 ±{rtt*500:.0f} ms")
JavaScript(浏览器 / Node 18+)
const res = await fetch("https://timer.makazs.xyz/get/api64");
const ms = Number((await res.text()).trim());
console.log(new Date(ms).toISOString()); // 2026-11-15T07:17:57.884Z
console.log(ms); // 1794725877884
在浏览器前端直接 fetch 需要服务器返回 Access-Control-Allow-Origin 响应头。
若被 CORS 拦截,请改为由你自己的后端代理请求,或仅在服务端/命令行环境中调用。
准确性说明
这个接口返回的数字是精确的整数,但它所代表的时间不一定准。误差来源主要有四类:
| 误差来源 | 说明 | 典型量级 |
|---|---|---|
| 网络往返延迟 | 服务器在生成响应的那一刻读取时钟,但你收到响应时已经过去了半个 RTT。接口没有做任何补偿。 | 10 ms – 500 ms |
| 服务器时钟自身漂移 | 站点未承诺其上游时间源(是否接了 NTP、是否校时、精度如何均未说明)。 | 未知 |
| DNS / TLS 握手 | 首次请求包含域名解析与 TLS 协商,耗时更长,进一步放大不确定性。 | 50 ms – 1 s |
| 服务端排队与负载 | 高并发时响应生成时间与请求到达时间的间隔不可控。 | 不定 |
该接口的实用定位是:「让模型知道今天是几号、现在大概几点」, 精度量级在百毫秒到数秒,且无法自我验证。 不要把它当作授时源用于任何需要亚秒级一致性或可追溯性的系统。
降低误差的实用技巧
- 记录请求前后时间,取本地中点作为「服务器时间对应的时刻」,误差上界 = RTT / 2。
- 多次请求取中位数,丢弃 RTT 明显异常(如超过 3 倍中位数)的样本。
- 复用连接 / 预热:首次请求仅用于建立连接,正式取时间用第二次。
- 缓存:同一进程内 30 分钟内不必重复对时,本地单调时钟足够推算。
系统对时(不推荐)
本节之所以存在,只是因为有人会问「能不能拿它来对系统时间」。答案是不推荐。 原因如下:
- 它不是 NTP,没有往返延迟补偿,误差无法被量化。
- 它不提供时钟层次、精度指示、源可信度等元数据,无法判断结果好坏。
- 它依赖 HTTP 与 HTTPS,握手开销远大于 NTP 的 UDP 包,延迟抖动大。
- 它只在 10:00–22:00 稳定可用,夜里无法对时。
- 用错误的授时源校时,比不校时更危险——会让日志、证书、分布式锁全部错位。
正确做法:使用标准 NTP
# Debian / Ubuntu
sudo apt install -y chrony
sudo systemctl enable --now chrony
chronyc sources -v # 查看授时源状态
# 常用公共 NTP 源(示例)
# ntp.aliyun.com
# cn.pool.ntp.org
# time.cloudflare.com
# time.google.com
如果实在要用(仅限低要求的业余场景)
下面这段代码只做「粗校准」,并强制设置误差阈值,超过阈值就放弃校正:
import subprocess, time, urllib.request
MAX_ACCEPTABLE_RTT = 0.30 # 往返延迟超过 300ms 就不采信
MAX_ACCEPTABLE_OFFSET = 5.0 # 偏差超过 5 秒说明本地时钟已经很离谱,人工检查
def coarse_calibrate():
t0 = time.time()
raw = urllib.request.urlopen(
"https://timer.makazs.xyz/get/api64", timeout=5
).read().decode().strip()
t1 = time.time()
rtt = t1 - t0
if rtt > MAX_ACCEPTABLE_RTT:
print(f"放弃:RTT {rtt*1000:.0f} ms 过大")
return False
server_s = int(raw) / 1000.0
offset = server_s - (t0 + t1) / 2
if abs(offset) > MAX_ACCEPTABLE_OFFSET:
print(f"放弃:偏差 {offset:+.2f}s 过大,请用 NTP 排查")
return False
# 注意:settimeofday 需要 root,且会引入 RTT/2 的误差
subprocess.run(["date", "-u", "-s", f"@{server_s:.3f}"], check=True)
print(f"已粗校准,偏差 {offset*1000:+.0f} ms,残留误差 ±{rtt*500:.0f} ms")
return True
上述脚本会直接修改系统时钟。时间回跳可能导致 cron 任务重复触发、数据库事务异常、TLS 证书判定失败。
生产环境请一律使用 chronyd 的 makestep 机制,或至少用 sntp / ntpdate 配合真实 NTP 源。
让联网模型每次启动对一次时间
这是本接口最合适的用法:在 Agent / 模型的会话启动时调用一次,把结果注入上下文, 让模型在后续回答里有一个明确的「当前时间」锚点。
1. 写一个小模块 timeguard.py
"""启动时对时一次,之后复用缓存。"""
import json, pathlib, time, urllib.request
API = "https://timer.makazs.xyz/get/api64"
CACHE = pathlib.Path.home() / ".cache" / "makazs-time.json"
TTL = 30 * 60 # 缓存有效期:30 分钟
TIMEOUT = 4.0
def _fetch():
t0 = time.time()
with urllib.request.urlopen(API, timeout=TIMEOUT) as r:
raw = r.read().decode("utf-8").strip()
t1 = time.time()
server_s = int(raw) / 1000.0
return {
"server_s": server_s,
"offset": server_s - (t0 + t1) / 2, # >0 表示服务器比本地快
"rtt": t1 - t0,
"uncertainty": (t1 - t0) / 2,
"fetched_at": t1,
}
def _load_cache():
try:
info = json.loads(CACHE.read_text("utf-8"))
if time.time() - info["fetched_at"] < TTL:
return info
except Exception:
pass
return None
def now(force=False):
"""返回 (校正后的 Unix 秒, 元信息 dict)。失败时回退本地时钟。"""
info = None if force else _load_cache()
if info is None:
try:
info = _fetch()
CACHE.parent.mkdir(parents=True, exist_ok=True)
CACHE.write_text(json.dumps(info), "utf-8")
except Exception as e:
return time.time(), {"ok": False, "error": str(e)}
return time.time() + info["offset"], {"ok": True, **info}
if __name__ == "__main__":
ts, meta = now(force=True)
if meta["ok"]:
print("UTC :", time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(ts)))
print(f"偏移: {meta['offset']*1000:+.0f} ms")
print(f"延迟: {meta['rtt']*1000:.0f} ms(误差 ±{meta['uncertainty']*1000:.0f} ms)")
else:
print("对时失败,已回退本地时钟:", meta["error"])
2. 在模型 / Agent 启动时调用
# 你的 Agent 初始化流程里
import time
from timeguard import now
def build_system_prompt():
ts, meta = now(force=True)
if meta["ok"]:
stamp = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(ts))
note = (
f"当前 UTC 时间:{stamp}。"
f"该时间来自网络对时,误差约 ±{meta['uncertainty']*1000:.0f} 毫秒。"
f"回答中涉及「现在」「今天」时请以此为准。"
)
else:
stamp = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(ts))
note = (
f"当前 UTC 时间(本地时钟,未校准):{stamp}。"
f"网络对时失败({meta['error']}),时间可能不准,必要时请向用户确认日期。"
)
return "你是一个助手。\n" + note
3. 或者直接写进系统提示词
在开始任何任务之前,先运行 `python timeguard.py` 获取当前 UTC 时间。
后续输出中凡涉及「今天」「现在」「最近」等相对时间,一律以该时间为基准,
不要凭训练数据猜测当前日期。
如果脚本执行失败,明确说明「时间来源为本地时钟,未校准」。
- 启动时一次即可:不要每次工具调用都去请求,既慢又浪费。
- 缓存 + 单调时钟:拿到 offset 后,用本地时间推算即可保持数十毫秒级一致。
- 失败必须降级:夜间服务不可用时,回退本地时钟并如实告知,不要编造时间。
- 时间要带来源:告诉模型「这个时间有多准」,它才知道该不该在回答里加不确定描述。
常见问题
返回的是 UTC 还是北京时间?
返回的是 Unix 时间戳,本质上就是 UTC 秒数/毫秒数,不含时区。
需要北京时间请自行 +8 小时,或使用 zoneinfo.ZoneInfo("Asia/Shanghai")。
为什么半夜访问不了?
站点常规运行窗口为北京时间 10:00–22:00,有时会扩大,但不保证。窗口外不可用属于预期行为,请实现兜底。
能用来做定时任务触发吗?
不建议。定时任务应依赖本机的单调时钟或系统 NTP 同步,而不是每次去拉网络接口。 网络抖动会让触发时间出现秒级偏差。
请求频率有要求吗?
合理做法是启动时一次、之后缓存 30 分钟, 避免把对时接口当成健康检查或轮询目标。
可以返回 JSON 吗?
现有端点均为纯文本数字,无 JSON 版本。若需要结构化数据,请在你自己的服务端做一层包装。
接口挂了怎么办?
兜底顺序建议:
1)读取本地缓存的上次对时结果 + 本地单调时钟推算;
2)回退到系统时钟;
3)在输出中明确标注「时间未经网络校准」。