Skip to content

Instantly share code, notes, and snippets.

@sba923
Last active July 28, 2024 11:13
Show Gist options
  • Save sba923/bc52cf74197ab3cddce825e8b502e28b to your computer and use it in GitHub Desktop.
Save sba923/bc52cf74197ab3cddce825e8b502e28b to your computer and use it in GitHub Desktop.
Improvement on Export-Csv that includes milliseconds in DateTime properties
#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