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

推荐订阅源

GbyAI
GbyAI
博客园 - 三生石上(FineUI控件)
S
Securelist
U
Unit 42
The Cloudflare Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Simon Willison's Weblog
Simon Willison's Weblog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
B
Blog
T
Tenable Blog
The Hacker News
The Hacker News
The Register - Security
The Register - Security
IT之家
IT之家
博客园 - 【当耐特】
Spread Privacy
Spread Privacy
P
Privacy & Cybersecurity Law Blog
博客园_首页
T
Tailwind CSS Blog
人人都是产品经理
人人都是产品经理
C
Cybersecurity and Infrastructure Security Agency CISA
Know Your Adversary
Know Your Adversary
NISL@THU
NISL@THU
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
T
Tor Project blog
C
CERT Recently Published Vulnerability Notes
Apple Machine Learning Research
Apple Machine Learning Research
Stack Overflow Blog
Stack Overflow Blog
T
Threat Research - Cisco Blogs
T
The Exploit Database - CXSecurity.com
V
Vulnerabilities – Threatpost
A
Arctic Wolf
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
V
V2EX
aimingoo的专栏
aimingoo的专栏
大猫的无限游戏
大猫的无限游戏
Scott Helme
Scott Helme
L
LINUX DO - 热门话题
Cyberwarzone
Cyberwarzone
V
Visual Studio Blog
月光博客
月光博客
爱范儿
爱范儿
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
美团技术团队
G
GRAHAM CLULEY
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
H
Heimdal Security Blog
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO

博客园 - 张占岭

springboot~关于构造方法注入和字段注入的选择 apisix~OpenResty各阶段的介绍 keycloak~aud受众字段的作用及如何生成 wso2~关于workbuddy中mcp在wso2中的授权端点 k8s~避免调度资源碎片化 WEB安全~csrf介绍 WEB安全~DPoP的介绍 WEB安全~csp的介绍 什么是中间人攻击 WEB安全~xss的介绍 k8s~pod资源限制和JVM的XMX配置 关于对wso2和keycloak的token交换的调研 keycloak~实现OAuth 2.0 Token Exchange backstage~实体的介绍及它们的关系 backstage~openapi的接入与protobuf的对比 backstage~将java服务添加到backstage backstage~对接github和gitlab backstage~开始一个backstage应用 apisix~graphQL的支持 wso2几个核心项目介绍 docker~BuildKit的介绍 k8s~secret资源的使用 wso2~4.5升级到4.6需要更新的数据表 backstage~Backstage的概述 springboot~jpa优雅的软删除能力 springboot~ImportBeanDefinitionRegistrar在自定义RPC框架中的使用 keycloak~深入了解DefaultSegmentedDataContainer对象解决内存泄漏 keycloak~分布式部署中会话过期清理机制 wso2~通过三方IDP的token置换wso2的token jmeter进行接口压测 Keycloak~infinispan中MergedUpdate中lifespanMs和maxIdleTimeMs wso2~添加mcp服务的注意点
算法~时间戳计算两个日期是否为同天同时同分
张占岭 · 2026-03-26 · via 博客园 - 张占岭

UTC时间戳验证两个日期是否为同一天的核心原理在于:时间戳是绝对的时间点,而“天”是依赖于特定时区(如UTC)的人为划分区间。通过将两个绝对时间点转换到同一时区后,比较它们的年、月、日是否完全相同。

具体原理可分以下几步理解:

1. 时间戳的本质

Unix时间戳(通常指秒数或毫秒数)是从 1970-01-01 00:00:00 UTC 开始经过的时间长度。它是一个绝对的时间度量,不携带时区信息。
例如:1710000000 这个数值代表全球同一瞬间。

2. “天”是时区相关的区间

“同一天”并不是指时间戳数值相近,而是指在某个特定时区的日历上,它们属于同一个日期(年、月、日)。

  • UTC+0 时区,一天是从 00:00:0023:59:59.999...
  • UTC+8 时区,同一天对应的UTC时间区间会偏移8小时

因此,判断“同一天”必须先确定一个时区。如果题目特指“UTC时间戳验证同一天”,那么通常就是以 UTC 作为参考时区。

3. 验证逻辑

验证两个时间戳 t1t2 在UTC时区是否为同一天的步骤:

  1. 取整:如果时间戳是毫秒级,通常先除以1000转为秒(或保留毫秒但后续计算时注意边界)。
  2. 计算每个时间戳对应的UTC日期
    • 将时间戳(秒数)转换为UTC时间的年、月、日。
    • 这可以通过编程语言的内置函数完成(如JavaScript的 new Date(timestamp).getUTCFullYear() 等)。
  3. 比较:如果两个时间戳的 年、月、日 完全相同,则它们是UTC下的同一天。

4. 边界情况:时区转换的等效原理

在数学上,这等价于计算两个时间戳在UTC时区下距离某个纪元日的天数是否相等。

days = floor(timestamp / 86400)(86400为一天的秒数)。
如果两个时间戳除以86400取整后的结果相等,那么它们在UTC时区就是同一天。

但需要注意:

  • 这个取整公式 floor(t / 86400) 隐含了UTC时区,因为Unix纪元的起点是 1970-01-01 00:00:00 UTC
  • 直接比较 floor(t1/86400) == floor(t2/86400) 在数学上等价于UTC时区的日期比较,但前提是时间戳是精确到秒且没有闰秒干扰(Unix时间戳忽略闰秒)。

5. 为什么要强调UTC

如果问题中明确说“UTC时间戳验证两个日期为同一天”,那么原理就是利用UTC时区下天数索引的一致性。如果换成其他时区(如北京时间),则需要在计算时先加上时区偏移量,再取天数的整数部分。

总结:原理就是将绝对的时间戳映射到UTC时区下的日历日期,通过比较年、月、日(或等价地比较从纪元开始的天数)来判断是否为同一天。

Java代码实现

/**
	 * UTC时间戳验证同一天、同一小时、同一分钟
	 */
	@Test
	public void utcTimeStampDayHourMin() {
		long sameDay = 24 * 60 * 60 * 1000;
		long sameHour = 60 * 60 * 1000;
		long sameMinute = 60 * 1000;
		LocalDateTime ldt = LocalDateTime.of(2026, 1, 1, 0, 50, 0);
		LocalDateTime ldt2 = LocalDateTime.of(2026, 1, 1, 23, 50, 0);
		long d1 = ldt.toInstant(ZoneOffset.UTC).toEpochMilli() / sameDay;
		long d2 = ldt2.toInstant(ZoneOffset.UTC).toEpochMilli() / sameDay;
		log.info("同一天 d1: {}, d2: {}, same day: {}", d1, d2, d1 == d2);

		LocalDateTime ldt3 = LocalDateTime.of(2026, 1, 1, 0, 50, 0);
		LocalDateTime ldt4 = LocalDateTime.of(2026, 1, 1, 0, 10, 0);
		long d3 = ldt3.toInstant(ZoneOffset.UTC).toEpochMilli() / sameHour;
		long d4 = ldt4.toInstant(ZoneOffset.UTC).toEpochMilli() / sameHour;
		log.info("同一天同一小时 d3: {}, d4: {}, same hour: {}", d3, d4, d3 == d4);

		LocalDateTime ldt5 = LocalDateTime.of(2026, 1, 1, 0, 50, 0);
		LocalDateTime ldt6 = LocalDateTime.of(2026, 1, 1, 0, 50, 30);
		long d5 = ldt5.toInstant(ZoneOffset.UTC).toEpochMilli() / sameMinute;
		long d6 = ldt6.toInstant(ZoneOffset.UTC).toEpochMilli() / sameMinute;
		log.info("同一天同一小时同一分钟 d5: {}, d6: {}, same minute: {}", d5, d6, d5 == d6);
	}