本文总阅读量:  次 | 文章总字数: 2,570 字

个性化文化日历如何保证同日结果可复用:日期规范化、缓存与版本

个性化文化日历如何保证同日结果可复用,关键不是完成一次调用,而是让输入口径、处理状态和结果证据可以复核。本文围绕“如何统一北京时间日期、出生资料版本和缓存键,构建可复用的每日文化日历”给出一套面向真实业务流程的实现方式。

问题与结果

同一资料版本、目标日期和规则版本得到稳定缓存键,历史结果不会被后续生成静默覆盖。

适用场景

  • 个性化每日文化日历
  • 内容订阅和历史查询
  • 文化类组件与小程序

实现前先确定边界

  1. 目标日期必须先统一到 Asia/Shanghai
  2. 缓存键包含资料、日期和规则版本
  3. SSE 完成事件与同步 JSON 必须落到同一结果版本

可验证工作流

个性化文化日历如何保证同日结果可复用工作流架构图

API 编排与职责

步骤 接口 请求方式 用途
生成每日内容 八字每日趋势解读 POST 返回目标日期的基础历法信息和每日文化解读
查询异步任务 异步任务状态查询 GET 后台预生成次日或批量内容

接口地址:

POST https://api.gugudata.com/ai/bazi-daily-insight

最小可运行实现

curl -X POST \
  "https://api.gugudata.com/ai/bazi-daily-insight?appkey=YOUR_APPKEY&responseMode=sync&streaming=false" \
  -H "Content-Type: application/json" \
  -d '{
    "profile": {
      "gender": "女",
      "calendarType": "公历",
      "birthDate": "1992-06-15",
      "birthTime": "09:20:00",
      "birthPlace": "江苏苏州",
      "isLeapMonth": false,
      "language": "zh-CN"
    },
    "targetDate": "2026-08-22"
  }'

name 是可选字段。除非产品确实需要称呼建议,否则不传姓名更符合隐私最小化原则。

农历输入必须把年月日理解为农历日期,并只在真实闰月设置 isLeapMonth=true。例如 2025 年闰六月初一:

{
  "profile": {
    "gender": "女",
    "calendarType": "农历",
    "birthDate": "2025-06-01",
    "birthTime": "09:20:00",
    "isLeapMonth": true,
    "language": "zh-CN"
  },
  "targetDate": "2026-08-22"
}

公历请求不能误传 isLeapMonth=true,非闰月年份也不能伪造闰月;这些情况会返回业务码 501。

服务端应显式构造缓存键:

import hashlib
import json

def build_daily_cache_key(profile: dict, target_date: str) -> str:
    """Build a stable cache key for one profile and target date."""
    canonical = {
        "profile": profile,
        "targetDate": target_date,
        "contractVersion": "v1",
    }
    raw = json.dumps(
        canonical,
        ensure_ascii=False,
        sort_keys=True,
        separators=(",", ":"),
    )
    return hashlib.sha256(raw.encode("utf-8")).hexdigest()

缓存键不能只使用用户 ID。用户修改出生时间、历法或语言后,旧内容不应继续命中。

日期边界设计

targetDate 使用 YYYY-MM-DD。未传时,服务端按北京时间当天处理,但生产系统仍建议显式传入日期,便于日志、缓存和测试复现。

场景 建议
用户主动查询某天 显式传入用户选择的 targetDate
每日零点更新 调度任务按 Asia/Shanghai 生成目标日期
次日内容预生成 在任务记录中同时保存创建时间和目标日期
历史回看 读取已有版本,不重新标记为今日结果

前端显示的日期、接口请求日期、缓存键和历史记录日期必须一致。需要单独核对农历、节气或日期边界时,可以读取 传统历法宜忌参考,并把它作为独立事实来源记录。

结果怎么组织

基础数据区建议展示:

  • 排盘基础.输入信息 的规范化结果;
  • 排盘基础.历法换算 的公历时间、农历日期、生肖与时区;
  • 排盘基础.四柱 的年柱、月柱、日柱和时柱;
  • 排盘基础.八字 的可展示组合;
  • 目标日期 的农历、干支、生肖、星座和节气。

文化解读区按每日主题、事业学习、关系沟通、生活节奏和行动提醒组织。页面可以提供收藏、复制和加入个人待办,但不能自动把文化解读变成必须执行的日程。

响应模式选择

前台交互可使用 SSE,让用户逐步看到内容;服务端定时任务更适合 responseMode=task。如果应用只需要结构化结果,使用同步 JSON 最简单。

SSE 断线后不应把不完整文本写入正式历史记录。只有收到 type=donedone.result 同时包含完整基础数据、六部分文化解读和免责声明后,才能持久化;随后出现的 [DONE] 仅表示事件流结束。异步任务也只有进入 SUCCEEDED 并取得 Data.result 后,才能标记为已生成。

失败分类与降级

出生资料错误属于输入问题,目标日期超出范围或格式错误也应在调用前处理。接口限流或任务失败时,页面可以展示“暂未生成”,但不能回退到其他日期内容且不标记日期。

业务码 HTTP 处理建议
501 400 修正日期、时间、历法、闰月或响应模式
502 429 按退避策略重试
503 403 检查订单有效期
504 401 检查 AppKey 是否缺失或无效
505 403 补充调用额度
900 500 记录请求时间并稍后重试
901 503 依赖暂不可用,不保存或缓存当前结果

如果用户修改个人资料,需要使未来缓存和当前结果同时失效。已保存的历史版本可以保留,但应显示当时使用的资料快照。

隐私最小化

仅收集完成排盘所需的字段。姓名和出生地点均为可选项;没有明确业务用途时不要传递。日志、错误追踪、分析事件和缓存键不得记录 AppKey、姓名或完整出生资料,运维排查应使用请求 ID、接口标识、业务码和脱敏后的日期范围。

数据契约与留痕

字段 作用
profile_version 输入、规则或产物版本,变更时保留旧版本
target_date 带时区的采样或生成时间
timezone 业务数据字段,保存来源、口径和缺失状态
cache_key 业务数据字段,保存来源、口径和缺失状态
request_id 稳定业务标识,用于关联记录和请求追踪
result_version 输入、规则或产物版本,变更时保留旧版本
generated_at 带时区的采样或生成时间
delivery_status 显式状态或原因,禁止以空值代替失败

重试应新增尝试记录,不覆盖最后一次失败。派生结果必须关联输入版本、生成时间和业务状态。

验收清单

  • [ ] 午夜和跨日请求使用明确日期口径
  • [ ] 缓存命中不会跳过版本检查
  • [ ] 历史记录能还原当时使用的资料版本

能力边界

每日趋势和历法内容仅作文化娱乐参考,不应用于替代医疗、财务或其他专业判断。

示例中的 YOUR_APPKEY 仅为占位符。真实密钥只能放在服务端环境变量或密钥管理系统中。

EOF

转载须以超链接形式标明文章原始出处和作者信息

微信公众号二维码