Powershell - Find the latest Friday - powershell

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

Related

How convert a future date to the yyyy-mm-ddT00:00:00Z format with PowerShell

I am trying to get this to work in PowerShell with no success.
I would need to convert a future date and time (let's say July 1st 2022 midnight 00:00) to the format yyyy-mm-ddT00:00:00Z
The below command:
Get-Date -Format u
outputs to 2022-06-21 13:34:20Z (at the time of writing), which is pretty close to what i need for the present time.
Is there a way to get what i need without the use of regex or replace() method and also in the future?
The format is pretty flexible. Just specify it manually:
Get-Date -Format yyyy-MM-ddTHH:mm:ssZ
Output: 2022-06-21T03:51:17Z
For a future date, it's probably easier to create that in advance, then use it with the formatting:
$futuredate = (Get-Date).AddDays(30)
Get-Date $futuredate -Format "yyyy-MM-ddTHH:mm:ssZ"
Output: 2022-07-21T03:56:46Z
Or, if in your case you really do want exactly midnight for the day in question:
$futuredate = (Get-Date).AddDays(10).Date
Get-Date $futuredate -Format "yyyy-MM-ddTHH:mm:ssZ"
Output: 2022-07-01T00:00:00Z
Based on the above answer, i tried to come up with a version of getting the first day of the next month and the last day. Let me know your thoughts:
Beggining of month:
Get-Date -Format "yyyy-MM-ddT00:00:00Z" -Date ([datetime](Get-Date -Day 1).AddMonths(1))
Output: 2022-07-01T00:00:00Z
End of month:
Get-Date -Format "yyyy-MM-ddT23:59:59Z"-Date (([datetime](Get-Date -Day 1).AddMonths(2)).AddDays(-1))
Output: 2022-07-31T23:59:59Z

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.

PowerShell date/time conversion

I have a variable, $date, containing 24 June 2012 00:00:00.
How do I convert this to 24/06/2012?
Use the Get-Date cmdlet together with the Format parameter:
PS> $date = '24 June 2012 00:00:00'
PS> Get-Date $date -Format 'dd/MM/yyyy'
24/06/2012
I tried reading a file with dates formatted day-month-year
The answer above did not work for me, I found a different solution on how to parse my dates and check which one is newer than the current date. This is my adapted code.
$currdateobj = Get-Date
$STARTDATE = "12-05-2017" // specific non-default date format
[DateTime]$startdateobj = [DateTime]::ParseExact($STARTDATE,"dd-MM-yyyy",[System.Globalization.CultureInfo]::InvariantCulture)
if ($startdateobj -lt $currdateobj)
{
// ....
}

Use UFormat to get unix time

I can use following to append a date to a text:
"Foo {0:G} Foo" -f (date) #returns "Foo 2009-12-07 15:34:16 Foo"
But I want the time in Unix format.
I can get it by date -UFormat %s, but can I use the same syntax?
When I use -UFormat %s I get 1260199855,65625, how do I remove the decimal?
[int](Get-Date -UFormat %s -Millisecond 0)
Here's how I do it:
$DateTime = (Get-Date).ToUniversalTime()
$UnixTimeStamp = [System.Math]::Truncate((Get-Date -Date $DateTime -UFormat %s))
Just cast the result to an int like so:
PS> [int][double]::Parse((Get-Date -UFormat %s))
1260172909
PS> "Foo {0:G} Foo" -f [int][double]::Parse((Get-Date -UFormat %s))
Foo 1260172997 Foo
Using the Parse method means the string is parsed "culture aware" such that the appropriate decimal separator character is recognized for the current culture. If you just cast directly, PowerShell uses the invariant culture which causes problems for any culture where decimal sep char is not a period.
I did this, rounded up
[System.Math]::Round((date -UFormat %s),0)
My solution:
(Get-Date -UFormat %s) -Replace("[,\.]\d*", "")
I would just truncate the decimal:
(date -UFormat %s).split('.')[0]
The answer should be in UTC. This should be good for embedding in Discord. See https://www.unixtimestamp.com "-uformat %s" does NOT convert to UTC in powershell 5.1 (but powershell 7 does). Only one other answer takes this into account, and not the accepted answer.
$unixtime = get-date '12/28/22 10pm' | % ToUniversalTime | get-date -uformat %s
"<t:$unixtime>"
<t:1672282800>
Alternative for UTC unix time:
[datetimeoffset]'12/28/22 10pm' | % ToUnixTimeSeconds
1672282800