fix(sync): 宿主纯日期按当地零点解释 —— 直通会被 JS 当成 UTC 零点,整整偏 8 小时

normalizeDatetime 旧版对纯日期('2026-05-10')直通不补 offset,下游 new Date() 按 ISO
规范解析成 **UTC 零点**;而宿主给的是**当地日期**(jvs-dw 的 DW 是 Asia/Shanghai):
    DW created_date = 2022-09-30(北京)
      旧:2022-09-30T00:00:00Z = 北京 09-30 08:00  
      新:2022-09-29T16:00:00Z = 北京 09-30 00:00  

【怎么发现的】回访补 source_created_at 时,手写回填(按 +08:00)与摄入路径写出的值
差整 8 小时。查下去发现不是新字段的问题,是这条既有路径 —— 测试服实测
diagnosis_record 有 106,860 条 occurred_at 落在 UTC 零点(占 6%),正是它;
落在 UTC 16:00(正确形态)的只有 5 条。

【边界:为什么不怕补 offset 导致跨日】本函数只作用于 CanonicalResourceMeta.datetimeFields
声明的字段,那些目标列全是 timestamptz。真正的纯日期列(patient_return_visit.taskDate /
patient.birthDate)刻意不在该清单里,走各自 new Date() 直解 —— 对它们补 offset 会让 PG
取 UTC 日期时退一天。新增字段按"目标列类型"归类,不能凭字段名像不像时间。

【存量】老数据不会自动修正(需 reparse,会触发一次性 fact 版本波)。偏差是 8 小时、
日期级判断基本不受影响,故不随本次修 —— 但新摄入的数据从此正确。
️ 若不修,回访刚回填好的正确值会被下一轮增量覆盖成错的。

测试 815 项(+7),含"旧行为偏 8 小时"的固化回归。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Found errors in your .gitlab-ci.yml:

  • jobs:openapi-drift config contains unknown keys: rules
You can also test your .gitlab-ci.yml in the Lint
Status Job ID Name Coverage