GUIDv7.psm1
function Get-DateTimeOffsetFromGUIDv7 { <# .SYNOPSIS Converts a version 7 GUID to a DateTimeOffset representing the timestamp encoded in the GUID. .DESCRIPTION The `Get-DateTimeOffsetFromGUIDv7` function extracts the timestamp from a version 7 GUID and converts it to a `DateTimeOffset` object. Version 7 GUIDs are time-ordered and include a timestamp in their first 6 bytes. This function decodes that timestamp and returns it as a `DateTimeOffset` object. .PARAMETER GUID The version 7 GUID to be converted. The GUID must be of version 7; otherwise, an error will be thrown. The function validates the GUID version before processing. .INPUTS [Guid] The function accepts a GUID object as input, either from the pipeline or as a direct parameter. .OUTPUTS [DateTimeOffset] The function outputs a `DateTimeOffset` object representing the timestamp encoded in the version 7 GUID. .EXAMPLE PS> $guid = [Guid]::CreateVersion7() PS> Get-DateTimeOffsetFromGUIDv7 -GUID $guid This example demonstrates how to pass a GUID to the function and retrieve the corresponding `DateTimeOffset`. .EXAMPLE PS> New-GUIDv7 | Get-DateTimeOffsetFromGUIDv7 This example demonstrates how to pipe a GUID directly to the function. The used cmdlet `New-GUIDv7` is part of the same module and generates a new version 7 GUID. .NOTES - This function only works with version 7 GUIDs. If a GUID of a different version is provided, an error will be thrown. - The function handles endianness to ensure compatibility across systems. .LINK https://github.com/diecknet/GUIDv7 #> [Alias("Convert-GUIDv7")] [CmdletBinding()] [OutputType([DateTimeOffset])] param( [Parameter( ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Mandatory=$true )] [ValidateScript({ if($_.Version -eq 7) { return $true } else { throw [System.ArgumentException]::new("The GUID must be a version 7 GUID. It looks like the provided GUID '$_' is version $($_.Version).") } })] [Guid]$GUID ) process { try { # Create an empty 8-byte array $bytes = [byte[]]::new(8) # Convert the GUID to a byte array (16 bytes) $GUIDBytes = $GUID.ToByteArray($true) # Copy the first 6 bytes of the GUID byte array into positions 2-7 of the 8-byte array [Array]::Copy($GUIDBytes, 0, $bytes, 2, 6) # Reverse if system is little-endian if ([BitConverter]::IsLittleEndian) { [Array]::Reverse($bytes) } # Convert bytes to Int64 $ms = [BitConverter]::ToInt64($bytes, 0) # Return DateTimeOffset from Unix milliseconds return [DateTimeOffset]::FromUnixTimeMilliseconds($ms) } catch { Write-Error "An error occurred while converting the GUID: $_" return $null } } } function New-GUIDv7 { <# .SYNOPSIS Generates a new Version 7 GUID (UUIDv7). .DESCRIPTION The `New-GUIDv7` function generates a new Version 7 GUID (UUIDv7) based on the current timestamp or a specified `DateTimeOffset`. Version 7 GUIDs are time-based and work well for cases where unique IDs with a time order are needed. .PARAMETER DateTimeOffset Specifies the `DateTimeOffset` to use for generating the Version 7 GUID. If not provided, the current timestamp is used. .INPUTS [DateTimeOffset] You can pipe a `DateTimeOffset` object to this function to generate a Version 7 GUID based on the provided timestamp. .OUTPUTS [Guid] The function outputs a Version 7 GUID. .EXAMPLE PS C:\> New-GUIDv7 This example demonstrates how to generate a new Version 7 GUID using the current timestamp. The GUID will be based on the current date and time. .EXAMPLE PS C:\> New-GUIDv7 -DateTimeOffset (Get-Date "2023-01-01T12:00:00Z") This example demonstrates how to generate a Version 7 GUID using a specific `DateTimeOffset`. The GUID will be based on the provided timestamp. .EXAMPLE PS C:\> [DateTimeOffset]::Now | New-GUIDv7 This example demonstrates how to pipe a `DateTimeOffset` object to the function. The function will generate a Version 7 GUID based on the provided timestamp. .NOTES This function requires the .NET implementation of Version 7 GUIDs. Ensure your environment supports this feature. Should be available in .NET 9.0 and later (PowerShell 7.5+). .LINK https://github.com/diecknet/GUIDv7 #> [CmdletBinding()] [OutputType([Guid])] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "", Justification="Does not modify system state.")] param( [Parameter( ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true )] [DateTimeOffset]$DateTimeOffset ) process { if($null -eq $DateTimeOffset) { [guid]::CreateVersion7() } else { [guid]::CreateVersion7($DateTimeOffset) } } } |