Convert existing DateTime to a different format - powershell

I have a DateTime object from a Get-ADUser which is stored into $logonDt. This is actually the returned value from an attribute in AD, namely LastLogonDate.
A gettype() confirms it is of type DateTime but it is in an American layout.
How can I take this existing DateTime object and re-format as UK, and dd/mm/yyyy

You can use Get-Date $logondt -f "dd/MM/yyyy" and change the format string as you like.
See https://technet.microsoft.com/library/hh849887.aspx for the details.
You cannot change the formatting after it is stored in the variable but you could access the single values, like $logondt.day etc.

//PowerShell's string formatting (–f) operator:
PS >$date = [DateTime] "05/09/1998 1:23 PM"
PS >"{0:dd-MM-yyyy # hh:mm:ss}" -f $date
09-05-1998 # 01:23:00
//CMDLET
PS >Get-Date -Date "05/09/1998 1:23 PM" -Format "dd-MM-yyyy # hh:mm:ss"
09-05-1998 # 01:23:00

Get-Date -format 'MM/dd/YYY
The format can be whatever you want and there are characters to represent almost every kinda of date-time unit (month, day, century, etc.)
You can find more info here.
https://technet.microsoft.com/en-us/library/hh849887.aspx

Related

Powershell format date after .AddDays() method

I can't find a way to format a date after using .AddDays()
CODE
[datetime] $searchDate = '2020-01-10'
$searchDate = '{0:yyyy-MM-dd}' -f $searchDate.AddDays(1)
returns "Saturday, January 11, 2020 12:00:00 AM" while I'm looking for 2020-01-11
tl;dr
# NOTE: [datetime] must be on the RHS if you want to assign a different type later.
$searchDate = [datetime] '2020-01-10'
$searchDate = '{0:yyyy-MM-dd}' -f $searchDate.AddDays(1)
Of course, you can combine that into a single assignment:
$searchDate = '{0:yyyy-MM-dd}' -f ([datetime] '2020-01-10').AddDays(1)
Or, via Get-Date:
$searchDate = Get-Date ([datetime] '2020-01-10').AddDays(1) -Format yyyy-MM-dd
Your own solution simply bypasses the conceptual problem with your code, which Jeroen Mostert describes well in a comment on the question.
[datetime] $searchDate = '2020-01-10'
By placing the cast ([datetime]) to the left of the variable ($searchDate) in your assignment, you type-constrain it.
This means that any values assigned later are invariably and implicitly coerced (converted) to the specified type ([datetime], in this case).
Therefore, you mustn't use the same variable to assign your string representation of a date, obtained with the -f operator, as that string representation is automatically reconverted to [datetime].
That is, after executing
$searchDate = '{0:yyyy-MM-dd}' -f $searchDate.AddDays(1), $searchData again contains a [datetime] instance, not the string of interest.
Another solution is to simply assign to a different variable, one that either isn't type-constrained or is constrained to [string].
Solved with Get-Date $searchDate -Format yyyy-MM-dd

Powershell - compare date with CSV date

I am trying to compare a date entered with a date from a CSV and display a message if the date entered is before the date in the CSV.
Am having difficulty, unsure if I need to convert the date in the CSV from string for it to be compared correctly.
Have got this far with the code:
$CSV=Import-Csv C:\Users\person\Desktop\date.csv
$InputDate = Get-Date -Format "MM/dd/yyyy" (Read-Host -Prompt 'Enter the date')
$CreatedDate = Get-Date -Format "MM/dd/yyyy HH:mm" $CSV.updated
if($InputDate -gt $CreatedDate) {
write-host "Input Newer"
}
else {
write-host "Input Older"
}
The comparison doesn't seem to work correctly.
CSV formatted as below (contains a single row, so $CSV.updated can be assumed to contain a single date string):
updated
11/07/2016 16:14
You need to parse the date in string to datetime type to do the date comparisons.
$CSV = Import-Csv C:\Users\person\Desktop\date.csv
$InputDate = [datetime]::Parse( $(Read-Host -Prompt 'Enter the date (MM/dd/yyyy)') )
$CreatedDate = [datetime]::Parse( $CSV.updated )
if($InputDate -gt $CreatedDate)
{write-host "Input Newer"}
else
{write-host "Input Older"}
Kiran Patnayakuni's answer provides an effective solution; let me make it clearer what the problem was:
You seemingly expected -Format "MM/dd/yyyy" to specify an input parsing format; in fact, it formats the output, which then becomes a [string].
For meaningful date comparison you need a [datetime] instance, however.
Your arguments to the (implied) -Date parameter ((Read-Host ...), $csv.updated) were implicitly parsed, based on the standard formats recognized by the current culture (System.Globalization.CultureInfo.CurrentCulture).
Therefore:
If your arguments are already properly recognized by the implicit parsing (as your acceptance of Kiran's answer suggests), the solution is to simply remove the -Format arguments from your code:
# Parse each input string implicitly, based on the current culture,
# and output a [datetime] instance, which will compare as expected
# with `-gt`
$InputDate = Get-Date (Read-Host -Prompt 'Enter the date')
$CreatedDate = Get-Date $CSV.updated
If, by contrast, you do need to parse by the "MM/dd/yyyy" format string explicitly in order for your arguments to be recognized, call .NET method [datetime]::ParseExact(<string>, <format>[, <culture>]) (System.DateTime.ParseExact); e.g.:
# Note: The input string must match the format *exactly*
$InputDate = [datetime]::ParseExact(
(Read-Host -Prompt 'Enter the date'), # input string
"MM/dd/yyyy", # format string
$null # default to the current culture's rules
)
Read on for background information.
Get-Date input and output formats an data types:
-Format "MM/dd/yyyy" doesn't specify an input parsing format, it specifies the output string-formatting format, which has two implications:
String input passed to input parameter -Date (which the first positional argument is bound to) is implicitly parsed as [datetime], based on the standard string formats recognized by the current culture[1]; in effect, the following is called behind the scenes:
[datetime]::Parse((Read-Host -Prompt 'Enter the date'), [cultureinfo]::CurrentCulture)
(Omitting [cultureinfo]::CurrentCulture in the call above has the same effect.)
Caveat: When you cast a string to [datetime], it is the invariant culture ([cultureinfo]::InvariantCulture, based on US-English) that is applied, which PowerShell often does for stability of code across cultures; that a cmdlet such as Get-Date is not culture-invariant is a historical accident that won't be corrected for fear of breaking old code; see this GitHub issue for background. For instance, with culture fr-FR (French) in effect, [datetime] '12/1] yields December 1st (month first), whereas Get-Date -Date '12/1' yields January 12 (day first).
The Get-Date command will return a (formatted) string rather than a [datetime] instance; that is, the [datetime] instance implicitly parsed on input is formatted based on the format string passed to -Format, based on the rules of the current culture; if $dt contains a [datetime] instance, -Format "MM/dd/yyyy" is the equivalent of (note how a direct call to System.DateTime.ToString() gives you the option to specify a different culture, which -Format doesn't):
$dt.ToString("MM/dd/yyyy", [cultureinfo]::CurrentCulture)
(As of PowerShell v7.0), the Get-Date cmdlet has no support for specifying a format string for input parsing.
As stated, passing a string to -Date causes it to be implicitly parsed, based on the standard date/time formats recognized by the current culture.
You'll have to call .NET method [datetime]::ParseExact(<string>, <format>[, <culture>]) (System.DateTime.ParseExact) directly, as demonstrated in the top section.
Once you have a [datetime] instance, you may pass it (via -Date) to Get-Date -Format to get a formatted string representation for the current culture; alternatively, you can call .ToString(<format>[, <culture>]) (System.DateTime.ToString) directly on the instance, which also gives you the option to format for a different culture.
As for Get-Date input and output data types:
Fundamentally, how the input is passed (specific arguments) determines the how the resulting [datetime] instance is interpreted, based on how the cmdlet chooses the instance's
.Kind property value (Utc, Local, or Unspecified).
The .Kind property value determines what specific global point in time, if any, a [datetime] instance represents. The .Kind value can also affect an instance's string representation, depending on what specific formatting is applied (notably, inclusion of time-zone information).
The resulting [datetime] instance is:
either: output directly (by default)
or: if a -Format argument was passed, is the basis for deriving the requested string representation ([string]).
Get-Date determines the .Kind property value as follows:
With no -Date argument, you get a Local instance (representing the current point in time)
(Unless a string is also passed to -Date), using the various offset parameters, such as -Year and -Day, produces a Local instance as well.
With a -Date argument that already is of type [datetime], that instance is used as-is, which means the existing .Kind property value is retained.
With a string -Date argument (which gets implicitly parsed), the .Kind value will be Unspecified (representing an abstract point in time, without reference to a specific time zone), including if combined with parameters such as -Year.
A numeric -Date argument (e.g, 637165787436900010) is interpreted as a System.DateTime.Ticks value, which also produces an Unspecified instance.
Note: PowerShell [Core] 7.1 will introduce an -AsUTC switch that makes the output / to-be-string-formatted instance be of kind Utc; -AsLocal and -AsUnspecified switches (and/or an -AsKind <kind> parameter) are also being discussed - see this GitHub issue.
[1] If the input already is a [datetime] instance, it is used as-is.

Unable to compare dates of different formats in PowerShell

I have to update objects in a data set by the last modified date.
The (potentially) updated objects come from a REST api call and the objects to be updated from a SharePoint list.
Unfortunately, I'm getting way different date/time formats for each identical item in PowerShell. Compare:
Rest call results: 2016-12-15T08:08:39.012+01:00
SharePoint list: Thursday, December 15, 2016 7:08:39 AM
I was thinking of using the [datetime]::ParseExact method but a) I don't know what the input format has to be and b) if that even helps me to compare the two afterwards.
I'd appreciate your help, thanks.
I'd like to address a few issues:
You can always use [System.DateTime]::Parse() for each of the formats. You don't need to use [System.DateTime]::ParseExact().
You can use Get-Date instead of C#. Use native features whenever possible. Get-Date $SomeDate will always give you the same results with [System.DateTime]::Parse($SomeDate).
The unnamed issue is one of the formats care about TimeZones but other one does not. You need to work on that.
you can store both the date in variable and change it to the specific format for example Get-Date $date -Format "yyyy-MM-dd hh:mm:ss" and then you can compare the dates for example
$date="Thursday, December 15, 2016 7:08:39 AM"
Get-Date $date -Format "yyyy-MM-dd hh:mm:ss"
$date="2016-12-15T08:08:39.012+01:00"
Get-Date $date -Format "yyyy-MM-dd hh:mm:ss"
for both output would be in same format
You can use Get-Date to convert the strings to [DateTime] objects, which can then be easily compared:
$date1 = Get-Date '2016-12-15T08:08:39.012+01:00'
$date2 = Get-Date 'Thursday, December 15, 2016 7:08:39 AM'
$date1 -gt $date2
True
$date1 -lt $date2
False
Thanks for the explanations, that was very helpful. I managed to compare and adjust for the timezone differences the following way:
$date1 = Get-Date '2016-12-15T08:08:39.012+01:00'
$date2 = (Get-Date 'Thursday, December 15, 2016 7:08:39 AM').AddHours(1)
By comparing the .DateTime property I will get the evaluation to be true:
$date1.DateTime -eq $date2.DateTime
True

Get the date modified to be formatted with AM/PM with powershell

I've currently got
Get-Item "C:\path\to\file.txt" | ForEach-Object { $_.LastWriteTime }
Which outputs like this
12/18/2018 16:54:32
But I want it to output like this
12/18/2018 4:54 PM
Is there any way I can do that?
Use the DateTime objects formatting. More info here
Get-Item "C:\path\to\file.txt" | ForEach-Object {
$_.LastWriteTime.ToString("MM/dd/yyyy hh:mm tt")
}
Much simpler to just use (Get-Date -Format 'M/d/yyyy h:mm tt')
# Convert 24hr time to 12hr with AM/PM ie, Monday 01/03/22 12:01 PM
Get-Date -Format "HH" -OutVariable time >$2
if ($time -ge 12) {
$ptime = Get-Date -Format "dddd MM/dd/yy hh:mm"
Write-Host "Right now it is $ptime PM"
} else {
$atime = Get-Date -Format "dddd MM/dd/yy hh:mm"
Write-Host "Right now it is $atime AM"
}
# clear variables
$time=$null
$atime=$null
$ptime=$null
tl;dr
Assuming that your current culture is US-English (in which case $PSCulture returns en-US), you have the following options to get the desired string format for a given [datetime] instance, such as contained in $_.LastWriteTime in your command ($PROFILE is used as a sample input file):
# Use .ToString() with the general date-time format, "g":
# -> e.g., "7/14/2022 3:44 PM"
Get-Item $PROFILE | ForEach-Object {
$_.LastWriteTime.ToString('g')
}
# Alternative, via Get-Date -Format
Get-Item $PROFILE | ForEach-Object {
Get-Date -Date $_.LastWriteTime -Format g
}
Note that the above implies that the simplest way to get the current date and time in the desired format is to use:
# Get the *current* date and time in general format.
# -> e.g. "7/14/2022 12:47 PM"
Get-Date -Format g
If you need a custom format that isn't covered by one of the standard formats, use kpogue's helpful answer.
Read on for background information, including how to ask for formats from a different culture, notably how to use the en-US culture for formatting even while a different culture is in effect.
The command in your question would not produce the display format in your sample output - instead, it would result in a more verbose, culture-specific representation as you would see for the current date with Get-Date, such as Thursday, July 7, 2022 3:44:57 PM in the US-English culture.
However, you would get such output if you were to stringify the [datetime] value via string interpolation with "$($_.LastWriteTime)", in which case PowerShell invariably applies the invariant culture, which is based on the US-English culture, but distinct from it, notably in that it guarantees culture-invariance and long-term stability - specifically, in this case it differs with respect to 12-hour vs. 24-hour clock representations, in that it uses a 24-hour clock.
kpogue's helpful answer shows you how to use custom formatting to achieve the desired output format; however, given that it seems like you're interested in the standard (general) US-English date-time format, the following solution is simpler (using $PROFILE as a sample file name):
Standard date-time format specifier g produces the desired format:
# Assumes that the current culture is en-US
Get-Item $Profile | ForEach-Object {
$_.LastWriteTime.ToString('g')
}
Sample output:
7/7/2022 3:44:57 PM
If your current culture is not en-US, you can pass the culture to use for formatting explicitly, as the second argument:
# Works irrespective of what the current culture is.
Get-Item $Profile | ForEach-Object {
$_.LastWriteTime.ToString('g', [cultureinfo] 'en-US')
}
This relies on the [datetime]::ToString() method having overloads that accept an [IFormatProvider] argument, which is an interface that the [cultureinfo] type implements, so that casting 'en-US' (the US-English culture's identifier) to [cultureinfo] results in that culture's general date-time format.

Convert Date variable into particular format in Powershell

Get-Date -format yyyy/M/d works in PS1 but it doesnt work with variable date like,
$date -format yyyy/M/d.
It prompts an error - Unexpected token in expression or statement.
How can I make the $date variable work.
Thanks,
A curious mind!
You can recreate an object with Get-Date:
Get-Date $date -format yyyy/M/d
You have to use ($date).ToString('yyyy/M/d')
Editing to say you can pipe the $date variable to Get-Member in order to reveal the available methods. Then we can search for formatting a DateTime string in PowerShell For example, this question
$date | GM
TypeName: System.DateTime
ToString Method
string ToString(), string ToString(string format),
string ToString(System.IFormatProvider provider), ...