Eigenverft.Manifested.Drydock.Version.ps1
function Convert-DateTimeTo64SecVersionComponents { <# .SYNOPSIS Encode DateTime to 64s-packed version (Build.Major.Minor.Revision), UTC-internal. .DESCRIPTION Seconds since Jan 1 (UTC) >> 6, split: HighPart (0..7), LowPart (16-bit). Minor = (Year * 10) + HighPart. Valid for years where Minor ≤ 65535. #> [CmdletBinding()] [Alias('cdv64')] param( [Parameter(Mandatory=$true)][int]$VersionBuild, [Parameter(Mandatory=$true)][int]$VersionMajor, [Parameter()][datetime]$InputDate = (Get-Date).ToUniversalTime() ) $dtUtc = $InputDate.ToUniversalTime() if ($dtUtc.Year -lt 1 -or $dtUtc.Year -gt 9999) { throw "Year must be 1..9999." } $startOfYear = New-Object datetime ($dtUtc.Year,1,1,0,0,0,[datetimekind]::Utc) $elapsedSeconds = [int](([timespan]($dtUtc - $startOfYear)).TotalSeconds) $shifted = $elapsedSeconds -shr 6 $low = $shifted -band 0xFFFF $high = $shifted -shr 16 if ($high -lt 0 -or $high -gt 7) { throw "Internal HighPart=$high out of 0..7." } $minor = ($dtUtc.Year * 10) + $high if ($minor -gt 65535) { throw "VersionMinor=$minor (>65535). Use year ≤ 6552 or change packing." } @{ VersionFull = "$($VersionBuild).$($VersionMajor).$minor.$low" VersionBuild = "$VersionBuild" VersionMajor = "$VersionMajor" VersionMinor = "$minor" VersionRevision = "$low" } } function Convert-64SecVersionComponentsToDateTime { <# .SYNOPSIS Decode 64s-packed version back to approximate UTC DateTime. .DESCRIPTION Expects: Minor = Year*10 + HighPart, Revision = Low 16 bits. Robust year extraction (integer decade + normalization) to avoid rounding bugs. #> [CmdletBinding()] [Alias('cdv64r')] param( [Parameter(Mandatory=$true)][int]$VersionBuild, [Parameter(Mandatory=$true)][int]$VersionMajor, [Parameter(Mandatory=$true)][int]$VersionMinor, [Parameter(Mandatory=$true)][int]$VersionRevision ) if ($VersionMinor -lt 0) { throw "VersionMinor must be >= 0." } # --- Robust decade split (avoid rounding-to-nearest bugs) --- # Use integer truncation then normalize remainder into 0..9. $year = [int]($VersionMinor / 10) # truncates toward zero for positives $high = $VersionMinor - ($year * 10) if ($high -lt 0) { $year -= 1; $high += 10 } elseif ($high -gt 9) { $year += 1; $high -= 10 } if ($year -lt 1 -or $year -gt 9999) { throw "Decoded year $year out of 1..9999." } if ($high -lt 0 -or $high -gt 7) { throw "HighPart $high out of range 0..7 not an encoded 64s version." } $low = $VersionRevision -band 0xFFFF if ($VersionRevision -ne $low) { throw "VersionRevision $VersionRevision exceeds 16 bits." } $shifted = ($high -shl 16) -bor $low $isLeap = [datetime]::IsLeapYear($year) $secondsInYear = if ($isLeap) { 31622400 } else { 31536000 } $maxShifted = [int][math]::Floor(($secondsInYear - 1) / 64) if ($shifted -gt $maxShifted) { throw "ShiftedSeconds $shifted exceeds max $maxShifted for year $year components invalid." } $startOfYearUtc = New-Object datetime ($year,1,1,0,0,0,[datetimekind]::Utc) $computed = $startOfYearUtc.AddSeconds($shifted * 64) @{ VersionBuild = $VersionBuild VersionMajor = $VersionMajor ComputedDateTime = $computed } } function Convert-DateTimeTo64SecPowershellVersion { <# .SYNOPSIS Converts a DateTime to a simplified three-part version string using 64-second encoding. .DESCRIPTION This function wraps Convert-DateTimeTo64SecVersionComponents and remaps its four-part version into a simplified three-part version. The mapping is: - New Build remains the same. - New Major is the original VersionMinor. - New Minor is the original VersionRevision. The resulting version is in the form: "Build.NewMajor.NewMinor" (e.g., if the original output is 1.0.20250.1234, the simplified version becomes "1.20250.1234"). .PARAMETER VersionBuild An integer representing the build version component. .PARAMETER InputDate An optional UTC DateTime. If not provided, the current UTC time is used. .EXAMPLE PS C:\> Convert-DateTimeTo64SecPowershellVersion -VersionBuild 1 -InputDate (Get-Date) #> [CmdletBinding()] [alias("cdv64ps")] param( [Parameter(Mandatory = $true)] [int]$VersionBuild, [Parameter(Mandatory = $false)] [datetime]$InputDate = (Get-Date).ToUniversalTime() ) # Call the original conversion function, assuming VersionMajor is 0. $original = Convert-DateTimeTo64SecVersionComponents -VersionBuild $VersionBuild -VersionMajor 0 -InputDate $InputDate # Remap: New Major = original VersionMinor, New Minor = original VersionRevision. $newMajor = $original.VersionMinor $newMinor = $original.VersionRevision $versionFull = "$($original.VersionBuild).$newMajor.$newMinor" return @{ VersionFull = $versionFull; VersionBuild = $original.VersionBuild; VersionMajor = $newMajor; VersionMinor = $newMinor } } function Convert-64SecPowershellVersionToDateTime { <# .SYNOPSIS Reconstructs an approximate DateTime from a simplified three-part version using 64-second encoding. .DESCRIPTION This function reverses the mapping performed by Convert-DateTimeTo64SecPowershellVersion. It expects the simplified version in the form: VersionBuild.NewMajor.NewMinor where: - NewMajor corresponds to the original VersionMinor (encoding the high part of the DateTime). - NewMinor corresponds to the original VersionRevision (encoding the low part of the DateTime). Since the original VersionMajor is not preserved in the simplified version, it is assumed to be 0. The function calls Convert-64SecVersionComponentsToDateTime with these mapped values to reconstruct the approximate DateTime. .PARAMETER VersionBuild An integer representing the build component of the version. .PARAMETER VersionMajor An integer representing the major component of the simplified version, which is mapped from the original VersionMinor. .PARAMETER VersionMinor An integer representing the minor component of the simplified version, which is mapped from the original VersionRevision. .EXAMPLE PS C:\> Convert-64SecPowershellVersionToDateTime -VersionBuild 1 -VersionMajor 20250 -VersionMinor 1234 Returns a hashtable containing the simplified version string, the VersionBuild, and the computed DateTime. #> [CmdletBinding()] [alias("cdv64psr")] param( [Parameter(Mandatory = $true)] [int]$VersionBuild, [Parameter(Mandatory = $true)] [int]$VersionMajor, # Represents the original VersionMinor. [Parameter(Mandatory = $true)] [int]$VersionMinor # Represents the original VersionRevision. ) # Since the original VersionMajor is not included in the simplified version, we assume it to be 0. $result = Convert-64SecVersionComponentsToDateTime -VersionBuild $VersionBuild -VersionMajor 0 -VersionMinor $VersionMajor -VersionRevision $VersionMinor # Rebuild the simplified version string for clarity. $versionFull = "$VersionBuild.$VersionMajor.$VersionMinor" return @{ VersionFull = $versionFull; VersionBuild = $VersionBuild; ComputedDateTime = $result.ComputedDateTime } } |