diff --git a/README.md b/README.md
index 2cda480..70e4201 100644
--- a/README.md
+++ b/README.md
@@ -243,8 +243,8 @@ namespace UnitGenerator
{
this.Type = typeof(T);
this.Options = options;
- }
- }
+ }
+ }
#endif
}
```
@@ -283,11 +283,15 @@ public static bool operator false(Foo x) => !x.value;
public static bool operator !(Foo x) => !x.value;
```
-> When type is Guid or [Ulid](https://github.com/Cysharp/Ulid), also implements `New()` and `New***()` static operator.
+> When type is Guid or [Ulid](https://github.com/Cysharp/Ulid), also implements `New()` and `New***()` static operator.
+> For Guid type in .NET 9.0 or later, these methods accept an optional `uuidV7` parameter. When `uuidV7` is set to `true`, the methods use `Guid.CreateVersion7()` internally.
```csharp
public static GroupId New();
public static GroupId NewGroupId();
+// overload .NET 9.0+
+public static GroupId New(bool uuidV7);
+public static GroupId NewGroupId(bool uuidV7);
```
Second parameter `UnitGenerateOptions options` can configure which method to implement, default is `None`.
diff --git a/UnitGenerator.sln b/UnitGenerator.sln
index 24ed89c..84f73fd 100644
--- a/UnitGenerator.sln
+++ b/UnitGenerator.sln
@@ -19,6 +19,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileGenerate", "sandbox\Fil
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkApp", "src\EntityFrameworkApp\EntityFrameworkApp.csproj", "{51AE7857-4223-40FE-AEA9-F0E64C5F8238}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitGenerator.NET9.Tests", "tests\UnitGenerator.NET9.Tests\UnitGenerator.NET9.Tests.csproj", "{EAC3A025-E49B-4719-8738-9C3B67484A4A}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -45,6 +47,10 @@ Global
{51AE7857-4223-40FE-AEA9-F0E64C5F8238}.Debug|Any CPU.Build.0 = Debug|Any CPU
{51AE7857-4223-40FE-AEA9-F0E64C5F8238}.Release|Any CPU.ActiveCfg = Release|Any CPU
{51AE7857-4223-40FE-AEA9-F0E64C5F8238}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EAC3A025-E49B-4719-8738-9C3B67484A4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EAC3A025-E49B-4719-8738-9C3B67484A4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EAC3A025-E49B-4719-8738-9C3B67484A4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EAC3A025-E49B-4719-8738-9C3B67484A4A}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -55,6 +61,7 @@ Global
{5DA06D43-A023-4464-B856-8BB42E8E4A05} = {187FBF64-D2AA-444D-AFB1-CE999BC6AD34}
{F8353A7A-290E-41D7-A6F8-8D8DBDD44433} = {34EB4113-923D-4855-979C-A0467461B75C}
{51AE7857-4223-40FE-AEA9-F0E64C5F8238} = {34EB4113-923D-4855-979C-A0467461B75C}
+ {EAC3A025-E49B-4719-8738-9C3B67484A4A} = {187FBF64-D2AA-444D-AFB1-CE999BC6AD34}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A64DF779-7829-414F-9E6E-3AF349486508}
diff --git a/src/UnitGenerator/SourceGenerator.cs b/src/UnitGenerator/SourceGenerator.cs
index 06d47ac..6ffcc4a 100644
--- a/src/UnitGenerator/SourceGenerator.cs
+++ b/src/UnitGenerator/SourceGenerator.cs
@@ -554,6 +554,18 @@ public bool TryFormat (Span utf8Destination, out int bytesWritten, ReadOnl
return new {{unitTypeName}}(Guid.NewGuid());
}
+#if NET9_0_OR_GREATER
+ public static {{unitTypeName}} New(bool uuidV7)
+ {
+ return new {{unitTypeName}}(uuidV7 ? Guid.CreateVersion7() : Guid.NewGuid());
+ }
+
+ public static {{unitTypeName}} New{{unitTypeName}}(bool uuidV7)
+ {
+ return new {{unitTypeName}}(uuidV7 ? Guid.CreateVersion7() : Guid.NewGuid());
+ }
+#endif
+
""");
}
diff --git a/tests/UnitGenerator.NET9.Tests/UnitGenerator.NET9.Tests.csproj b/tests/UnitGenerator.NET9.Tests/UnitGenerator.NET9.Tests.csproj
new file mode 100644
index 0000000..4fcb87c
--- /dev/null
+++ b/tests/UnitGenerator.NET9.Tests/UnitGenerator.NET9.Tests.csproj
@@ -0,0 +1,25 @@
+
+
+
+ net9.0
+ enable
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/UnitGenerator.NET9.Tests/UnitOfGuidTests.cs b/tests/UnitGenerator.NET9.Tests/UnitOfGuidTests.cs
new file mode 100644
index 0000000..d6fc7de
--- /dev/null
+++ b/tests/UnitGenerator.NET9.Tests/UnitOfGuidTests.cs
@@ -0,0 +1,35 @@
+using FluentAssertions;
+using System;
+
+namespace UnitGenerator.NET9.Tests;
+
+public class UnitOfGuidTests
+{
+ [Fact]
+ public void Guidv7_v4_Comparison_AsExpected()
+ {
+ // v7
+ TryGetUuidV7Timestamp(Guidv7Unit.New(uuidV7: true).AsPrimitive(), out var v).Should().BeTrue();
+ // ...approximate check
+ v?.ToString("yyyyMMdd").Should().Be(DateTime.UtcNow.ToString("yyyyMMdd"));
+ TryGetUuidV7Timestamp(Guidv7Unit.New().AsPrimitive(), out var _).Should().BeFalse();
+ }
+
+ static bool TryGetUuidV7Timestamp(Guid uuid, out DateTimeOffset? timestamp)
+ {
+ timestamp = null;
+ var uuidString = uuid.ToString("N");
+ // version number is the 13th character
+ if (uuidString[12] == '7')
+ {
+ var timestampHex = uuidString.Substring(0, 12);
+ var milliseconds = Convert.ToInt64(timestampHex, 16);
+ timestamp = DateTimeOffset.FromUnixTimeMilliseconds(milliseconds);
+ return true;
+ }
+ else return false;
+ }
+}
+
+[UnitOf()]
+public readonly partial struct Guidv7Unit { }