Get Easter-Sunday in Powershell - algorithm

I want to build a function to test if today is a workday or weekend/holiday.
So I headed over to german wikipedia and tried to recreate that Easter Formular from Gauß:
Function Test-Workday {
Param([Parameter(ValueFromPipeline=$True)]$Date = (Get-Date))
Process {
$Date = Get-Date -Date $Date
# Ergänzte Osteformel
# https://de.wikipedia.org/wiki/Gau%C3%9Fsche_Osterformel#Eine_erg%C3%A4nzte_Osterformel
# Floor abrunden, Ceiling aufrunden
# https://germanpowershell.com/mathematische-funktionen/
$X = $Date.Year
$K = [math]::Floor($X / 100)
$M = [math]::Ceiling(15 + (3 * $K + 3) / 4 - (8 * $K + 13) / 25)
$S = [math]::Ceiling(2 - (3 * $K + 3) / 4)
$A = $X % 19
$D = (19 * $A + $M) % 30
$R = [math]::Floor(($D + $A / 11) / 29)
$OG = 21 + $D - $R
$SZ = [math]::Ceiling(7 - ($X + $X / 4 + $S) % 7)
$OE = 7 - ($OG - $SZ) % 7
$OS = $OG + $OE
if ($OS -gt 31) {
$Day = $OS - 31
$Month = 4
} else {
$Day = $OS
$Month = 3
}
$EasterSunday = (Get-Date -Year $X -Month $Month -Day $Day)
# Feiertagsliste Hashtable: Tag des Jahres .Name (Index), Feiertag .Value
$Holiday = #{(Get-Date -Year $X -Month 1 -Day 1).DayOfYear = "Neujahr"
(Get-Date -Year $X -Month 1 -Day 6).DayOfYear = "Heilige Drei Könige"
$EasterSunday.AddDays(-2).DayOfYear = "Karfreitag"
$EasterSunday.AddDays( 1).DayOfYear = "Ostermontag"
(Get-Date -Year $X -Month 5 -Day 1).DayOfYear = "1. Mai"
$EasterSunday.AddDays(39).DayOfYear = "Christi Himmelfahrt"
$EasterSunday.AddDays(50).DayOfYear = "Pfingstmontag"
$EasterSunday.AddDays(60).DayOfYear = "Fronleichnam"
(Get-Date -Year $X -Month 10 -Day 3).DayOfYear = "Tag der Deutschen Einheit"
(Get-Date -Year $X -Month 11 -Day 1).DayOfYear = "Allerheiligen"
(Get-Date -Year $X -Month 12 -Day 24).DayOfYear = "Heiligabend"
(Get-Date -Year $X -Month 12 -Day 25).DayOfYear = "1. Weihnachtstag"
(Get-Date -Year $X -Month 12 -Day 26).DayOfYear = "2. Weihnachtstag"
(Get-Date -Year $X -Month 12 -Day 31).DayOfYear = "Sylvester"
}
# Prüfe auf Wochenende (Anfangsbuchstabe Samstag/Sonntag)
If(($Date).DayOfWeek.ToString().Substring(0,1) -eq "S") {
$Workday = $False
} else {
# Prüfe auf Feiertag
$Workday = (-Not ($Holiday.ContainsKey($Date.DayOfYear)))
}
# Werktrag $True sonst $False
Return $Workday
}
}
After a few tests, it seems to work.. but does it for real?
To get the exact same numbers as in the examples from the wikipedia article, I had to round the numbers up and down (floor/ceiling) here and there but that's why I'm insecure if it's really correct...
Also, is it ok to use hasthables like that? I planed to use the holidays Name but eventually decided otherwise.
The ContainsKey-Test seems to be faster than going through an array tho.
Thanks for your help! :-)

Related

I need to loop from one array to another new array

I'm sorting windows last logon, and I want to use only variables instead of file, in file it's easy to manipulate it but slow since it will use disk access not ram.
# lastlogon
$UserProperty = #{n="User";e={(New-Object System.Security.Principal.SecurityIdentifier $_.ReplacementStrings[1]).Translate([System.Security.Principal.NTAccount])}}
$TypeProperty = #{n="Action";e={if($_.EventID -eq 7001) {"Logon"} else {"Logoff"}}}
$TimeProperty = #{n="Time";e={$_.TimeGenerated}}
$MachineNameProperty = #{n="MachinenName";e={$_.MachineName}}
$last1=Get-EventLog System -Source Microsoft-Windows-Winlogon -ComputerName localhost | select $UserProperty,$TypeProperty,$TimeProperty,$MachineNameProperty
foreach ($line in $last1) {
$l = $line -split ' '
$user1 = $l[0]
$user0 = $user1 -replace ';'
$user2 = $user0.Substring($user0.IndexOf("\")+1,$user0.Length-$user0.IndexOf("\")-1)
$t1 = $l[2] -replace 'Time='
$t2 = $l[3] -replace ';'
$time1 = $t1+' '+$t2
$last21 = $user2+' '+$time1
}
$last21 will only get the last data. If I change it to += it will be one line. I want my $last21 like this:
PS > $last21
user1 1/2/20 150000
user1 1/1/20 120000
user2 1/1/20 010000
.
.
.
Thanks and more power!!!
You can do these who ever you are ;)
$last21 = $last1
$c = 0
foreach ($line in $last1) {
$l = $line -split ' '
$user1 = $l[0]
$user0 = $user1 -replace ';'
$user2 = $user0.Substring($user0.IndexOf("\") + 1, $user0.Length - $user0.IndexOf("\") - 1)
$t1 = $l[2] -replace 'Time='
$t2 = $l[3] -replace ';'
$t3 = $t1 + ' ' + $t2
$last21[$c] = $user2 + ' ' + $t3
$c += 1
}
$last2 = $last21 | sort -Descending

Powershell script - break loop

Giving this little script in powershell:
$index = 1
$file = "C:\Users\myfile"
while ($index -le 100000)
{
$init_size = Write-Host((Get-Item $file).length/1KB)
<here is my command which populates $file>
$final_size = Write-Host((Get-Item $file).length/1KB)
$index ++
sleep 5
If ($final_size -eq $init_size) {break}
}
I don't understand why it breaks even if the init_size is different from the final_size.
Any suggestions?
Write-Host writes directly to the screen buffer and doesn't output anything, so the value of both $init_size and $final_size are effectively $null when you reach the if statement.
Do Write-Host $variable after assigning to $variable and it'll work:
$index = 1
$file = "C:\Users\myfile"
while ($index -le 100000) {
$init_size = (Get-Item $file).Length / 1KB
Write-Host $init_size
<here is my command which populates $file>
$final_size = (Get-Item $file).Length / 1KB
Write-Host $final_size
$index++
sleep 5
If ($final_size -eq $init_size) { break }
}
Calling Write-Host on the results of the assignment expression itself would work too:
Write-Host ($init_size = (Get-Item $file).Length / 1KB)

Find time difference in minutes using a PowerShell script

I am trying to find the time difference between the last updated time and current time for a file. How do I extract TotalMinutes data from the output?
$Date = Get-Date
$Files = gci "C:\Users\ABCD\Documents\command.txt"
ForEach ($File in $Files){
$FileDate = $File.LastWriteTime
}
$DURATION=$Date-$FileDate
Echo $DURATION
Output is coming as below
Days : 0
Hours : 2
Minutes : 21
Seconds : 37
Milliseconds : 311
Ticks : 84973115857
TotalDays : 0.0983485137233796
TotalHours : 2.36036432936111
TotalMinutes : 141.621859761667
TotalSeconds : 8497.3115857
TotalMilliseconds : 8497311.5857
You will not need a loop, after getting a single file:
$Files = gci "C:\Users\ABCD\Documents\command.txt"
ForEach ($File in $Files){
$FileDate = $File.LastWriteTime
}
In this case, $Files might as well be $File, making the loop completely redundant:
$File = gci "C:\Users\ABCD\Documents\command.txt"
$FileDate = $File.LastWriteTime
In the exact same way you extracted LastWriteTime, you can get TotalMinutes:
$Date = Get-Date
$DURATION = $Date - $FileDate
$DURATION.TotalMinutes
Here is a complete answer:
$Date = Get-Date
$Files = gci "C:\Users\ABCD\Documents\command.txt"
ForEach ($File in $Files){
$FileDate = $File.LastWriteTime
}
$DURATION=$Date-$FileDate
Write-Host "$($DURATION.TotalMinutes)"
You can use the below command to get just TotalMinutes
$mins = $DURATION.TotalMinutes
$StartDate=(GET-DATE)
#wait a few seconds
$EndDate=(GET-DATE)
$diff = NEW-TIMESPAN -Start $StartDate -End $EndDate
Write-Output "Time difference is: $diff"
$diff
#to see minutes only
$diff.Minutes
#or seconds
$diff.Seconds
Assuming the file exists, here's a one-liner:
((Get-Date) - (Get-ChildItem 'C:\Users\ABCD\Documents\command.txt').LastWriteTime).TotalMinutes
You can either let it echo to the screen as is, or you can assign it to a variable if you want to retain it.

Deleting pictures based on dimensions with PowerShell

I would like to delete all VERTICAL and SMALL pictures from a certain folder.
I have a folder that I do not want the vertical pictures or pictures with dimensions less than 600 x 600 pixels. I believe that PowerShell is the best thing to use since I cannot get Python to work on my computer.
I am doing this because I do not want to manually delete the vertical/small pictures from my folder each day. (It gets new ones every day)
Any help would be greatly appreciated!!
Here is my code :
cd C:\Users\Jack\Desktop\Test
$c = 5
Function Get-FileMetaData {
Param([string[]]$folder)
foreach($sFolder in $folder) {
$a = 0
$b = 1
$objShell = New-Object -ComObject Shell.Application
$objFolder = $objShell.namespace($sFolder)
foreach ($File in $objFolder.items()) {
$FileMetaData = New-Object PSOBJECT
for ($a ; $a -le 266; $a++) {
if($objFolder.getDetailsOf($File, $a)) {
$hash += #{$($objFolder.getDetailsOf($objFolder.items, $a)) =
$($objFolder.getDetailsOf($File, $a)) }
$FileMetaData | Add-Member $hash
if ($($objFolder.getDetailsOf($objFolder.items, $a)) -eq "Height") {
Write-Host $($objFolder.getDetailsOf($objFolder.items, $a)) =====
$($objFolder.getDetailsOf($File, $a))
}
if ($($objFolder.getDetailsOf($objFolder.items, $a)) -eq "Width") {
Write-Host $($objFolder.getDetailsOf($objFolder.items, $a)) =====
$($objFolder.getDetailsOf($File, $a))
}
if ($($objFolder.getDetailsOf($objFolder.items, $a)) -eq "Name") {
Write-Host $($objFolder.getDetailsOf($objFolder.items, $a)) =====
$($objFolder.getDetailsOf($File, $a))
}
$b++
$hash.clear()
} #end if
} #end for
Write-Host $a
$a=0
$FileMetaData
} #end foreach $file
$c++
Write-Host c = $c
} #end foreach $sfolder
} #end Get-FileMetaData
Write-Host c = $c
$h = Get-FileMetaData C:\Users\Jack\Desktop\Test | select Height
$w = Get-FileMetaData C:\Users\Jack\Desktop\Test | select Width
$n = Get-FileMetaData C:\Users\Jack\Desktop\Test | select Name
$h
Write-Host w = $w
Write-Host name = $n
$SpecChars = '!', "{", "}", '"', '£', '$', '%', '&', '^', '*', '(', ')', '#', '=', '+', '¬', '`', '\', '<', '>', '?', '/', ':', ';', '#', '~', "'", '-', "Name", "N", "a", "m", "e", ' '
$remspecchars = [string]::join('|', ($SpecChars | % {[regex]::escape($_)}))
if (($h) -replace '\D+(\d+)','$1' -gt ($w) -replace '\D+(\d+)','$1') {
Write-Host "VERTICAL"
Write-Host name = $n
$d = $n -replace $remspecchars, ""
$d.split()
Write-Host $d
$tally = 0
while($tally -ne $d.Count) {
del $d[$tally]
$tally++
}
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}
Write-Host "Finished"
try this
$folder = 'C:\temp\Pictures\'
$image = New-Object -ComObject Wia.ImageFile
$pictures = Get-ChildItem $folder *.jpg | ForEach-Object {
$image.LoadFile($_.fullname)
$size = $image.Width.ToString() + 'x' + $image.Height.ToString()
$orientation = $image.Properties | ? {$_.name -eq 'Orientation'} | % {$_.value}
if ($orientation -eq 6) {
$rotated = $true
} else {
$rotated = $false
}
$heightGtWidth = if ([int]$image.Height.ToString() -gt [int]$image.Width.ToString()) {
$true
} else {
$false
}
[pscustomobject]#{
Fullname = $_.FullName
Size = $size
Rotated = $rotated
HeightGtWidth = $heightGtWidth
}
}
$pictures

Powershell passing variables to a job

Function start
{
$BackupList = Import-Csv C:\file.csv -Delimiter ";"
ForEach($computer in $BackupList)
{
$arrayBackup = ($computer.Backup).split(".")
$backupdate = Get-Date -Day $arrayBackup[0] -Month $arrayBackup[1] -Year $arrayBackup[2]
$datetoday = Get-Date -format d
$countingday = (get-date $datetoday).AddMonths(-3)
if ($Zahl -eq 1)
{
if ($backupdate -le $countingday)
{
$global:client = $computer.computername
$global:mac = $computer.MAC
$global:Name = $computer.device
$global:lastsaved = [int]$computer.lastsavetime
if ($computer.computername -match $Client)
{
{
$computer.Backup = $datetoday
if ($lastsaved -ne 4)
{
$lastsaved++
}
else
{
$lastsaved = 1
}
if ($lastsaved -eq 1)
{
$global:savingplace = "\\Savingplace1"
}
elseif ($lastsaved -eq 2)
{
$global:savingplace = "\\Savingplace2"
}
elseif ($lastsaved -eq 3)
{
$global:savingplace = "\\Savingplace3"
}
elseif ($lastsaved -eq 4)
{
$global:savingplace = "\\Savingplace4"
}
$computer.lastsavetime = $lastsaved
}
}
Start-Job -InitializationScript $functions -ScriptBlock {NASLOGIN} -argumentlist $_ | Receive-Job
}
}
}
}
I am reading some information out of a csv-file.
i want to pass some of this information read to a job.
in the job im doing quiet a lot of function calls and operations using this variables.
but at the moment there is no variable passed to the job.
how can i fix this?
You are passing $_ to the ArgumentList parameter but I don't see anywhere in where you code where there is a pipeline active - hence $_ is not defined. To pass variables to the job, specify valid variables in the ArgumentList e.g.:
$foo = 'foo'
$bar = 'bar'
Start-Job {param($a, $b) "a is $a, b is $b"} -Arg $foo,$bar | Receive-Job -Wait
Start-Job -ScriptBlock {NASLOGIN $args[0]$args[1]$args[2]$args[3]$args[4]} -argumentlist $var1,$var2,$var3,$var4,$var5 -InitializationScript $functions
}
}
}
$functions =
{
Function NASLogin
{
$var1 = $args[0]
$var2 = $args[1]
$var3 = $args[2]
$var4 = $args[3]
$var5 = $args[4]
Have done it like this and it works.
Thanks for your help.

Resources