Powershell Parse Date ISO8601 - powershell

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"

Related

PowerShell get latest string date

I have a list with dates inside
$date = #('05-28-2020','09-30-2021')
I want to find the most recent date
I tried to convert string before comparat it :
[datetime]::ParseExact($date[0],'MM_dd_yyyy', $null)
But not working
Any ideas ?
You can directly cast your date-time strings to [datetime] - no need for a ParseExact() call - given that your input format is recognized by the invariant culture that PowerShell always uses in casts.
System.Linq.Enumerable.Max<T>() allows you to find the maximum in a [datetime]-typed enumerable.
Therefore:
$date = #('05-28-2020','09-30-2021') # Note: The #(...) enclosure isn't strictly needed.
[Linq.Enumerable]::Max([datetime[]] $date)
On a US-English system, the above yields Thursday, September 30, 2021 12:00:00 AM, i.e. the default output formatting of the most recent date in the input, [datetime] '09-30-2021'.
As for what you tried:
As has been mentioned, the only immediate problem with your ParseExact() call was that you used _ instead of -.
Also note that passing $null as the third argument implies that the culture currently in effect is used during parsing (as reflected in [cultureinfo]::CurrentCulture; this won't matter with numeric formatting sequences such as MM, but it would with symbolic ones such as MMM - and potentially even with unquoted placeholders : and /.
switch your _ to - and it will work:
$date = #('05-28-2020','09-30-2021')
$max = '01-01-1999'
$date | ForEach-Object {
if($_ -ge $max){
$max = $_
}
}
This should do the work.

Convert string to PowerShell date and time format

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

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.