You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@shardingsphere.apache.org by zh...@apache.org on 2026/07/04 05:19:03 UTC
(shardingsphere) branch master updated: Compute the Snowflake epoch in UTC instead of the system timezone (#38932)
This is an automated email from the ASF dual-hosted git repository.
terrymanu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/shardingsphere.git
The following commit(s) were added to refs/heads/master by this push:
new a2c8572d344 Compute the Snowflake epoch in UTC instead of the system timezone (#38932)
a2c8572d344 is described below
commit a2c8572d344b3ccd7846e68ded163250d206ed63
Author: Vasiliy Mikhailov <va...@users.noreply.github.com>
AuthorDate: Sat Jul 4 08:18:56 2026 +0300
Compute the Snowflake epoch in UTC instead of the system timezone (#38932)
* Compute the Snowflake epoch in UTC instead of the system timezone
The static EPOCH (2016-11-01 00:00:00) was converted to epoch millis using the JVM default timezone offset, so the generated key timestamps shifted with the server timezone, risking duplicate or mis-ordered keys across deployments in different zones. Use ZoneOffset.UTC so the epoch is timezone-independent.
* Force non-UTC timezone in Snowflake epoch test and add 5.5.4 release note
* Apply spotless formatting to snowflake pom
Signed-off-by: vmihaylov <va...@gmail.com>
* Compose test timezone onto inherited Surefire argLine instead of replacing it
Signed-off-by: Vasiliy Mikhailov <va...@gmail.com>
---------
Signed-off-by: vmihaylov <va...@gmail.com>
Signed-off-by: Vasiliy Mikhailov <va...@gmail.com>
---
RELEASE-NOTES.md | 1 +
infra/algorithm/type/key-generator/type/snowflake/pom.xml | 4 ++++
.../keygen/snowflake/SnowflakeKeyGenerateAlgorithm.java | 5 ++---
.../keygen/snowflake/SnowflakeKeyGenerateAlgorithmTest.java | 11 +++++++++++
4 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md
index c8723984008..bad29fe27a9 100644
--- a/RELEASE-NOTES.md
+++ b/RELEASE-NOTES.md
@@ -33,6 +33,7 @@
1. Sharding: Fix generated actual index names exceeding database identifier length limits while preserving legacy generated index name compatibility - [#38449](https://github.com/apache/shardingsphere/pull/38449)
1. Sharding: Fix AUTO_INTERVAL sharding failure under JVM default locales that use comma decimal separators - [#38806](https://github.com/apache/shardingsphere/pull/38806)
1. DistSQL: Fix case-sensitive storage unit matching in `SHOW RULES USED STORAGE UNIT` - [#38848](https://github.com/apache/shardingsphere/pull/38848)
+1. Sharding: Compute the Snowflake key generator epoch in UTC instead of the JVM default timezone - [#38932](https://github.com/apache/shardingsphere/pull/38932)
### Enhancements
diff --git a/infra/algorithm/type/key-generator/type/snowflake/pom.xml b/infra/algorithm/type/key-generator/type/snowflake/pom.xml
index 95b03564f28..6e7adbc71ca 100644
--- a/infra/algorithm/type/key-generator/type/snowflake/pom.xml
+++ b/infra/algorithm/type/key-generator/type/snowflake/pom.xml
@@ -26,6 +26,10 @@
<artifactId>shardingsphere-infra-algorithm-key-generator-snowflake</artifactId>
<name>${project.artifactId}</name>
+ <properties>
+ <argLine>-Duser.timezone=Asia/Shanghai</argLine>
+ </properties>
+
<dependencies>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
diff --git a/infra/algorithm/type/key-generator/type/snowflake/src/main/java/org/apache/shardingsphere/infra/algorithm/keygen/snowflake/SnowflakeKeyGenerateAlgorithm.java b/infra/algorithm/type/key-generator/type/snowflake/src/main/java/org/apache/shardingsphere/infra/algorithm/keygen/snowflake/SnowflakeKeyGenerateAlgorithm.java
index 6cfae7a44a5..6c2a17350e7 100644
--- a/infra/algorithm/type/key-generator/type/snowflake/src/main/java/org/apache/shardingsphere/infra/algorithm/keygen/snowflake/SnowflakeKeyGenerateAlgorithm.java
+++ b/infra/algorithm/type/key-generator/type/snowflake/src/main/java/org/apache/shardingsphere/infra/algorithm/keygen/snowflake/SnowflakeKeyGenerateAlgorithm.java
@@ -28,9 +28,8 @@ import org.apache.shardingsphere.infra.exception.ShardingSpherePreconditions;
import org.apache.shardingsphere.infra.instance.ComputeNodeInstanceContext;
import org.apache.shardingsphere.infra.instance.ComputeNodeInstanceContextAware;
-import java.time.Instant;
import java.time.LocalDateTime;
-import java.time.ZoneId;
+import java.time.ZoneOffset;
import java.util.Collection;
import java.util.LinkedList;
import java.util.Properties;
@@ -91,7 +90,7 @@ public final class SnowflakeKeyGenerateAlgorithm implements KeyGenerateAlgorithm
private int maxTolerateTimeDifferenceMillis;
static {
- EPOCH = LocalDateTime.of(2016, 11, 1, 0, 0, 0).toInstant(ZoneId.systemDefault().getRules().getOffset(Instant.now())).toEpochMilli();
+ EPOCH = LocalDateTime.of(2016, 11, 1, 0, 0, 0).toInstant(ZoneOffset.UTC).toEpochMilli();
}
@Override
diff --git a/infra/algorithm/type/key-generator/type/snowflake/src/test/java/org/apache/shardingsphere/infra/algorithm/keygen/snowflake/SnowflakeKeyGenerateAlgorithmTest.java b/infra/algorithm/type/key-generator/type/snowflake/src/test/java/org/apache/shardingsphere/infra/algorithm/keygen/snowflake/SnowflakeKeyGenerateAlgorithmTest.java
index a9c45723901..7e7b6f25902 100644
--- a/infra/algorithm/type/key-generator/type/snowflake/src/test/java/org/apache/shardingsphere/infra/algorithm/keygen/snowflake/SnowflakeKeyGenerateAlgorithmTest.java
+++ b/infra/algorithm/type/key-generator/type/snowflake/src/test/java/org/apache/shardingsphere/infra/algorithm/keygen/snowflake/SnowflakeKeyGenerateAlgorithmTest.java
@@ -52,6 +52,9 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
class SnowflakeKeyGenerateAlgorithmTest {
private static final long DEFAULT_SEQUENCE_BITS = 12L;
@@ -60,6 +63,14 @@ class SnowflakeKeyGenerateAlgorithmTest {
private static final ComputeNodeInstanceContext INSTANCE;
+ @Test
+ void assertEpochShouldBeTimezoneIndependent() {
+ // The EPOCH is supposed to represent 2016-11-01 00:00:00 UTC.
+ // It MUST equal the UTC-based value regardless of system timezone.
+ long expectedUtcEpoch = LocalDateTime.of(2016, 11, 1, 0, 0, 0).toInstant(ZoneOffset.UTC).toEpochMilli();
+ assertThat(SnowflakeKeyGenerateAlgorithm.EPOCH, is(expectedUtcEpoch));
+ }
+
static {
ComputeNodeInstanceContext computeNodeInstanceContext = mock(ComputeNodeInstanceContext.class);
when(computeNodeInstanceContext.getWorkerId()).thenReturn(0);