Convert string to PowerShell date and time format - powershell

I could use some help figuring out the formatting syntax for converting a string to DateTime in PowerShell. I've tried many combinations and continue to get
Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime."
The code I'm trying to use is as follows:
$timeinfo = '1/‎3/‎2020 ‏‎9:56 AM'
$template = 'M/d/yyyy h:mm tt'
$culture = [Globalization.CultureInfo]::InvariantCulture
[DateTime]::ParseExact($timeinfo, $template, $culture)
I'm using syntax that I found here: https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/parsing-custom-datetime-formats. Would someone be willing to show me what I'm doing wrong? I'm stuck! Thanks so much!

try this and let the parser do the work:
$timeinfo = '04/02/2020 02:00 PM'
[datetime]$timeinfo

Related

Extracting date from a file name in PowerShell

I have written a PowerShell script to extract the date from filenames and delete based on that.
Sample file name: TBTT_UAT_01012021_000019.csv
Code to extract date :
$fileDateText = ($filename -split '_')[4]
$fileDate = [System.DateTime]::ParseExact($fileDateText, "dd/MM/yyyy", [System.Globalization.CultureInfo]::InvariantCulture)
But I am getting the following error when I run the script, as it recognizes the date before CSV:
String '000019.csv' was not recognized as a valid DateTime.: FormatException
Can someone advise, please?
Thanks,
I think you may be looking at the wrong array element returning from your split. Also the string you are giving in the overloads for .ParseExact() may be off. This seemed to work in my tests:
$fileDate = ("TBTT_UAT_01012021_000019.csv" -split '_')[2]
[DateTime]::ParseExact($fileDate, "ddMMyyyy", [System.Globalization.CultureInfo]::InvariantCulture)
Returned: Friday, January 1, 2021 12:00:00 AM
If you want to get more granular about the time we'll have to cut up the string file name differently.
Issue has been fixed by changing from:
[System.DateTime]::ParseExact($fileDateText, "dd/MM/yyyy", [System.Globalization.CultureInfo]::InvariantCulture)
to
$fileDate = [DateTime]::ParseExact("$fileDateText", 'ddMMyyyy',[CultureInfo]::InvariantCulture)
if ($filename -match '(?<Timestamp>\d{8})') {
[DateTime]::ParseExact($Matches.Timestamp, 'ddMMyyyy', [CultureInfo]::InvariantCulture)
}
I gravitate toward regexes with named extraction groups rather than doing string manipulation. The syntax is a bit more fiddly, but the resulting script ends up being more resilient.

Powershell Parse Date ISO8601

I have a date string in what I think is ISO8601 format (although I'm not 100% sure), e.g.
20200210T165905+0000
I want to parse this using powershell and have tried the following
$Date = "20200210T165905+0000"
$DatePattern = "yyyyMMdd\THHmmss\+zzzz"
$DateTime = [DateTime]::ParseExact($Date, $DatePattern, $null)
But I get the following error
Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime."
What am I doing wrong?
The Dateformat you have requires a different pattern where the Time zone information is handled by K.
+0000 means that the date is in UTC time (offset 0). If you remove that, the date string is parsed as if it is a LOCAL DateTime, giving you false information (unless you live in a part of the world where UTC is the same as the local time)
$Date = "20200210T165905+0000"
$DatePattern = "yyyyMMddTHHmmssK"
$DateTime = [DateTime]::ParseExact($Date, $DatePattern, $null)
$DateTime
Returns (in my NL Locale => UTC + 1)
10-2-2020 17:59:05
Removing the \+ escaped character from the pattern seems to fix it for me, i.e.,
$DatePattern = "yyyyMMdd\THHmmsszzzz"

Why in PowerShell does embedding a DateTime object in a string lose the DateTime locale?

The locale of my machine is UK (en-gb). When I do the following (to check expiration date of an SSL cert) the DateTime object stores the value in UK format
$expiration = Get-Date $req.ServicePoint.Certificate.GetExpirationDateString()
See here what happens firstly if you just have the value printed to the command prompt, and secondly what happens if you try to embed that DateTime object value within a string.
PS>$expiration
19 December 2016 23:59:59
PS>write-host "this is the expiration: $expiration"
this is the expiration: 12/19/2016 23:59:59
So we see that it has switched to non UK format (should be 19/12/2016). Why is this, and is there a simple workaround?
It's a string expansion problem and a bit of a pain I'm afraid. You know this one to display incorrectly:
"$(Get-Date 01/02/2016)"
These however, display as you'd expect:
(Get-Date 01/02/2016).ToString()
"$((Get-Date 01/02/2016).ToString())"
Both of these approaches work to work around the problem:
$expiration = Get-Date 01/02/2016
write-host "this is the expiration: $($expiration.ToString())"
write-host ("this is the expiration: {0}" -f $expiration)
You see similar ignorance of the time zone when casting to DateTime:
[DateTime]$var = "01/02/2016"
$var
Chris
You could use a simple string format option
MSDN article:
https://msdn.microsoft.com/en-us/library/az4se3k1(v=vs.110).aspx
$expirationString = "{0:F}" -f $expiration
and then
Write-Host "this is the expiration: $expirationString"
If this also provides the wrong output, you could make a custom format string, like this:
"{0:dd MMMM yyyy hh:mm:ss}"

Convert a string to datetime in PowerShell

I am using PowerShell to try and convert a string to a datetime. It should be easy, right?
I am getting the string from a CSV import, and it comes in the format of Jul-16. I have tried multiple ways of getting it into the format I want which is yyyy-MM-dd and I am currently at the following.
$invoice = $object.'Invoice Month'
$invoice = "01-" + $invoice
$invoice = [datetime]::parseexact($invoice, 'yyyy-MM-dd', $null)
But I get the error:
String was not recognized as a valid DateTime.
Am I missing something?
ParseExact is told the format of the date it is expected to parse, not the format you wish to get out.
$invoice = '01-Jul-16'
[datetime]::parseexact($invoice, 'dd-MMM-yy', $null)
If you then wish to output a date string:
[datetime]::parseexact($invoice, 'dd-MMM-yy', $null).ToString('yyyy-MM-dd')
You can simply cast strings to DateTime:
[DateTime]"2020-7-16"
or
[DateTime]"Jul-16"
or
$myDate = [DateTime]"Jul-16";
And you can format the resulting DateTime variable by doing something like this:
'{0:yyyy-MM-dd}' -f [DateTime]'Jul-16'
or
([DateTime]"Jul-16").ToString('yyyy-MM-dd')
or
$myDate = [DateTime]"Jul-16";
'{0:yyyy-MM-dd}' -f $myDate
You need to specify the format it already has, in order to parse it:
$InvoiceDate = [datetime]::ParseExact($invoice, "dd-MMM-yy", $null)
Now you can output it in the format you need:
$InvoiceDate.ToString('yyyy-MM-dd')
or
'{0:yyyy-MM-dd}' -f $InvoiceDate
Chris Dents' answer has already covered the OPs' question but seeing as this was the top search on google for PowerShell format string as date I thought I'd give a different string example.
If like me, you get the time string like this 20190720170000.000000+000
An important thing to note is you need to use ToUniversalTime() when using [System.Management.ManagementDateTimeConverter] otherwise you get offset times against your input.
PS Code
cls
Write-Host "This example is for the 24hr clock with HH"
Write-Host "ToUniversalTime() must be used when using [System.Management.ManagementDateTimeConverter]"
$my_date_24hr_time = "20190720170000.000000+000"
$date_format = "yyyy-MM-dd HH:mm"
[System.Management.ManagementDateTimeConverter]::ToDateTime($my_date_24hr_time).ToUniversalTime();
[System.Management.ManagementDateTimeConverter]::ToDateTime($my_date_24hr_time).ToUniversalTime().ToSTring($date_format)
[datetime]::ParseExact($my_date_24hr_time,"yyyyMMddHHmmss.000000+000",$null).ToSTring($date_format)
Write-Host
Write-Host "-----------------------------"
Write-Host
Write-Host "This example is for the am pm clock with hh"
Write-Host "Again, ToUniversalTime() must be used when using [System.Management.ManagementDateTimeConverter]"
Write-Host
$my_date_ampm_time = "20190720110000.000000+000"
[System.Management.ManagementDateTimeConverter]::ToDateTime($my_date_ampm_time).ToUniversalTime();
[System.Management.ManagementDateTimeConverter]::ToDateTime($my_date_ampm_time).ToUniversalTime().ToSTring($date_format)
[datetime]::ParseExact($my_date_ampm_time,"yyyyMMddhhmmss.000000+000",$null).ToSTring($date_format)
Output
This example is for the 24hr clock with HH
ToUniversalTime() must be used when using [System.Management.ManagementDateTimeConverter]
20 July 2019 17:00:00
2019-07-20 17:00
2019-07-20 17:00
-----------------------------
This example is for the am pm clock with hh
Again, ToUniversalTime() must be used when using [System.Management.ManagementDateTimeConverter]
20 July 2019 11:00:00
2019-07-20 11:00
2019-07-20 11:00
MS doc on [Management.ManagementDateTimeConverter]:
https://learn.microsoft.com/en-us/dotnet/api/system.management.managementdatetimeconverter?view=dotnet-plat-ext-3.1
$invoice = "Jul-16"
[datetime]$newInvoice = "01-" + $invoice
$newInvoice.ToString("yyyy-MM-dd")
There you go, use a type accelerator, but also into a new var, if you want to use it elsewhere, use it like so: $newInvoice.ToString("yyyy-MM-dd")as $newInvoice will always be in the datetime format, unless you cast it as a string afterwards, but will lose the ability to perform datetime functions - adding days etc...
Hope below helps!
PS C:\Users\aameer>$invoice = $object.'Invoice Month'
$invoice = "01-" + $invoice
[datetime]$Format_date =$invoice
Now type is converted. You can use method or can access any property.
Example :$Format_date.AddDays(5)
It's very easy; in my case it works with;
Input:
$Date = '29-07-2022'
DateFormat Convertion:
[datetime]::parseexact($date, 'dd-MM-yyyy', $null).ToString('dd-MMMM-yyyy')
Output:
I had a different but related need to convert a number (seconds) into days/hours/seconds etc.
$seconds = 41414141
New-Timespan -seconds $seconds

Change date format from "yyyymmdd" to "mm/dd/yyyy"

I've tried a lot of different ways and I can't seem to get it right.
Here is the code of what I have tried so far...
[String]$dateValue = '20161212'
[String]$dateStamp = $dateValue -f (Get-Date)
[String]$dateStamp2 = ([datetime]::parseexact($dateValue, "yyyyMMdd", [System.Globalization.CultureInfo]::InvariantCulture)).Date
[String]$dateStamp3 = ([datetime]::FromFileTime($dateValue)).ToString('g')
Write-Host '$dateStamp = ' $dateStamp
Write-Host '$dateStamp2 = ' $dateStamp2
Write-Host '$dateStamp3 = ' $dateStamp3
Current Code Output
$dateStamp = 20161212
$dateStamp2 = 12/12/2016 00:00:00
$dateStamp3 = 12/31/1600 5:00 PM
Desired Code Output
$dateStamp = 12/12/2016
Any Ideas?
Once you have a datetime object it's easy to convert it to whatever string format you need. You are so close with your second attempt. Adding ToString allows you to specify a string format.
([datetime]::parseexact($dateValue, "yyyyMMdd", [System.Globalization.CultureInfo]::InvariantCulture)).ToString("dd/MM/yyyy")
Given that you have a culture-invariant string as your input and that you want a fixed output format, you may as well perform string parsing, without the need to convert to an intermediate [datetime] instance:
> '20161213' -replace '\d{2}(\d{2})(\d{2})(\d{2})', '$2/$3/$1'
12/13/16
Note that I've changed the day to be different from the month to better highlight the reformatting that takes place.
Generally, though, the [datetime]-based method demonstrated in Nick's helpful answer gives you the most flexibility.