Last active
July 28, 2024 11:13
-
-
Save sba923/bc52cf74197ab3cddce825e8b502e28b to your computer and use it in GitHub Desktop.
Improvement on Export-Csv that includes milliseconds in DateTime properties
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#requires -version 7.3 | |
# this is one of Stéphane BARIZIEN's public domain scripts | |
# the most recent version can be found at: | |
# https://gist.github.com/sba923/bc52cf74197ab3cddce825e8b502e28b#file-export-csvwithmilliseconds-ps1 | |
<# | |
.SYNOPSIS | |
Proxy for Export-Csv that adds milliseconds to DateTime properties | |
.DESCRIPTION | |
When objects contain properties of type DateTime, Export-Csv doesn't include milliseconds in the resulting CSV file: | |
[PSCustomObject]@{ | |
Date = [datetime]"2024-12-31 23:59:59.999" | |
} | Export-Csv foo.csv | |
Get-Content foo.csv | |
"Date" | |
"2024-12-31 23:59:59" | |
This proxy script adds milliseconds to the resulting CSV: | |
[PSCustomObject]@{ | |
Date = [datetime]"2024-12-31 23:59:59.999" | |
> } | Export-CsvWithMilliseconds.ps1 foo.csv | |
> Get-Content foo.csv | |
"Date" | |
"2024-12-31 23:59:59.999" | |
Until https://github.com/PowerShell/PowerShell/issues/19536 is addressed, this is an acceptable workaround. | |
#> | |
# original proxy code produced by: | |
# $MetaData = New-Object System.Management.Automation.CommandMetaData (Get-Command Export-Csv) | |
# [System.Management.Automation.ProxyCommand]::Create($MetaData) | |
[CmdletBinding(DefaultParameterSetName = 'Delimiter', SupportsShouldProcess = $true, ConfirmImpact = 'Medium', HelpUri = 'https://go.microsoft.com/fwlink/?LinkID=2096608')] | |
param( | |
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] | |
[psobject] | |
${InputObject}, | |
[Parameter(Position = 0)] | |
[ValidateNotNullOrEmpty()] | |
[string] | |
${Path}, | |
[Alias('PSPath', 'LP')] | |
[ValidateNotNullOrEmpty()] | |
[string] | |
${LiteralPath}, | |
[switch] | |
${Force}, | |
[Alias('NoOverwrite')] | |
[switch] | |
${NoClobber}, | |
[ValidateNotNullOrEmpty()] | |
# remove typing, see https://github.com/PowerShell/PowerShell/issues/19647 | |
${Encoding}, | |
[switch] | |
${Append}, | |
[Parameter(ParameterSetName = 'Delimiter', Position = 1)] | |
[ValidateNotNull()] | |
[char] | |
${Delimiter}, | |
[Parameter(ParameterSetName = 'UseCulture')] | |
[switch] | |
${UseCulture}, | |
[Alias('ITI')] | |
[switch] | |
${IncludeTypeInformation}, | |
[Alias('NTI')] | |
[switch] | |
${NoTypeInformation}, | |
[Alias('QF')] | |
[string[]] | |
${QuoteFields}, | |
[Alias('UQ')] | |
[Microsoft.PowerShell.Commands.BaseCsvWritingCommand+QuoteKind] | |
${UseQuotes}) | |
begin | |
{ | |
# derived from https://github.com/PowerShell/PowerShell/issues/19536#issuecomment-1515140128 | |
# Save the original culture. | |
$original = [cultureinfo]::CurrentCulture | |
# Temporarily replace it with a read/write copy. | |
[cultureinfo]::CurrentCulture = [cultureinfo] $original.Name | |
# Modify the LongTimePattern format to include milliseconds. | |
[cultureinfo]::CurrentCulture.DateTimeFormat.LongTimePattern += ([cultureinfo]::CurrentCulture.NumberFormat.CurrencyDecimalSeparator + 'fff') | |
# Now .ToString(), which uses ShortDatePattern and LongTimePattern, | |
# separated by a space, uses the modified formats. | |
try | |
{ | |
# removed according to https://github.com/PowerShell/PowerShell/issues/10863 | |
# $outBuffer = $null | |
# if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) | |
# { | |
# $PSBoundParameters['OutBuffer'] = 1 | |
# } | |
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\Export-Csv', [System.Management.Automation.CommandTypes]::Cmdlet) | |
$scriptCmd = { & $wrappedCmd @PSBoundParameters } | |
$steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) | |
$steppablePipeline.Begin($PSCmdlet) | |
} | |
catch | |
{ | |
# changed according to https://github.com/PowerShell/PowerShell/issues/10863#issuecomment-545533276 | |
# throw | |
$PSCmdlet.ThrowTerminatingError($_) | |
} | |
} | |
process | |
{ | |
try | |
{ | |
$steppablePipeline.Process($_) | |
} | |
catch | |
{ | |
# changed according to https://github.com/PowerShell/PowerShell/issues/10863#issuecomment-545533276 | |
# throw | |
$PSCmdlet.ThrowTerminatingError($_) | |
} | |
} | |
end | |
{ | |
try | |
{ | |
$steppablePipeline.End() | |
} | |
catch | |
{ | |
# changed according to https://github.com/PowerShell/PowerShell/issues/10863#issuecomment-545533276 | |
# throw | |
$PSCmdlet.ThrowTerminatingError($_) | |
} | |
} | |
clean | |
{ | |
# Restore culture | |
[cultureinfo]::CurrentCulture = $original | |
if ($null -ne $steppablePipeline) | |
{ | |
$steppablePipeline.Clean() | |
} | |
} | |
<# | |
.ForwardHelpTargetName Microsoft.PowerShell.Utility\Export-Csv | |
.ForwardHelpCategory Cmdlet | |
#> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment