diff --git a/guid/pom.xml b/guid/pom.xml
new file mode 100644
index 0000000..786fd4c
--- /dev/null
+++ b/guid/pom.xml
@@ -0,0 +1,37 @@
+
+
+
+
+ 4.0.0
+
+ cn.org.codecrafters
+ jdevkit
+ 1.0.0
+
+
+ guid
+
+
+ 17
+ 17
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/guid/src/main/java/cn/org/codecrafters/guid/GuidCreator.java b/guid/src/main/java/cn/org/codecrafters/guid/GuidCreator.java
new file mode 100644
index 0000000..d9362c4
--- /dev/null
+++ b/guid/src/main/java/cn/org/codecrafters/guid/GuidCreator.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2023 CodeCraftersCN.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0"
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package cn.org.codecrafters.guid;
+
+/**
+ * The `GuidCreator` is a generic interface for generating globally unique
+ * identifiers (GUIDs) of a specific type.
+ *
+ * The type of ID is determined by the class implementing this interface.
+ *
+ * @param this represents the type of the Global Unique Identifier
+ */
+public interface GuidCreator {
+
+ /**
+ * Generates and returns the next globally unique ID.
+ * The exact implementation of how the globally unique ID is generated and
+ * returned will depend on the class implementing this method.
+ *
+ * @return the next globally unique ID
+ */
+ IdType nextId();
+
+}
\ No newline at end of file
diff --git a/guid/src/main/java/cn/org/codecrafters/guid/SnowflakeGuidCreator.java b/guid/src/main/java/cn/org/codecrafters/guid/SnowflakeGuidCreator.java
new file mode 100644
index 0000000..52874e7
--- /dev/null
+++ b/guid/src/main/java/cn/org/codecrafters/guid/SnowflakeGuidCreator.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2023 CodeCraftersCN.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0"
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package cn.org.codecrafters.guid;
+
+import cn.org.codecrafters.guid.exceptions.TimingException;
+
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+
+/**
+ * SnowflakeGuidCreator is a GUID generator based on the Snowflake algorithm.
+ * It generates unique identifiers using a combination of timestamp, worker ID,
+ * and data center ID.
+ *
+ * The Snowflake algorithm allows for the generation of 64-bit long integers,
+ * with the following bit distribution:
+ * - 1 bit for sign
+ * - 41 bits for timestamp (in milliseconds)
+ * - 5 bits for data center ID
+ * - 5 bits for worker ID
+ * - 12 bits for sequence number (per millisecond)
+ *
+ *
The worker ID and data center ID must be specified during initialization,
+ * and they must be within the valid range defined by the bit size.
+ * The generator maintains an internal sequence number that increments for IDs
+ * generated within the same millisecond. If the system clock moves backwards,
+ * an exception is thrown to avoid generating IDs with repeated timestamps.
+ *
+ * @author Zihlu Wang
+ * @version 1.0.0
+ * @since 14 Jul 2023
+ */
+public final class SnowflakeGuidCreator implements GuidCreator {
+
+ /**
+ * Default Custom Epoch (January 1, 2015, Midnight UTC = 2015-01-01T00:00:00Z)
+ */
+ private static final long DEFAULT_CUSTOM_EPOCH = 1_420_070_400_000L;
+
+ /**
+ * The start epoch timestamp to generate IDs from.
+ */
+ private final long startEpoch;
+
+ /**
+ * The number of bits reserved for the worker ID.
+ */
+ private final long workerIdBits = 5L;
+
+ /**
+ * The number of bits reserved for the data center ID.
+ */
+ private final long dataCentreIdBits = 5L;
+
+ /**
+ * The worker ID assigned to this generator.
+ */
+ private final long workerId;
+
+ /**
+ * The data center ID assigned to this generator.
+ */
+ private final long dataCentreId;
+
+ /**
+ * The current sequence number.
+ */
+ private long sequence = 0L;
+
+ /**
+ * The timestamp of the last generated ID.
+ */
+ private long lastTimestamp = -1L;
+
+ /**
+ * Constructs a SnowflakeGuidGenerator with the default start epoch and custom worker ID, data center ID.
+ *
+ * @param workerId the worker ID (between 0 and 31).
+ * @param dataCentreId the data center ID (between 0 and 31).
+ */
+ public SnowflakeGuidCreator(long workerId, long dataCentreId) {
+ this(DEFAULT_CUSTOM_EPOCH, workerId, dataCentreId);
+ }
+
+ /**
+ * Constructs a SnowflakeGuidGenerator with a custom epoch, worker ID, and data center ID.
+ *
+ * @param startEpoch the custom epoch timestamp (in milliseconds) to start generating IDs from
+ * @param workerId the worker ID (between 0 and 31)
+ * @param dataCentreId the data center ID (between 0 and 31)
+ * @throws IllegalArgumentException if the start epoch is greater than the current timestamp,
+ * or if the worker ID or data center ID is out of range
+ */
+ public SnowflakeGuidCreator(long startEpoch, long workerId, long dataCentreId) {
+ if (startEpoch > currentTimestamp()) {
+ throw new IllegalArgumentException("Start Epoch can not be greater than current timestamp!");
+ }
+
+ var maxWorkerId = ~(-1L << workerIdBits);
+ if (workerId > maxWorkerId || workerId < 0) {
+ throw new IllegalArgumentException(String.format("Worker Id can't be greater than %d or less than 0",
+ maxWorkerId));
+ }
+
+ var maxDataCentreId = ~(-1L << dataCentreIdBits);
+ if (dataCentreId > maxDataCentreId || dataCentreId < 0) {
+ throw new IllegalArgumentException(String.format("Data Centre Id can't be greater than %d or less than 0",
+ maxDataCentreId));
+ }
+
+ this.startEpoch = startEpoch;
+ this.workerId = workerId;
+ this.dataCentreId = dataCentreId;
+ }
+
+ /**
+ * Generates the next unique ID.
+ *
+ * @return the generated unique ID
+ * @throws TimingException if the system clock moves backwards,
+ * indicating an invalid sequence of timestamps.
+ */
+ @Override
+ public synchronized Long nextId() {
+ var timestamp = currentTimestamp();
+
+ // If the current time is less than the timestamp of the last ID generation, it means that the system clock
+ // has been set back and an exception should be thrown.
+ if (timestamp < lastTimestamp) {
+ throw new TimingException("Clock moved backwards. Refusing to generate id for %d milliseconds"
+ .formatted(lastTimestamp - timestamp));
+ }
+
+ // If generated at the same time, perform intra-millisecond sequences
+ long sequenceBits = 12L;
+ if (lastTimestamp == timestamp) {
+ long sequenceMask = ~(-1L << sequenceBits);
+ sequence = (sequence + 1) & sequenceMask;
+ // Sequence overflow in milliseconds
+ if (sequence == 0) {
+ // Block to the next millisecond, get a new timestamp
+ timestamp = awaitToNextMillis(lastTimestamp);
+ }
+ }
+ // Timestamp change, sequence reset in milliseconds
+ else {
+ sequence = 0L;
+ }
+
+ // Timestamp of last ID generation
+ lastTimestamp = timestamp;
+
+ // shifted and put together by or operations to form a 64-bit ID
+ var timestampLeftShift = sequenceBits + workerIdBits + dataCentreIdBits;
+ var dataCentreIdShift = sequenceBits + workerIdBits;
+ return ((timestamp - startEpoch) << timestampLeftShift)
+ | (dataCentreId << dataCentreIdShift)
+ | (workerId << sequenceBits)
+ | sequence;
+ }
+
+ /**
+ * Blocks until the next millisecond to obtain a new timestamp.
+ *
+ * @param lastTimestamp the timestamp when the last ID was generated
+ * @return the current timestamp
+ */
+ private long awaitToNextMillis(long lastTimestamp) {
+ var timestamp = currentTimestamp();
+ while (timestamp <= lastTimestamp) {
+ timestamp = currentTimestamp();
+ }
+ return timestamp;
+ }
+
+ /**
+ * Returns the current timestamp in milliseconds.
+ *
+ * @return the current timestamp
+ */
+ private long currentTimestamp() {
+ return LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli();
+ }
+}
+
diff --git a/guid/src/main/java/cn/org/codecrafters/guid/exceptions/TimingException.java b/guid/src/main/java/cn/org/codecrafters/guid/exceptions/TimingException.java
new file mode 100644
index 0000000..f445bc4
--- /dev/null
+++ b/guid/src/main/java/cn/org/codecrafters/guid/exceptions/TimingException.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2023 CodeCraftersCN.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0"
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package cn.org.codecrafters.guid.exceptions;
+
+/**
+ * The TimingException class represents an exception that is thrown when there is an error related
+ * to time sequence.
+ *
+ * This class extends the RuntimeException class, which means that instances of TimingException
+ * do not need to be declared in a method or constructor's throws clause.
+ *
+ * Instances of TimingException can be created with or without a message and a cause. The message
+ * provides a description of the exception, while the cause represents the underlying cause of the
+ * exception and provides additional information about the error.
+ *
+ * TimingException is typically used to handle exceptions related to timing, such as timeouts or
+ * synchronization issues. It is a subclass of RuntimeException, which means it is an unchecked
+ * exception and does not need to be caught or declared.
+ *
+ *
+ * @author Zihlu Wang
+ * @since 1.0.0
+ */
+public class TimingException extends RuntimeException {
+
+ /**
+ * A custom exception that is thrown when there is an issue with timing or scheduling.
+ */
+ public TimingException() {
+ }
+
+ /**
+ * A custom exception that is thrown when there is an issue with timing or scheduling with
+ * customized error message.
+ *
+ * @param message customized message
+ */
+ public TimingException(String message) {
+ super(message);
+ }
+
+ /**
+ * A custom exception that is thrown when there is an issue with timing or scheduling with
+ * customized error message.
+ *
+ * @param message customized message
+ * @param cause the cause of this exception
+ */
+ public TimingException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * A custom exception that is thrown when there is an issue with timing or scheduling with
+ * customized error message.
+ *
+ * @param cause the cause of this exception
+ */
+ public TimingException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/guid/src/main/java/cn/org/codecrafters/guid/package-info.java b/guid/src/main/java/cn/org/codecrafters/guid/package-info.java
new file mode 100644
index 0000000..b88b3ec
--- /dev/null
+++ b/guid/src/main/java/cn/org/codecrafters/guid/package-info.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 CodeCraftersCN.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0"
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * The package provides a set of tools for generating globally unique
+ * identifiers (GUIDs).
+ *
+ * The goal of this library is to provide an efficient, reliable way to
+ * generate globally unique identifiers without requiring any specific
+ * environment or configuration.
+ *
+ * Key features include:
+ *
+ * - Efficient generation of globally unique identifiers
+ * - High performance and quick response
+ * - Easy to integrate
+ *
+ *
+ * @since 2023.2
+ */
+package cn.org.codecrafters.guid;
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 2192302..0917b83 100644
--- a/pom.xml
+++ b/pom.xml
@@ -15,6 +15,9 @@
1.0.0
pom
+
+ guid
+
17