Skip to content

Commit 775671e

Browse files
committed
add UUIDv7 generation option, its test and document
1 parent ad84e76 commit 775671e

File tree

5 files changed

+86
-3
lines changed

5 files changed

+86
-3
lines changed

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,8 @@ namespace UnitGenerator
243243
{
244244
this.Type = typeof(T);
245245
this.Options = options;
246-
  }
247-
    }
246+
}
247+
}
248248
#endif
249249
}
250250
```
@@ -283,11 +283,15 @@ public static bool operator false(Foo x) => !x.value;
283283
public static bool operator !(Foo x) => !x.value;
284284
```
285285

286-
> When type is Guid or [Ulid](https://github.com/Cysharp/Ulid), also implements `New()` and `New***()` static operator.
286+
> When type is Guid or [Ulid](https://github.com/Cysharp/Ulid), also implements `New()` and `New***()` static operator.<br />
287+
> 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.
287288
288289
```csharp
289290
public static GroupId New();
290291
public static GroupId NewGroupId();
292+
// .NET 9.0+
293+
public static GroupId New(bool uuidV7 = false);
294+
public static GroupId NewGroupId(bool uuidV7 = false);
291295
```
292296

293297
Second parameter `UnitGenerateOptions options` can configure which method to implement, default is `None`.

UnitGenerator.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FileGenerate", "sandbox\Fil
1919
EndProject
2020
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EntityFrameworkApp", "src\EntityFrameworkApp\EntityFrameworkApp.csproj", "{51AE7857-4223-40FE-AEA9-F0E64C5F8238}"
2121
EndProject
22+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitGenerator.NET9.Tests", "tests\UnitGenerator.NET9.Tests\UnitGenerator.NET9.Tests.csproj", "{EAC3A025-E49B-4719-8738-9C3B67484A4A}"
23+
EndProject
2224
Global
2325
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2426
Debug|Any CPU = Debug|Any CPU
@@ -45,6 +47,10 @@ Global
4547
{51AE7857-4223-40FE-AEA9-F0E64C5F8238}.Debug|Any CPU.Build.0 = Debug|Any CPU
4648
{51AE7857-4223-40FE-AEA9-F0E64C5F8238}.Release|Any CPU.ActiveCfg = Release|Any CPU
4749
{51AE7857-4223-40FE-AEA9-F0E64C5F8238}.Release|Any CPU.Build.0 = Release|Any CPU
50+
{EAC3A025-E49B-4719-8738-9C3B67484A4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51+
{EAC3A025-E49B-4719-8738-9C3B67484A4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
52+
{EAC3A025-E49B-4719-8738-9C3B67484A4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
53+
{EAC3A025-E49B-4719-8738-9C3B67484A4A}.Release|Any CPU.Build.0 = Release|Any CPU
4854
EndGlobalSection
4955
GlobalSection(SolutionProperties) = preSolution
5056
HideSolutionNode = FALSE
@@ -55,6 +61,7 @@ Global
5561
{5DA06D43-A023-4464-B856-8BB42E8E4A05} = {187FBF64-D2AA-444D-AFB1-CE999BC6AD34}
5662
{F8353A7A-290E-41D7-A6F8-8D8DBDD44433} = {34EB4113-923D-4855-979C-A0467461B75C}
5763
{51AE7857-4223-40FE-AEA9-F0E64C5F8238} = {34EB4113-923D-4855-979C-A0467461B75C}
64+
{EAC3A025-E49B-4719-8738-9C3B67484A4A} = {187FBF64-D2AA-444D-AFB1-CE999BC6AD34}
5865
EndGlobalSection
5966
GlobalSection(ExtensibilityGlobals) = postSolution
6067
SolutionGuid = {A64DF779-7829-414F-9E6E-3AF349486508}

src/UnitGenerator/SourceGenerator.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,18 @@ public bool TryFormat (Span<byte> utf8Destination, out int bytesWritten, ReadOnl
554554
return new {{unitTypeName}}(Guid.NewGuid());
555555
}
556556
557+
#if NET9_0_OR_GREATER
558+
public static {{unitTypeName}} New(bool uuidV7 = false)
559+
{
560+
return new {{unitTypeName}}(uuidV7 ? Guid.CreateVersion7() : Guid.NewGuid());
561+
}
562+
563+
public static {{unitTypeName}} New{{unitTypeName}}(bool uuidV7 = false)
564+
{
565+
return new {{unitTypeName}}(uuidV7 ? Guid.CreateVersion7() : Guid.NewGuid());
566+
}
567+
#endif
568+
557569
""");
558570
}
559571

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<Nullable>enable</Nullable>
6+
<IsPackable>false</IsPackable>
7+
</PropertyGroup>
8+
9+
<ItemGroup>
10+
<PackageReference Include="coverlet.collector" Version="6.0.2" />
11+
<PackageReference Include="FluentAssertions" Version="6.12.2" />
12+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
13+
<PackageReference Include="xunit" Version="2.9.2" />
14+
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<ProjectReference Include="..\..\src\UnitGenerator\UnitGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
19+
</ItemGroup>
20+
21+
<ItemGroup>
22+
<Using Include="Xunit" />
23+
</ItemGroup>
24+
25+
</Project>
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using FluentAssertions;
2+
using System;
3+
4+
namespace UnitGenerator.NET9.Tests;
5+
6+
public class UnitOfGuidTests
7+
{
8+
[Fact]
9+
public void Guidv7_v4_Comparison_AsExpected()
10+
{
11+
// v7
12+
TryGetUuidV7Timestamp(Guidv7Unit.New(uuidV7: true).AsPrimitive(), out var v).Should().BeTrue();
13+
// ...approximate check
14+
v?.ToString("yyyyMMdd").Should().Be(DateTime.UtcNow.ToString("yyyyMMdd"));
15+
TryGetUuidV7Timestamp(Guidv7Unit.New().AsPrimitive(), out var _).Should().BeFalse();
16+
}
17+
18+
static bool TryGetUuidV7Timestamp(Guid uuid, out DateTimeOffset? timestamp)
19+
{
20+
timestamp = null;
21+
var uuidString = uuid.ToString("N");
22+
// version number is the 13th character
23+
if (uuidString[12] == '7')
24+
{
25+
var timestampHex = uuidString.Substring(0, 12);
26+
var milliseconds = Convert.ToInt64(timestampHex, 16);
27+
timestamp = DateTimeOffset.FromUnixTimeMilliseconds(milliseconds);
28+
return true;
29+
}
30+
else return false;
31+
}
32+
}
33+
34+
[UnitOf<Guid>()]
35+
public readonly partial struct Guidv7Unit { }

0 commit comments

Comments
 (0)