Powershell - Determine Sunset and Add Time - powershell

I have a Powershell script that determines my local sunrise and sunset. However, my end goal is to run a function at 45 minutes past sunset. I know I can't use AddMinutes(45) as that only works with Get-Date. I tried to format the output of the value returned for "sunset", but even formatted to match Get-Date, it still doesn't work. Is there some other method I could use?
$Daylight = (Invoke-RestMethod "https://api.sunrise-sunset.org/json?lat=35.608081&lng=-78.647666&formatted=0").results
$Sunrise = ($Daylight.Sunrise | Get-Date -Format "HH:mm")
$Sunset = ($Daylight.Sunset | Get-Date -Format "dddd, MMMM dd, yyyy hh:mm:ss tt")

If you're using PowerShell Core, the properties Sunrise and Sunset from the object returned by your API query should already be of the type DateTime, however in Windows PowerShell, you would need to cast [datetime] to them to convert them from string. Then .AddMinutes method would work without issues, if you're looking to run a function 45 minutes past Sunset you can try the following assuming this could be a scheduled task:
$Daylight = (Invoke-RestMethod "urlhere").results
$sunset = [datetime] $Daylight.sunset # => [datetime] only needed in Windows PowerShell
if([datetime]::Now -ge $sunset.AddMinutes(45)) {
# run function here
}
Or if you want your script to execute and wait until the right time, you can use a loop:
do {
Start-Sleep -Seconds 60
} until([datetime]::Now -ge $sunset.AddMinutes(45))
# run function here

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

Powershell keep looping until condition is true then proceed

I have written a script that so far is able to check a file "latest.json" for the "created_at" object which shows the last date that a commit has occurred for software.
$websiteJson = Invoke-WebRequest "https://website/latest.json" | ConvertFrom-Json | select created_at
$todaysDate = Get-Date -Format "yyyy-MM-dd HH:mm"
if($websitejson.created_at | where {$_.created_at -eq $todaysDate}){
Write-Output "Today's date matches"
} else {
Write-Output "has not yet been updated"
}
How part of latest.json looks like
"created_at":"2020-03-23 17:32:48"
How do I change this to keep looping until the date pull from latest.json matches then proceed to next step (would download and install software). Also, since "created at" has "17:32:48" will this cause the date check to fail since the time does not match?
. I want it to keep checking if dates match.
Thank you!
Right now, I'm not going to bother converting dates to match to make sure they're the same format, but what you need for your specific questions is just a do until loop. I might update this to check the date formats if you supply an example layout of the returned JSON.
Do{
$websiteJson = Invoke-WebRequest "https://website/latest.json" | ConvertFrom-Json | select created_at
$todaysDate = Get-Date -Format "yyyy-MM-dd HH:mm"
if($websitejson.created_at | where {$_.created_at -eq $todaysDate}){
Write-Output "Today's date matches"
} else {
Write-Output "has not yet been updated"
}
start-sleep -s 60
}until($websiteJson -eq $todaysDate)
I believe this wont work right off the bat. You'll have to get the JSON date and $todaysDate to be the same format, then you can do this and it will work.
if you want to compare the date and/or time, use datetime objects instead of datetime strings. something like this ...
if you want to test for the actual time difference between two time objects ...
((Get-Date -Date '2020-03-23 18:11:22') - [datetime]'2020-03-23 17:32:48').TotalHours
# result = 0.642777777777778
you keep mentioning date as if you don't want the time, so this method would work for comparing the date parts of two timestamps ...
# the date at the time the code was run = 2020 April 03, Friday 4:30:34 PM
$Today = (Get-Date).Date
$Created_At = '2020-04-03 15:15:15'
$Today -eq ([datetime]$Created_At).Date
result = True

How to generated a timestamp based on another formatted timestamp

I'm attempting to output a timestamp in Powershell to represent the time now (rounded down to the 00 seconds), and another to represent 30 minutes before that. Both timestamps should be formatted yyyy-mm-ddThh:mm:ss.
If I use just Get-Date as when setting $end_time, then $start_time is set too.
$end_time = Get-Date
$start_time = $end_time.AddMinutes(-30)
However, when I format $end_time as required, an error occurs when settings $start_time. It looks like calling -Format returns the date as string rather than a date object.
$end_time = Get-Date -Format s -Second 00
$start_time = $end_time.AddMinutes(-30)
Method invocation failed because [System.String] does not contain a method
named 'addminutes'.
To try and work around this shortcomming I added a $date variable, but now I'm unable to even set $end_time. I guess this is because the formatting is returned by the Get-Date function, and cannot be set retrospectily.
$date = Get-Date
$end_time = $date -Format s -Second 00
Unexpected token '-Format' in expression or statement.
So my question is: if I am unable to manipulate a formatted date, and if I cannot format a pre-generated date as requred, how is it possible to generate two timestamps that are 30 minutes apart (one for 'now', one for 30 minutes ago) and which are formatted as yyyy-mm-ddThh:mm:ss?
Instead of using the -Format parameter of Get-Date, use the .ToString method on the date objects you create instead:
$Date = Get-Date -Second 0
$Date.ToString("yyyy-MM-ddTHH:mm:ss")
$Date.AddMinutes(-30).ToString("yyyy-MM-ddTHH:mm:ss")
Explanation:
Get-Date is executed and returns a DateTime object representing the current date and time with the seconds set to 0. This is then cast to a string using the .ToString method to format per your custom style.
The next command is the same, but before casting it as a formatted string (whereby it loses the date object methods), the .AddMinutes method is used to remove 30 minutes.
Keep $date as datetime, use ToString as required:
$date = Get-date -second 0
$end_time = $date.ToString("yyyy-MM-ddTHH:mm:ss")
$start_time = ($date.AddMinutes(-30)).ToString("yyyy-MM-ddTHH:mm:ss")

Change format of DateTimeReceived (Built-in feature from Microsoft)

I am working with email and its downloading and i want to set a condition to run a script with If {} only when email is received on the same day.
I do have this 2 lines of script:
$datetime = get-date -f yyyMMdd
$Sfha = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::DateTimeReceived, $datetime)
First declares today in the format of yyymmdd.
In order If condition to work, I also need to change format of DateTimeReceived.
You can pass date as a parameter to the get-date function, it can convert it to a specified format. You can try something like,
$datetime = get-date -f yyyyMMdd
$Sfha = new-object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo((Get-Date ([Microsoft.Exchange.WebServices.Data.EmailMessageSchema]::DateTimeReceived) -Format yyyyMMdd), $datetime)

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.