timer.makazs.xyz AI 友好 · 纯文本 服务时间 10:00–22:00 (UTC+8)

timer.makazs.xyz 时间 API

一组返回当前 UTC 时间戳的极简 HTTP 接口,主要面向 AI / LLM / 联网 Agent 场景: 让模型在回答前拿到一个可信的「现在」,而不是凭空猜测日期。

⚠️ 这不是 NTP 服务

本接口通过普通 HTTP 请求返回服务器当前时间,没有任何往返延迟补偿与时钟漂移校准。 它不适合用于系统时钟同步、分布式一致性、证书校验、定时任务调度等对时间精度敏感的场景。 请使用标准 NTP / PTP 服务完成这类工作(见 系统对时 一节)。

基础信息

项目值
域名https://timer.makazs.xyz
协议HTTPS(GET)
响应类型text/plain,纯数字字符串
时区返回值为 Unix 时间戳,天然对应 UTC,不含时区信息
认证无,无需 API Key
限流未公开说明,请自觉控制频率(建议 ≥ 10 秒一次)

服务时间

站点通常在北京时间(UTC+8)以下区间内稳定运行:

✅ 常规可用窗口

每日 10:00 — 22:00(UTC+8)

因此任何调用方都必须实现失败兜底:请求超时或解析失败时,回退到本地时钟并在输出中标注「时间来源:本地,未校准」。

接口列表

路径返回示例精度
/get/ai-api/ 13 位毫秒时间戳 1794725561250 毫秒(字符串层面)
/get/api32 10 位秒级时间戳 1794725875 秒
/get/api64 13 位毫秒时间戳 1794725877884 毫秒(字符串层面)
关于「精度」

这里的精度仅指返回字符串的位数,不代表真实时间准确度。 真实误差取决于网络往返延迟与服务器自身时钟,见 准确性说明。

接口详情

GET /get/ai-api/

通用端点,返回毫秒级 Unix 时间戳。路径带结尾斜杠。

GET https://timer.makazs.xyz/get/ai-api/

1794725561250
GET /get/api32

返回秒级 Unix 时间戳(10 位)。适合只需精确到秒的场景,也便于直接喂给 date -d @…。

GET https://timer.makazs.xyz/get/api32

1794725875
GET /get/api64

返回毫秒级 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
服务端排队与负载 高并发时响应生成时间与请求到达时间的间隔不可控。 不定
⛔ 结论

该接口的实用定位是:「让模型知道今天是几号、现在大概几点」, 精度量级在百毫秒到数秒,且无法自我验证。 不要把它当作授时源用于任何需要亚秒级一致性或可追溯性的系统。

降低误差的实用技巧

系统对时(不推荐)

⛔ 不推荐,也不完全准确

本节之所以存在,只是因为有人会问「能不能拿它来对系统时间」。答案是不推荐。 原因如下:

  • 它不是 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)在输出中明确标注「时间未经网络校准」。