PowerShell - formatting date to yyMMdd format - date

I run a PowerShell script that passes a parameter, such as "20160428".
I need to format this into yyMMdd (i.e., getting "160428" as the result). I could just strip out the "20", but I would like to get this right. For such I did so many attempts, such as:
#$COBDATE= '{0:yyMMdd}' -f $COBDATE
#$COBDATE = ([datetime]::ParseExact($COBDATE, "yyMMdd", [System.Globalization.CultureInfo]::InvariantCulture )).DayOfWeek
And the last one:
$COBDATE = ("{0:yyMMdd}" -f [datetime]::parse($COBDATE))
The below works, but once I replace "Get-Date" by my date "20160428" it just prints out the yyMMdd string.
$b = (Get-Date).AddDays(-1).ToString("yyMMdd")
So if I try this:
$input = "20160428"
$format = "yyMMdd"
$input_toDate_up = [DateTime]::ParseExact($input, $format, $null).ToString($format)
$input_toDate_up
It just says that the string is not a valid Date Time, which seems to be the root cause.
How can I fix this?

$Input = "20160428"
Get-Date -Year $Input.Substring(0,4) -Month $Input.Substring(4,2) -Day $Input.Substring(6,2) -Format "yyMMdd"

I think for one $input is a reserved variable so you shouldn't use it as nothing will really work in there as you expect. See here about_Automatic_Variables
I have used this drawn out substring process before with varied abstract date formats.
$dateinput = "20160428"
$dateformat = "yyMMdd"
Get-Date($dateinput.Substring(4,2) + "/" + $dateinput.Substring(2,2) + "/" + $dateinput.substring(0,4)) -Format $dateformat
I'm sure there is a shorter regex method, but that is not under my hat yet.

Related

Powershell - Find the latest Friday

How can the following code be modified to identify the latest Friday within the past week (instead of the next one), but with formatting?
$Date = #(#(0..7) | % {$(Get-Date).AddDays($_)} | ? {$_.DayOfWeek -ieq "Friday"})[0]
Source: https://stackoverflow.com/a/23939203/5651418
The post you linked to offers a more elegant solution, which you can adapt as follows:
# Get the most recent Friday relative to the given date,
# which may be that date itself.
$mostRecentFriday =
($date = Get-Date).AddDays((-7 - $date.DayOfWeek + [DayOfWeek]::Friday) % 7)
If you want to create a formatted string representation of the resulting [datetime] instance (all examples below yield something like '07 01 2022':
To use Unix-style format specifiers, use Get-Date's -UFormat parameter:
Get-Date $mostRecentFriday -UFormat '%d %m %Y'
To use .NET's format specifiers, use Get-Data's -Format parameter:
Get-Date $mostRecentFriday -Format 'dd MM yyyy'
Alternatively, pass the format string to the [datetime]
instance's .ToString() method:
$mostRecentFriday.ToString('dd MM yyyy')
If I understood correctly, your expected output would be 1 7 2022, I would personally use a do loop that stops as soon as the DayOfWeek Property of the DateTime instance is Friday:
$date = [datetime]::Now
do {
$date = $date.AddDays(-1)
} until($date.DayOfWeek -eq [DayOfWeek]::Friday)
$date.ToString("d M yyyy")
I noticed that some Get-Date -UFormat specifiers didn't seem to work when attempting to incorporate them into an output string.
Should anyone need to incorporate some rarely needed ones (like 'Week of Year' (%G), 'Day of Year (%j), etc) you could preset needed variables and add them to the output string:
$DayOfYear = (Get-Date -UFormat %j)
$WeekOfYear = (Get-Date -UFormat %V)
$Date = #(#(0..7) | % {$(Get-Date).AddDays(-$_)} | ? {$_.DayOfWeek -ieq "Wednesday"})[0].ToString("MM-dd-yyyy|Week $WeekOfYear|'Day' $DayOfYear")
I imagine someone could incorporate all the code into one Powershell command.
Additional Get-Date -UFormat specifiers: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-date?view=powershell-7.2#notes

How to use the .AddMonths method of Get-Date in Powershell

I am writing a simple script that gets the date, gets the date 6 months from now, and copies both of those dates to the clipboard. When run, the script is supposed to copy:
Terminated MM/dd/yy - Delete from AD on MM/dd/yyyy
But it only copies
Terminated MM/dd/yyyy - Delete from AD on
$currentDate = Get-Date -Format "MM/dd/yyyy"
$futureDate = Get-Date.AddMonths(6) -Format "MM/dd/yyyy"
$copyThisText = "Terminated " + $currentDate + " - Delete from AD on " + $futureDate
$copyThisText | clip
The reason it failed is because once you format a date using -Format "MM/dd/yyyy" it converts that variable to a type of string rather than datetime which then means that the normal datetime methods are no longer available.
For demonstration purposes I have tried to change as little as possible. What I have done below is set the $currentDate and $futureDate without implicitly converting them to strings. I then format them the way you want when you are concatenating the strings in $copyThisText.
This will do what you want.
$currentDate = Get-Date
$futureDate = (Get-Date).AddMonths(6)
$copyThisText = "Terminated " + $currentDate.tostring("MM/dd/yyyy") + " - Delete from AD on " + $futureDate.tostring("MM/dd/yyyy")
$copyThisText | clip
Furthermore there are multiple ways to format the strings that could aid in readability of the code. Thanks #Santiago Squarzon for the suggestion -
"Terminated {0:MM/dd/yyyy} - Delete from AD on {1:MM/dd/yyyy}" -f $currentDate, $futureDate

Culture based formatting of time variable

In this example it seems to me that the first two outputs should match, giving me formatting based on my defined culture. The last should be different because French formatting is different. Instead, the last two are the same, and are both getting some kind of default formatting. So, how do I do Culture based formatting when the time is a variable rather than formatting directly with Get-Date? It seems like it should be the same, but it's not.
get-date -format ((Get-Culture).DateTimeFormat.FullDateTimePattern)
$time = Get-Date
$pattern = 'FullDateTimePattern'
$formattedTime = $time -f (Get-Culture).DateTimeFormat.$pattern
Write-Host "$formattedTime"
$culture = New-Object system.globalization.cultureinfo('fr-FR')
$formattedTime = $time -f ($culture).DateTimeFormat.$pattern
Write-Host "$formattedTime"
The output I get is
July 9, 2019 11:22:01 AM
07/09/2019 11:22:01
07/09/2019 11:22:01
What I want to get is
July 9, 2019 11:26:46 AM
July 9, 2019 11:26:46 AM
Tuesday 9 July 2019 11:26:46
EDIT: So, based on I.T Delinquent's response, I tried this
$pattern = 'longDateTimePattern'
$date = Get-Date
$format = (Get-Culture).DateTimeFormat.$pattern
$string = ($date).ToString($format)
Write-Host $string
$culture = New-Object system.globalization.cultureinfo('de-DE')
$format = $culture.DateTimeFormat.$pattern
$string = ($date).ToString($format)
Write-Host $string
And it gave me identical results. Because it's not 'longDateTimePattern', its 'longDatePattern'. Given that the pattern could become a user supplied string, I better validate them.
Your attempt at using the -f operator is flawed (see bottom section).
To get the desired output, use the [datetime] type's appropriate .ToString() overload:
$time.ToString($culture.DateTimeFormat.$pattern, $culture)
Passing $culture as the 2nd argument ensures that the formatting is applied in the context of that culture.
If your intent is truly to use a format from another culture and apply it in the context of the current culture, simply omit the 2nd argument (as an alternative to the Get-Date -Format approach in your question):
$time.ToString($culture.DateTimeFormat.$pattern)
If there's no need to involve a different culture, the task becomes much simpler, by way of the standard date-time format strings, where single-character strings such as "D" refer to standard formats, such as LongDatePattern:
$time.ToString("D")
You can also pass these strings to Get-Date -Format
Get-Date -Format D
As for what you tried:
In order for the -f operator to work correctly, your LHS must be a string template with placeholders ({0} for the first one, {1} for the second, ...), to be replaced with the RHS operands.
Using a simple example:
Format the RHS, an [int], as a number with 2 decimal places.
PS> '{0:N2}' -f 1
1.00
Therefore, $time -f (Get-Culture).DateTimeFormat.$pattern doesn't perform (explicit) formatting at all, because the LHS - $time - contains no placeholders.
That is, the RHS is ignored, and the LHS is returned as a string: It is effectively the same as calling $time.ToString() in the context of the invariant culture (because the result of applying the -f operator is always a string and PowerShell uses the invariant culture in many string-related contexts).
While you can incorporate a specific date-time format string into a template-string placeholder - by following the placeholder index with : and a format string, as shown above ({0:N2}) - you cannot also provide a culture context for it.
You'd have to (temporarily) switch to the desired culture first:
# Save the currently effective culture and switch to the French culture
$prev = [cultureinfo]::CurrentCulture
[cultureinfo]::CurrentCulture = 'fr-FR'
# Format with the desired format string.
"{0:$($culture.DateTimeFormat.$pattern)}" -f $time
[cultureinfo]::CurrentCulture = $prev
I think this has something to do with how the Get-Date is passed using the variable, it seems to lose the format capability. In fact, if you try using Write-Host ($date -Format $format) gives an error:
Unexpected token '$format' in expression or statement
Here are my setup variables:
$pattern = 'FullDateTimePattern'
$format = (Get-Culture).DateTimeFormat.$pattern
$date = Get-Date
As stated above, using Write-Host ($date -f $format) and incorrectly outputs 07/09/2019 12:24:38. However, using any of the below options does work and correctly outputs 09 July 2019 12:24:38:
Write-Host (Get-Date -Format $format)
Write-Host (Get-Date).ToString($format)
Write-Host ($date).ToString($format)
Hope this helps :)

Convert date and time string into datetime

I've got a variable of type string which looks something like this
$string = "07/07/2019 18:00". I want to convert this variable into an variable of type datetime. The format should be MM/DD/YYYY HH:MM
$date = '07/07/2019'
$time = '18:00'
$datetime = $date + ' ' + $time
$datetime = [datetime]::ParseExact('$datetime', 'MM/DD/YYYY_HH:MM', $null)
Using the code above, I get an error message telling me:
Exception calling "ParseExact" with "3" argument(s): "String was not recognized as a valid DateTime."
Is there another way to go?
Your format string used wrong specifiers, namely DD and YYYY; see custom date and time formats.
Change your code to
$date = '07/07/2019'
$time = '18:00'
$datetime = $date + ' ' + $time
$datetime = [datetime]::ParseExact($datetime, 'MM/dd/yyyy HH:mm', $null)
$datetime
Also be aware to pass $datetime as reference and not as single quoted string.
You find above code under this link.
[datetime]'07/07/2019 18:00'
Sunday, July 7, 2019 6:00:00 PM
Or
[datetime]'7/7'
[datetime]'18:00'
[datetime]'6pm'
Then you can add or subtract them, but then the answer is a [timespan].

Use Get-Date "time" in an "if" statement PowerShell

$WshShell = New-Object -ComObject wscript.shell
$Time = (Get-Date).hour
$Time2 = Get-Date -DisplayHint Time
$Message ="Test for $Env:username at: " + $Time2
$fail = "ERROR:It is $Time2, which is past 12PM"
$PopUp = $WshShell.popup("$Message",0,"Task Scheduler Pop-up",1)
if ($Time2 > 12)
{
$PopUp = $wshShell.popup("$Message",0,"Task Scheduler Pop-up",1)
}
else {
$PopUp = $wshShell.popup("$fail",2,"Task Scheduler Pop-up",1)
}
Hi guys, I'm practicing a little bit of my PowerShell and have run across something I'm not quite sure how to Google for, or what method I need to use to get this to work correctly.
What I'm attempting to accomplish is have my box display only, the hour and minute like "12:31".
As you can see in the script I'm calling the
Hour, but I can't quite figure out how to have it display the time by itself the right way. I'm using the "Time" operator, but when you compare that in the "IF" statement, it doesn't recognize it as something it can compare itself to since it's not a real integer. I understand why, but I would like to be able to compare the .Hour to $Time2
I'm new to this and appreciate any help you can provide!
Thank you!
Don't think in terms of output strings before you actually need to.
> won't work for comparisons, you need to use -lt (less than) and -gt (greater than)
If you want to compare the time of two DateTime objects (regardless of the date), you can compare the TimeOfDay property:
$DateTimeNow = Get-Date
$DateTimeEarly = Get-Date -Hour 1 -Minute 5
if($DateTimeNow.TimeOfDay -lt $DateTimeEarly.TimeOfDay){
"It is very early right now!"
} else {
"It is at least past 01:05"
}
If you want to show the time in output, you have multiple options for formatting a DateTime string:
You can use the ToString() method with a formatting string:
PS C:\> (Get-Date).ToString('HH:mm')
20:41
The format operator -f:
PS C:\> '{0:HH:mm}' -f (Get-Date)
20:41
Or have Get-Date return a formatted string itself:
PS C:\> Get-Date -Format 'HH:mm'
20:41
If you want 12-hour style time, use hh:mm
If you need to display the time you could use one of several methods. Those would all convert the result to string. I think you need to save $time2 as just a [datetime] object. That way you can format it for display and use .Hour for comparison logic.
$Time2 = Get-Date
$Message ="Test for $Env:username at: " + $Time2.ToString("HH:mm")
$PopUp = $WshShell.popup("$Message",0,"Task Scheduler Pop-up",1)
if ($Time2.Hour -gt 12){
#Do Stuff
}
This logic would only work for 24hr time though. 1(pm) is less than 12 but later in the day. Which is what HH:mm represents.