跳到主要内容
弗美科技
技术分享

企业微信接口同步打卡,时间差了 8 小时

对接企业微信打卡数据,本地跑测试全对,一上服务器导出的考勤表整体差 8 小时。查下来是接口返回的时间戳被格式化了两次,中间按 UTC 又解析了一回。顺带踩了 access_token 缓存、分页 cursor 重复和 2000 行批量插入三个坑,记一下。

2019年3月8日接口对接时区踩坑记录

给一个客户做考勤汇总,每天凌晨从企业微信拉前一天的打卡记录,写进 MySQL,再给 HR 导出 Excel。本地测了三天都对,上线第一天早上,HR 发来一句话:所有人上班时间都晚了 8 小时。

1. 时间戳被转了两次

接口返回的 checkin_time 是 Unix 时间戳,本身没有时区。我们脚本里用 PHP 的 date() 格式化,服务器时区设的是 Asia/Shanghai,这一步没问题。问题是前面还有同事写的一层「统一时间处理」,把时间戳当成字符串又按 UTC 解析了一次,等于多绕了一圈,最后整体偏移。

改法很土:全链路只认时间戳,格式化只在最后导出那一步做,中间不许再转。顺手在数据库里加了一列 raw_ts 存原始值,出事能倒回去看。

2. access_token 每次都重新取

第一版图省事,每个请求都调一次拿 token 的接口。跑 200 多人的数据要几十次请求,有天触发了频率限制,整批失败。改成存 Redis,过期 7000 秒,官方给 7200,留点余量,快到期再刷。

钉钉那边的考勤接口我们早半年接过,坑不一样,频率限制倒是差不多。

3. 分页 cursor 用错了

打卡接口按 cursor 翻页,第一版把上一页最后一条记录的时间当 cursor 传回去,结果边界那条被重复拉了一次,考勤表里多了几条重复。改成老老实实用响应里返回的 next_cursor,并且在写入时按 user_id 加 checkin_time 建了唯一索引,重复的直接忽略。

4. 2000 行一条条插

2000 多行记录,一开始循环单条 INSERT,跑了 20 多秒。改成拼成每 500 行一批的批量 INSERT,降到 1 秒出头。没什么技术含量,就是别忘了。

5. 没考虑补卡

接口里除了正常打卡还有补卡记录,字段一样但来源不同。第一版没区分,把补卡当成当天第二次打卡算进去了。后来加了个 source 字段,导出时按 HR 的规则单独列一列。

收尾

那天上午把 8 小时改回来,重跑了一次全量,HR 那边重新导出。表格发出去之前我们拿三个人的原始时间戳手算了一遍,对着看,没再偏。

后来这份脚本的注释第一行写着:时间只转一次,在最后。

商务咨询 · 免费初步沟通

需要针对你的场景给个建议?

把业务背景和当前系统情况告诉我们,我们会给出可执行的思路。

在线留言

周一至周五 9:00–18:00 · 工作日 9:00–18:00 响应,留言会在一个工作日内回复。

商务微信
商务微信二维码

扫一扫,加商务微信咨询服务与方案报价

或填写需求表单