How to get the next business day in powershell - powershell

I have the following test code. Basically I am checking when a new file is created in folder. I need to know that if the file was created after 4pm display the next business day. Currently my code displays the next day, but I need to display the next business day. Any help would be appreciated.
$formatteddate = "{0:h:mm:ss tt}" -f (get-date)
if ($formatteddate -gt "4:00:00 PM"){
$(Get-Date).AddDays(1).ToString('MMM d yyyy')
}

Adding to what jisaak said: "business day" is organization specific. Some organizations don't work on holidays that other organizations do. If you want to handle holidays correctly you'll need an explicit list of holidays for your business
Omitting the formatting details (which OP seems to understand) this should do it:
# $date is input date
$nextBizDay = $date.adddays(1)
# You would probably want to generate the follow list programmatically,
# instead of manually as done here
$holidays = 1, <# New Years #>
18, <# MLK day 2016 #>
<# other holidays encoded as Day Of Year #>
360 <# Christmas in a Leap Year #>
# An alternative to a list of holidays like this is to find a web service
# you can query to get the holidays for a given year
while ($nextBizDay.DayOfWeek -eq 'Saturday' -or
$nextBizDay.DayOfWeek -eq 'Sunday' -or
$nextBizDay.DayOfYear -in $holidays) {
if ($nextBizDay.DayOfYear -gt 366) {
throw "No next business day this year. Need to add additional logic"
}
$nextBizDay = $nextBizDay.adddays(1)
}

Related

Writing Foldernames in a Array Powershell

I would like to write the directory names of several folders in an array. However, only all directory names with a date <today should be read. The directory names contain a date in this form * YYYYMMDD *
So I would have to do the following:
Borrow the date
Write the date in the form of YYYYMMDD in a variable
Read out directory names and check against the variable
Write data to an array ... do something ...
Can someone tell me how I can solve this with Powershell please?
Thank you
Start by retrieving all the candidate directories, then use Where-Object to extract the date part and test that it describes a date prior to today:
# Define threshold
$Today = (Get-Date).Date
# Go through all candidate directories
$oldDirectories = Get-ChildItem .\path\to\root\folder -Directory |Where-Object {
$dt = 0
# Test if directory name contains 8 consecutive digits describing a valid date
if($_.Name -match '(\d{8})' -and [datetime]::TryParseExact($Matches[1], 'yyyyMMdd', , $null, 'None', [ref]$dt)){
# We only want the ones with a date prior to today
$dt.Date -lt $today
}
else{
# Not containing a properly formatted date, we're not interested
$false
}
}
# Now we can extract the names
$oldDirectoryNames = #($oldDirectories.Name) # or #($oldDirectories |Select -Expand Name)
Do these directorynames start with the date?
yes
What do you mean by Borrow the date? Is that the date of today or what?
Determine the Date, Yes of today.
I read out the date accordingly and wrote it in a variable:
$Timestamp = ([datetime]::now).tostring("yyyyMMdd")
Now I want to read out all directory names which have got a Date < 1 Day and would like to process it in a foreach for further processing
Understandable?

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

duplicates when using directorysearcher

I have a script that is using DirectorySearcher to query Active Directory for around ~13k users total every day.
I have been told that there are duplicates in my report, but I cannot figure out why.
The duplicates usually appear at the end of the report, and has been 6-7 users so far. The only difference between these users & their previous entry in the report is that their last logon time has changed (the time of which is seconds AFTER the script was initially started)
#Get date for 3months back in datetime format
$Date = (Get-Date).AddDays(-90)
# Correct for daylight savings.
If ($Date.IsDaylightSavingTime)
{$Date = $Date.AddHours(-1)}
# Convert the datetime value, in UTC, into the number of ticks since
# 12:00 AM January 1, 1601.
$Value = ($Date.ToUniversalTime()).Ticks - ([DateTime]"January 1, 1601").Ticks
$Searcher = New-Object DirectoryServices.DirectorySearcher
$Searcher.PageSize = 30000
$Searcher.Filter = "(&(&(objectCategory=person)(objectClass=user))(lastLogonTimeStamp>=$value)(pwdLastSet>=$value)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))"
$Searcher.SearchRoot = 'LDAP://dc=contoso,dc=net'
$results = $Searcher.FindAll()
foreach ($result in $results)
{
# Fetches different attributes for each user
# which is then appended to a .csv file via Add-Content
}
It feels like I am identifying additional users based on the fact that their last logon time was changed.. does anyone know anything about this? Maybe
How I can disable this behavior?
The script runs at 06:00:00.
Here is the last logon time for the duplicate entries
10/31/2015 06:00:24
10/31/2015 06:00:32
10/31/2015 06:02:07
10/31/2015 06:05:01
10/31/2015 06:06:05
10/31/2015 06:08:19
10/31/2015 06:08:36

Date / Time condition in powershell - SharePoint - LastItemModifiedDate - LastRunTime

I'm making a script that collect two dates from the system. One from when the scheduling task has last run and the date a list has last been modified. Problem is that the datetime format isn't correct .
LastItemModifiedDate from a SPList - output format 04/09/2015 12:48:48
LastRunTime from a scheduling task - output format 09.04.2015 10:50:03
What I want to do is to check if the list has been changed since the last time the scheduling task has run.
$scheduledTask = Get-ScheduledTask -TaskName "SharePoint scheduling" | Get-ScheduledTaskInfo
$scheduledTaskLastRunTime = $scheduledTask.LastRunTime
$listExist = $spSourceWeb.Lists | where{$_.Title -eq $listName}
if($listExist)
{
$spSourceList = $spSourceWeb.Lists[$listName]
if ($scheduledTaskLastRunTime -le $spSourceList.LastItemModifiedDate)
{
Write-Host " Changes found" -ForegroundColor Green
SetListColumnToCopy($listName)
}
Do I do the IF correct ? What magic do I have to do to check the datetime?
I've read that "don't need a special format to compare dates in Powershell" but is it true in this situation?
You should use ParseExact static method from DateTime class.
$dateToCompare = [datetime]::ParseExact("09.04.2015 10:50:03","MM.dd.yyyy hh:mm:ss", $null)

Powershell Golf: Next business day

How to find next business day with powershell ?
Well, my phone allows me to set which days are business days, but Windows/.NET won't, so I assume Monday through Friday.
Note: As the question includes "golf" I am golfing this one, that is trying to use as few bytes for the script as possible. The code is not necessarily readable as a result.
The easiest and most straightforward way to do is would be to start with today, add a day and look whether it is in the wanted range:
PS> $d = [DateTime]::Now.AddDays(1); while ($d.DayOfWeek -eq "Saturday" -or $d.DayOfWeek -eq "Sunday") { $d = $d.AddDays(1) }; $d
Montag, 22. Juni 2009 19:50:27
We can shorten that a little, though:
PS> $d=(Get-Date)+"1";for(;6,0-contains$d.DayOfWeek){$d+="1"}$d
Montag, 22. Juni 2009 19:52:31
But we can also try it differently, using the pipeline. The next business day is at least one and at most three days away, so we can generate a list of possible dates and filter them accordingly and at last, select the first one:
PS> #(1..3|%{(Get-Date).AddDays($_)}|?{$_.DayOfWeek -ge "Monday" -and $_.DayOfWeek -le "Friday"})[0]
Montag, 22. Juni 2009 22:11:19
or shorter:
PS> #(1..3|%{(Get-Date)+"$_"}|?{1..5-contains$_.DayOfWeek})[0]
Montag, 22. Juni 2009 19:55:53
By letting the range go to 4 we can guarantee that it always returns at least two workdays and save the # operator to force an array:
PS> (1..4|%{(Get-Date)+"$_"}|?{1..5-contains$_.DayOfWeek})[0]
Montag, 22. Juni 2009 20:24:06
This is pretty short too (but uses aliases):
,(1,2-eq7-(date).dayofweek)|%{(date)+"$(1+$_[0])"}
In one single statement:
(date)+"$(1+$(#(1,2-eq7-(date).dayofweek)))"
A few notes about this approach:
In Powershell (v1 at least), comparisons with collections return items where the condition is true, for example:
PS> 1,2 -eq 1
PS> 1
I'm taking advantage of the fact that the actual exceptions to the rule today + 1 to calculate the next business day are only Friday (+3 days) and Saturday (+2 days).
Here is another pipline way:
(#(1..4) | foreach { if (([datetime]::Now.AddDays($_)).DayOfWeek -ne "Sunday" -and ([datetime]::Now.AddDays($_)).DayOfWeek -ne "Saturday") {[datetime]::Now.AddDays($_); }})[0]
Not sure why I have to use (1..4) instead of (1..3) however.
I found the sample code in the first answer to be really difficult to follow so I rewrote it to be a bit easier to see what was happening. I'm still using the -eq behavior where the -eq test will return the matching value.
$date = get-date "2013 Apr 24"
write-host "Based on your date"
$date
write-host "next business day (skipping saturday and sunday)"
$Date.AddDays(1 + $(1,2 -eq 7 - [int]$date.dayofweek) )
write-host "Next week monday"
$Date.AddDays(1 + $(0,1,2,3,4,5,6,7 -eq 7 - [int]$date.dayofweek) )