Serializing Date and Time in a Culture-Invariant Way

When you save date and time to text, for example when exporting to CSV, or when creating text reports, DateTime objects are converted to the date and time format defined in your regional settings:

 
PS> $date = Get-Date -Date '2017-02-03 19:22:11'

PS> "$date"
02/03/2017 19:22:11

PS> $date.ToString()
03.02.2017 19:22:11

PS> Get-Date -Date $date -DisplayHint DateTime

Freitag, 3. Februar 2017 19:22:11
 

These all are culture-dependent formats, so when someone else opens your data, conversion back to a real datetime may fail. This is why it is recommended to convert datetime information to the culture-independent ISO format whenever you are saving it as text:

 
PS> Get-Date -Date $date -Format 'yyyy-MM-dd HH:mm:ss'
2017-02-03 19:22:11

PS>
 

The ISO format always correctly converts back to a DateTime object, no matter what language your computer is using:

 
PS> [DateTime]'2017-02-03 19:22:11'

Friday, February 3, 2017 19:22:11
 

In addition, it is designed in a way that sorts correctly using alphanumeric sort.

Twitter This Tip! ReTweet this Tip!

Converting Ticks to Date and Time (Part 2)

In the previous tip we explained how you convert date and time displayed as ticks to a true DateTime format. However, there are two different time formats involving ticks, and here is an overview of how you can convert numeric datetime information:

 
PS> $date = Get-Date -Date '2017-02-03 19:22:11'

PS> $ticks = $date.Ticks

PS> $ticks
636217465310000000

PS> [DateTime]$ticks

Friday, February 3, 2017 19:22:11



PS> [DateTime]::FromBinary($ticks)

Friday, February 3, 2017 19:22:11



PS> [DateTime]::FromFileTime($ticks)

Friday, February 3, 3617 20:22:11



PS> [DateTime]::FromFileTimeUtc($ticks)

Friday, February 3, 3617 19:22:11
 

As you see, converting ticks to DateTime is equivalent of running the FromBinary() static method. But what does FromFileTime() do? It seems to beam you in the far future.

This example shows what’s going on:

 
PS> $date1 = [DateTime]::FromBinary($ticks)

PS> $date2 = [DateTime]::FromFileTime($ticks)

PS> $date2 - $date1


Days              : 584388
Hours             : 1
Minutes           : 0
Seconds           : 0
Milliseconds      : 0
Ticks             : 504911268000000000
TotalDays         : 584388,041666667
TotalHours        : 14025313
TotalMinutes      : 841518780
TotalSeconds      : 50491126800
TotalMilliseconds : 50491126800000




PS> ($date2 - $date1).Days / 365.25
1599,96714579055
 

FromFileTime() simply adds 1601 years (the calculated difference is a little off due to leap years). Some parts of Windows (like Active Directory) start their calendar at Jan 1, 1601. For these, use FromFileTime() to get the accurate date and time.

Twitter This Tip! ReTweet this Tip!

Converting Ticks to Date and Time (Part 1)

Occasionally, you may run into strange date and time representations: they might be represented as a 64-bit integer like this: 636264671350358729.

If you’d like to convert these “ticks” (the smallest time and date increment on Windows), simply convert the number to a DateTime type:

 
PS> [DateTime]636264671350358729

Thursday, March 30, 2017 10:38:55
 

Likewise, to turn a date into ticks, try this:

 
PS> $date = Get-Date -Date '2017-02-03 19:22:11'

PS> $date.Ticks
636217465310000000
 

You could use ticks to serialize date and time in a culture-neutral format, for example.

Twitter This Tip! ReTweet this Tip!

Directly Importing Certificates (Part 2)

In the previous tip we showed how to import digital certificates with .NET methods on any version of PowerShell. Newer versions of PowerShell come with the “PKI” module which includes the cmdlet Import-Certificate. With it, importing certificates becomes even easier.

#requires -Version 2.0 -Modules PKI 
# importing to personal store
$Path = 'C:PathToCertFile.cer'
Import-Certificate -FilePath $Path -CertStoreLocation Cert:CurrentUserMy

Note how Import-Certificate lets you specify the target store location with -CertStoreLocation. It returns the imported certificate.

Twitter This Tip! ReTweet this Tip!

Directly Importing Certificates (Part 1)

Installing certificate files on a computer can be done using .NET methods with any version of PowerShell. This would import a certificate file to your personal store:

# importing to personal store
$Path = 'C:PathToCertFile.cer'
$Store = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Store -ArgumentList My, CurrentUser
$Store.Open('ReadWrite')
$Store.Add($Path)
$Store.Close()

You can verify it by opening the certificate manager:

 
PS C:> certmgr.msc
 

If you’d like to import the certificate to a different store location, simply adjust the arguments you submit when creating the store object.

Twitter This Tip! ReTweet this Tip!

Beware of Aliases

Can you spot what is wrong here?

 
PS C:> function r { "This never runs" }

PS C:> r
function r { "This never runs" }

PS C:>
 

When you run function “r”, it simply returns the function source code.

The reason is that the function name “r” conflicts with a built-in alias:

 
PS C:> Get-Alias r

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------                                        
Alias           r -> Invoke-History                                                                                     


PS C:>
 

So always make sure you know your built-in alias names – they always have precedence over functions or any other command. Better yet, adhere to best practice, and always assign Verb-Noun names to your functions.

Twitter This Tip! ReTweet this Tip!