Powershell - Subtract two dates excluding the weekends - powershell

I have two dates: 1. Current_Date 2. Last_Updated_Date
I would like to take the Current_Date subtract the Last_Updated_Date without including the weekends.
This will be done in Powershell. Any input would be appreciated.
Thank you.

You may use a helper function for that:
function Get-WorkingDates {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true, Position = 0)]
[datetime]$StartDate,
[Parameter(Mandatory = $true, Position = 1)]
[datetime]$EndDate
)
# swap if the end date is before the start date
if ($EndDate -lt $StartDate) { $StartDate, $EndDate = $EndDate, $StartDate }
$difference = $enddate - $startdate # or: New-TimeSpan -Start $startdate -End $enddate
$days = [Math]::Ceiling($difference.TotalDays) + 1
# loop through the days and filter out the dates that are Saturday or Sunday
1..$days | ForEach-Object {
$startdate
$startdate = $startdate.AddDays(1)
} | Where-Object { 1..5 -contains $_.DayOfWeek }
# or filter with Where-Object { $_.DayOfWeek -gt 'Sunday' -and $_.DayOfWeek -lt 'Saturday' }
# or something like Where-Object { $_.DayOfWeek -gt 0 -and $_.DayOfWeek -lt 6 }
}
and use it like this
Get-WorkingDates $Current_Date $Last_Updated_Date
This will output an array of working day dates.
Of course you can capture that in a variable if you like:
$workingDates = Get-WorkingDates $Current_Date $Last_Updated_Date
to get the number of working dates with #($workingDates).Count
the #() in the last example is to force the $workingDates variable to be an array that has a .Count property, even if there is only one date in it.

Related

How to get a result from a function

I'm trying to write a function to calculate either a full ISO date (yyyy-W-d, where W is the ISO week number), or just the ISO week number by itself. My function is based on this.
I have 2 problems with my code. One is that I do not know how extract either of the results I am after as written above. The other problem is that the second parameter doesn't show when I try to call the function.
This is my current code.
Function Get-ISODate {
Param(
[datetime]$Date = (Get-Date),
[bool]$LongFormat
)
$DayOfWeek = $Date.DayOfWeek
If ($DayOfWeek -match "[1-3]") {$Date.AddDays(3)}
$Year = $Date.Year
$Week = $(Get-Culture).Calendar.GetWeekOfYear(($Date),[System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [DayOfWeek]::Monday)
$Day = $Date.Day
If ($LongFormat)
{
Get-ISODate = $Year + '-W' + $Week + '-' + $Day
}
Else
{
Get-ISODate = 'W' + $Week
}
}
My expected results would be,
Get-ISOWeek returns W16, which is the current ISO week at this time of writing.
Get-ISOWeek -LongFormat $true returns 2021-W16-1
Get-ISOWeek -Date '2000-1-1' returns W52
Get-ISOWeek -Date '2000-1-1' -LongFormat $true returns 1999-W52-6
I'm using this link to verifiy my results with regards to the week calculation.
You can read about switch paramenter here.
What Mathias meant is to literally remove Get-ISODate =
The function should look like this:
Function Get-ISODate {
Param(
[datetime]$Date = (Get-Date),
[switch]$LongFormat
)
$DayOfWeek = $Date.DayOfWeek
If ($DayOfWeek -match "[1-3]") {$Date.AddDays(3)}
$Year = $Date.Year
$Week = $(Get-Culture).Calendar.GetWeekOfYear(($Date),[System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [DayOfWeek]::Monday)
$Day = $Date.Day
If ($LongFormat.IsPresent)
{
return "$Year-W$Week-$Day"
}
'W' + $Week
}
# Testing the function
PS /~> Get-IsoDate
W16
PS /~> Get-IsoDate -LongFormat
2021-W16-19
Got this working. Please note that the main issue was that I was trying to call the function incorrectly with "Get-ISOWeek". Monday morning.
I also added .value__ to Day for $Day to get the number instead of the day as "Monday" etc.
Function Get-ISODate {
Param(
[datetime]$Date = (Get-Date),
[bool]$LongFormat
)
$DayOfWeek = $Date.DayOfWeek
If ($DayOfWeek -match "[1-3]") {$Date.AddDays(3)}
$Year = $Date.Year
$Week = $(Get-Culture).Calendar.GetWeekOfYear(($Date),[System.Globalization.CalendarWeekRule]::FirstFourDayWeek, [DayOfWeek]::Monday)
$Day = $Date.DayOfWeek.value__
If ($LongFormat -eq $true)
{
"$Year-W$Week-$Day"
}
Else
{
"W$Week"
}
}
Edit: I realised after posting this, the year was sometimes wrong according to the week number and day of the week. So here is my new version. I have checked the dates here.
Function Get-ISODate {
Param(
[datetime]$Date = (Get-Date),
[switch]$LongFormat
)
[int]$Year = $Date.Year
[int]$Month = $Date.Month
[int]$Day = $Date.DayOfWeek.value__
If ($Day -eq 0) {$Day = 7}
If ($Day -ge 1 -and $Day -le 3) {$Date = $Date.AddDays(3)}
$Week = (Get-Culture).Calendar.GetWeekOfYear($Date, 'FirstFourDayWeek', 'Monday')
Switch ($Week)
{
52 {If ($Day -ge 5 -and $Day -le 7 -and $Month -ne 12) {$Year = $Year - 1} ; Break}
53 {If ($Day -ge 5 -and $Day -le 7 -and $Month -ne 12) {$Year = $Year - 1} ; Break}
1 {If ($Month -eq 12) {$Year = $Year + 1} ; Break}
}
$Week = $Week.ToString('00')
If ($LongFormat.IsPresent)
{
"$Year-W$Week-$Day"
}
Else
{
"W$Week"
}
}

Update SharePoint list field using powershell based on Date comparison

I am currently try to update SharePoint field (Dropdown field called Overdue to Yes if the dateFormat field is equal or less than current date. At this stage, it does not change the value. Is there anything that i missed. Please refer the code i have below. Thanks
if((Get-PSSnapin | Where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}) -eq $null) {
Add-PSSnapin Microsoft.SharePoint.PowerShell;
}
$SPWeb = Get-SPWeb "http://contoso/sites/test";
$List = $SPWeb.Lists["Catalog"];
$currentDate = Get-Date (Get-Date) -format dd/MM/yyyy;
$items = $List.Items;
foreach ($item in $items) {
$deadline = $item["TA Deadline"];
$dateFormat = Get-Date $deadline -format dd/MM/yyyy;
#if date Format is less or equal than current date then update the Overdue drop down field to yes
if($dateFormat -le $currentDate)
{
$item["Overdue"] = "YES"
$item.Update()
}
}
$SPWeb.Dispose();
I think you need to supply an index/numerical numerical value for the choice. See the blog post here.
As it mentions you could do:
$item["Overdue"] = 0; #assuming 0 == YES
Or
$item["Overdue"] = $list.Fields["Overdue"].GetFieldValue("YES");
New code for the datetime logic
if((Get-PSSnapin | Where {$_.Name -eq "Microsoft.SharePoint.PowerShell"}) -eq $null) {
Add-PSSnapin Microsoft.SharePoint.PowerShell;
}
$SPWeb = Get-SPWeb "http://contoso/sites/test";
$List = $SPWeb.Lists["Catalog"];
$currentDate = Get-Date;
$items = $List.Items;
foreach ($item in $items) {
$deadline = $item["TA Deadline"];
$dateFormat = [datetime]$deadline
#if date Format is less or equal than current date then update the Overdue drop down field to yes
if($dateFormat -le $currentDate)
{
$item["Overdue"] = "YES"
Write-Debug $item["Overdue"]
$item.Update()
}
}
$SPWeb.Dispose();
if the Overdue column is a yes/no field (Boolean) I guess You can either do like Dana V suggested, so:
$item["Overdue"] = 0
or
$item["Overdue"] = $true

Comparing PowerShell / SharePoint list dates

I am trying to use PowerShell to get the dates from a Sharepoint list and compare today's date to see if there is a match.
I have some code so far but it doesn't seem to be working. I am guessing I have some data types wrong when I am doing a comparison or something of that nature. This is the code I have so far below:
$unusableDatesArray is set with a CAML query to a list in SharePoint
The column name of the date field in SharePoint is called 'UnusableDate' and of type date/time
$todaysDate = Get-Date
$foundUnusableDate = $false
ForEach($item in $unusableDatesArray) {
if($item['UnusableDate'] -eq $todaysDate) {
$foundUnusableDate = $true
}
}
Even though both values appear to have 8/10/2017 12:00:00 AM as the value when I find a matching date, $foundUnusableDate never ends up being true. If anyone knows what I am doing wrong please chime in.
-eq is a "hard" comparison operator to get a $true out of it, both variables would need to be at the exact same datetime. This would return $true:
$date1 = [datetime]'8/11/2017 12:00:00'
$date2 = [datetime]'8/11/2017 12:00:00'
if ($date1 -eq $date2) {$true
} else {$false}
while a simple difference of one second would cause it to return $false
$date1 = [datetime]'8/11/2017 12:00:00'
$date2 = [datetime]'8/11/2017 12:00:01'
if ($date1 -eq $date2) {$true} else {$false}
To work around that you can use different approaches
$date1 = [datetime]'8/11/2017 12:00:00'
$date2 = Get-Date
if (('{0:yyyyMMdd}' -f $date1) -eq ('{0:yyyyMMdd}' -f $date2)) {$true} else {$false}
if ($date1.Date -eq $date2.Date) {$true
} else {$false}
$date1 = ([datetime]'8/11/2017 12:00:00').Date
$date2 = (Get-Date).Date
if ($date1 -eq $date2) {$true} else {$false}
$dateToCheck = Get-Date
ForEach($item in $unusableDatesArray) {
[DateTime]$sharePointDate = $item['UnusableDate']
if(Get-Date $sharePointDate -Format 'MM/dd/yyyy') -eq (Get-Date $dateToCheck -Format 'MM/dd/yyyy')) {
$foundUnusableDate = true
}
}
The above is my final solution

Filtering dates in PowerShell from CSV input

I've got a script that's causing me grief, where the where clause in the final pip isn't filtering dates out by the criteria I want.
The script is taking a CSV as an input, and the script parses the dates it finds so that they are in the correct date format.
The dates are then processed in a Where-Object clause to select all dates that are from within the past month onwards (all records with dates prior are not included). The problem I'm having is that this filter isn't working, and I'm getting all records included regardless.
My question is, what is wrong with my script and how can I fix this where clause.
Here's the code that correlates directly to the above:
if ($o.'Joined Company') {
$StartDate = [datetime]::ParseExact($o.'Joined Company','d/MM /yyyy',$null).ToString("dd/M/yyyy")
$o.StartDateObj = $StartDate
} elseif ($o.'Joined Company' -eq '') {
$o.StartDateObj = $null
}
if ($o.'last day of duty') {
$EndDate = [datetime]::ParseExact($o.'Last Day of Duty','d/MM/yyyy',$null).ToString("dd/M/yyyy")
$o.EndDateObj = $EndDate
} elseif ($o.'Last Day of Duty' -eq '') {
$o.EndDateObj = $null
}
Write-Debug ("" + $o.EndDateObj)
Write-Debug ("" + $o.StartDateObj)
}
$Today = Get-Date
$LastMonth = $Today.AddMonths(-1)
$obj | Where-Object {$_.Company -like "New Zealand"} |
Where-Object {($_.EndDateobj -gt $LastMonth) -or ($_.EndDateobj -eq $null)} |
It's just a snippit of the full script, which can be found here.

Powershell compare months and exclude which are not required

I have a text file as shown below. I need to preserve the files which are within 6 months old (from the previous month) and write every other content to other file which are more than 6 months old.
What I've done so far is like:
$array3 =
do {
foreach($monthl in $monthlookup)
{
$mnthl = $monthl -split '-'
$m_day = $mnthl[1]
$m_month = $mnthl[2]
$m_year = $mnthl[3]
$m_temp = 0
$prevmonth = (Get-Date).AddMonths(-1).ToString("dd-MM-yy")
while(($m_temp -eq "0"))
{
if(($m_month -ge $startmonth) -and ($m_month -le $prevmonth))
{
$monthl | Add-Content "C:\each_month_latest.txt"
break;
}else
{
$monthl | Add-Content "C:\exclusions.txt"
}
}
}
} until ($m_month -ge $m)
What the issue I identified here is like: If the current month is 1, then it wont go back to the last 6 months and check, as I use just strings here.
Any suggestions or code improvements, anyone of you can think of..? Would be really appreciated.
Edit
monthlookup will look like:
testdatabase-30-11-14-23-00
testdatabase-31-12-14-23-00
testdatabase-30-01-15-23-00
testdatabase-31-01-15-23-00
testdatabase-27-05-15-23-00
testdatabase-28-02-15-23-00
testdatabase-31-03-15-23-00
testdatabase-30-04-15-23-00
testdatabase-31-05-15-23-00
$m is $m = Get-Date -Format "MM"
Well, I don't completly understand what you want to do but here some tipps:
$prevmonth = (Get-Date).AddMonths(-1).ToString("dd-MM-yy") shouldn't be done each time within the foreach loop
You could extract the date using a simple regex: [regex]::Match('testdatabase-30-11-14-23-00', '^.*?-(\d{2}-\d{2}-\d{2}-\d{2}-\d{2}$)').Groups[1].Value
Parse the date using [datetime]::ParseExact and a format string
So it could look like this:
# this doesn't have to be done each time in the foreach loop
$sixMonthBefore = (Get-Date).AddMonths(-6)
foreach($monthl in $monthlookup)
{
# extract the date
$dateString = [regex]::Match($monthl, '^.*?-(\d{2}-\d{2}-\d{2}-\d{2}-\d{2}$)').Groups[1].Value
# create a datetime using format string
$date = [datetime]::ParseExact($dateString, 'dd-MM-yy-HH-mm', $null)
if ($date.Month -eq (Get-Date).Month -and $date.Year -eq (Get-Date).Year)
{
Write-Host "$monthl is from this month"
}
elseif ($date -gt $sixMonthBefore)
{
$monthl | Add-Content "C:\each_month_latest.txt"
}
else
{
$monthl | Add-Content "C:\exclusions.txt"
}
}