惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
云风的 BLOG
云风的 BLOG
B
Blog
博客园 - Franky
I
InfoQ
A
About on SuperTechFans
博客园_首页
L
LangChain Blog
量子位
腾讯CDC
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
美团技术团队
V
V2EX
Apple Machine Learning Research
Apple Machine Learning Research
雷峰网
雷峰网
MongoDB | Blog
MongoDB | Blog
Microsoft Azure Blog
Microsoft Azure Blog
月光博客
月光博客
T
The Blog of Author Tim Ferriss
P
Proofpoint News Feed
G
Google Developers Blog
Last Week in AI
Last Week in AI

Go 编程语言

WorkBuddy + 企业微信 有人用过吗? - V2EX 业务系统开发语言从 PHP / Python 转向 Go 如何实现数据的存储 - V2EX [2026 最新] Go 1.27 泛型方法完全解读 - V2EX Go 后台接入 SSO 后,本地用户表应该怎么退? - V2EX clbtransport - 自带负载均衡的 http.Transport 简易替代 - V2EX 基于 go+react 开发的一款可私有化部署、任务驱动的代码托管平台 iForge - V2EX 分享一个还在 RC 阶段的项目:把 C 编译成不依赖 cgo 的 Go package - V2EX [工业边缘网关] EdgeX 更新啦,增加了 MCP,可以被 AI 接管了,可以让 AI 控制物理世界啦 [工业边缘网关] EdgeX 更新啦 上线了官网 顺便更新版本 v0.10.0 有了 Agent,后台脚手架是该退场,还是变成约束层? 强兼 Claude Code:左 DeepSeek V4,右 Kimi K3 构建时自动注入版本号:从 Git tag 到 Go 可执行文件 [边缘计算] 想借助 AI 来开发 边缘网关接入 AI 解决设备通信 不知道有没有需求 [Go]工业边缘计算网关 edgex 业余时间独立开发 持续更新半年咯 求个 star eget:不用等中央仓库,直接安装 GitHub 和任意下载站的工具 gookit/gcli v3.8:新增支持共享选项、文档生成和参数重排 V2EX 我开源了一款极简的 P2P 文件传输与 VPN 工具 (Win/Mac/ Linux /Android) gookit/gcli v3.5.0 发布 - 简单易用、功能丰富的 Go 命令行应用与工具库 用 Go gRPC 信令对接 Android WebRTC:大家一般怎么划分网关和客户端边界? 在服务端用 Pion + FFmpeg + RNN 做 WebRTC 通话降噪,值得吗? 这两种 lint 报错场景, v 友们一般怎么处理 tikrok 的部分来时路 tikrok 第 7 代微服务重构: Golang 微服务 grpc 接口与服务实现隔离方案 写了个 Go 库:在 TCP 应用协议开始前做认证,也支持端口敲门 Tikrok v6.0 新的生产级架构,成本不变,但是部署复杂略有增加 go 打包的二进制程序怎么反编译 [边缘计算开源] 工业数据采集网关 版本更新 用 golang 写了,一套面向个人音乐资产的本地优先音乐系统 做了个 Go 的 MCP Server 框架,一行代码把 Gin API 接入 AI
日期函数获取上一个月 bug, 在一些特殊日子才出现,比如今天 ...
Qjues · 2025-10-31 · via Go 编程语言

今天生产环境出现比较多的异常,挺纳闷的,毕竟最近该服务没有怎么迭代。

经过排查定位发现,居然是某些特殊日子才会出现的问题。

RetentionMonths = 3 MonthTablePrefix = "jobs_"

代码是一个分表逻辑中,获取最近月份的表,通过 AddDate(0, -i, 0) 函数获取前几个月的表。应返回当前月和前 3 个月的分表名数组。[jobs_202510 jobs_202509 jobs_202508 jobs_202507]( golang 1.19 )

// GetRecentHotTables 获取最近 n 个月的热表名称列表
func (j jobPartitionRepositoryImpl) GetRecentHotTables() []string {
	months := RetentionMonths

	tables := make([]string, 0, months)
	now := time.Now()

	for i := 0; i <= months; i++ {
		date := now.AddDate(0, -i, 0)
		year := date.Format("2006")
		month := date.Format("01")
		tableName := fmt.Sprintf("%s%s%s", MonthTablePrefix, year, month)
		tables = append(tables, tableName)
	}

	return tables
}

光看代码感觉是没啥问题的,为啥怀疑到这段代码,也是通过日志发现,查询表的 sql 只查 2025-10, 2025-08, 2025-07 表,缺了 2025-09 表。

所以本地验证一番。(单元测试还通过了。。。因为验证的代码和里面一样。。。)

=== RUN   TestGetRecentHotTables
--- PASS: TestGetRecentHotTables (0.00s)
=== RUN   TestGetRecentHotTables/默认获取最近 3 个月表
[jobs_202510 jobs_202510 jobs_202508 jobs_202507]
    --- PASS: TestGetRecentHotTables/默认获取最近 3 个月表 (0.00s)
PASS

看输出发现 jobs_202510 jobs_202510 有两个,问题就在这里了。

now := time.Now()
fmt.Println(now.AddDate(0, -1, 0).Format("200601"))

预期是输出 202509 的,但现实是 202510

那为什么呢?通过询问 google ,找到下面相关文章说明,大致意思就是,因为 10-31 减去一个月为 09-31, 但是又因为 9 月没有 31 号,就将日期标准化为 10-01 ,保证了 time 值的有效性。

https://github.com/golang/go/issues/31145 https://learnku.com/articles/71760

在 learnku 文章中提到 php ,然后用 php 类似函数试了一下,也有类似问题( php8.1 )

echo date('Y-m-d', strtotime('-1 months'));

// 2025-10-01

周五给我整个这个,真是够了。

修改方案, 减去当前时间的天数,时间调整到上一个月最后一天:

now := time.Now()
now.AddDate(0, 0, -now.Day())

js moment 试了是正常的

console.log(moment(new Date()).subtract(1, 'months').format('YYYY-MM-DD'))