Reputation: 37
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
Upvotes: 1
Views: 751
Reputation: 437548
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]
.
[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)
[cultureinfo]::CurrentCulture
in the call above has the same effect.)[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:
-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)
-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.
Upvotes: 1
Reputation: 46
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"}
Upvotes: 2