How to get a result from a function - powershell

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"
}
}

Related

powershell IF condition in a Variable

I've been strugling on a little thing for few hours now, and I wanted to know if one of you have the solution (maybe i'm missing a little thing)
I got a switch for setting the condition in a IF but seems it doesn't interprete it as a if condiction
switch ( $CampaignStatus )
{
"Complete" { $CampainCondition = ($DateStr -eq (get-date -Format "MM/dd/yyyy")) }
"Incomplete" { $CampainCondition = ($DateStr -eq (get-date -Format "MM/dd/yyyy")) }
"InProgress" { $CampainCondition = ($DateStr -gt (get-date -Format "MM/dd/yyyy")) }
}
foreach($c in $CampaignList) {
$index = $index +1
$DateStr = ConvertToFriendlyDate -Date $c.deadline
if ($CampainCondition) { blablabla}
Any idea ?
I tried with quotes, without etc
You're looking for Script Blocks to store those expressions and later evaluate them:
$CampainCondition = switch ( $CampaignStatus ) {
"Complete" { { $DateStr -eq (Get-Date -Format "MM/dd/yyyy") } }
"Incomplete" { { $DateStr -eq (Get-Date -Format "MM/dd/yyyy") } }
"InProgress" { { $DateStr -gt (Get-Date -Format "MM/dd/yyyy") } }
}
Then for evaluation, you can use the call operator &:
foreach($c in $CampaignList) {
$index = $index++
$DateStr = ConvertToFriendlyDate -Date $c.deadline
if(& $CampainCondition) {
<# blablabla #>
}
<# blablabla #>
}
As for the conditions themselves, instead of converting the date into a specific format (Get-Date -Format "MM/dd/yyyy") and then comparing that string with $DateStr, it would a much better idea to parse $DateStr as a DateTime instance and compare that against today's date.

Powershell - Subtract two dates excluding the weekends

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.

How to manage transition from one year to another in powershell

I've this list of directories to ZIP :
2019_40
2019_41
2019_42
2019_43
2019_44
2019_45
2019_46
2019_47
2019_48
2019_49
2019_50
2019_51
2019_52
2020_01
2020_02
2020_03
2020_04
2020_05
Here my code to zip them. I set the year 2020 for simulation what will happen the next year :
### Set 7Zip excutabe as variable
$7Zip = gci c:\Program* -include '7z.exe' -recurse -ea 4|select -first 1 -expand fullname
# Date
$Year = get-date -UFormat %Y
$WeekNb = get-date -UFormat %V
#Simulation the future
$Year = "2020"
$WeekNb = "02"
$Dir_To_Zip = Get-ChildItem -path "C:\Temp\LOG Script"
Foreach ($element in $Dir_To_Zip )
{
$DirName = $element.Name
$DirNameY = $DirName.Substring(0, $DirName.Length -3 )
$DirNameW = $DirName.Substring($DirName.Length -2)
if ( $DirNameW -lt $WeekNb - 4 )
{
& $7zip a "$element.zip" "$element" }
}
In this state my script is ziping the directories of the year 2020 only, not the 2019.
If I change this line :
if ( $DirNameW -lt $WeekNb - 4 )
by this one
if (( $DirNameY -le $Year -1 ) -or ($DirNameW -lt $WeekNb -4 ))
All directories are zipped
With the -or condition, the $DirNameY was not considered like a string number so I corrected like this :
#Set 7Zip excutabe as variable
$7Zip = gci c:\Program* -include '7z.exe' -recurse -ea 4|select -first 1 -expand fullname
# Date
$Year = get-date -UFormat %Y
$WeekNb = get-date -UFormat %V
# DEBUG pour forcer l annee et le numero de seamine
$Year = "2020"
$WeekNb = "05"
# List files to  Zip
$Dir_To_Zip = Get-ChildItem -path "C:\Temp\LOG Script"
Foreach ($element in $Dir_To_Zip )
{
$DirName = $element.Name
$DirNameY = $DirName.Substring(0, $DirName.Length -3 )
$DirNameW = $DirName.Substring($DirName.Length -2)
$DirNameW = $DirNameW.trimstart('0')
if (( $DirNameY -lt $Year -1 ) -or ($DirNameW -lt $WeekNb -4 ))
{
& $7zip a "$element.zip" "$element" }
}

copying files from daily folders using Powershell

I am looking to move daily created files each day to another folder. These files are saved to the relevant YYYY\MM\folder each day. Now I have created a way to move these files over using the year/month date function, however because there a number attached to the month, i.e. December looks like "12. December" it becomes a little tricky.
I tried to amend this with an If statement which would assign "a" to the relevant number corresponding with the month however it doesnt work.
$year = (Get-Date).Year
$month = Get-Date -Format "MMMMMMMM"
$day = (Get-Date).Day
$a = ""
If ($month = "January") { $a = "1."}
Elseif ($month = "February") { $a = "2."}
Elseif ($month = "March") { $a = "3."}
Elseif ($month = "April") { $a = "4."}
Elseif ($month = "May") { $a = "5."}
Elseif ($month = "June") { $a = "6."}
Elseif ($month = "July") { $a = "7."}
Elseif ($month = "August") { $a = "8."}
Elseif ($month = "September") { $a = "9."}
Elseif ($month = "October") { $a = "10."}
Elseif ($month = "November") { $a = "11."}
Elseif ($month = "December") { $a = "12."}
$month = Get-Date -Format $a" MMMMMMMM"
Copy-Item -Path F:\BB\$year\$month\Scan.pdf -Destination F:\BB
Any idea how to fix this/where am i going wrong. This is my first time writing in Powershell.
Edit: I am getting an error in the file location it is copying to does not register the difference in the coressponding months. For example the if statement states that if the month is = December a should = 12. but its currently coming up as 1. which should be the case for if it were January
The different forms of the month may as well be repeated in the format string, where
M = month number without leading zeroes
MM = month number with leading zeroes
MMM = abbreviated month name
MMMM = full month name
So:
$Month = Get-Date -f "M. MMMM"
> $Month
12. December
As the format string can contain any letter you can build the source path in one step:
(escaped with a backslash if interfering with a format letter)
$Source = "F:\BB\{0:yyyy\\M. MMMM}\Scan.pdf" -f (Get-Date)
> $Source
F:\BB\2018\12. Dezember\Scan.pdf
But I'm missing the days here?
If you use
$month = Get-Date -Format "MM"
this will get you the month as a number. If I understand what you are trying to achive this should match you source path.
$Date = get-date
$Path = "F:\BB\" + "$($Date.year)" + "\" + "$($Date.month)" + "\"
Copy-Item -Path $Path -Destination F:\BB

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"
}
}