It's me again, talented programming beginner fast-learner, so I have overcomed yet another self-imposed programming challenge, I have developped two algorithms to calculate occurrences of Friday the 13th between two given years(including the two inputed years) as said in title using PowerShell, one with built-in, the other without built-in. I have tested them numerous times on Windows 10 Power 7.1 x64, redirected their outputs to txt and compared the txts using fc and compared the results with outputs of other softwares and confirmed they are both working.
My idea is to loop through all 13th's (loop1 through years loop2 in loop1 through months) and check their Fridayness, the one with builtin, I used [DateTime] and [DateTime].DayOfWeek to do this mainly in one line, the one without builtin I used brute force to convert date to number of days, using this: days=365(y-1)+m+d+leap, where y is the year, m is sum of days before the month, d is day, and leap is: q(y/4)-q(y/100)+q(y/400), where q() means quotient of the division, Now I know of [math]::floor() and I know I can determine number of leap years using this:
$leap=[math]::floor($year/4)-[math]::floor($year/100)+[math]::floor($year/400)
But I decided against using this, then I checked Fridayness by date mod 7, I have found out if the remainder is 5 then it's Friday, now here are the scripts:
With Built-in:
$start=Read-Host "Input start year"
$end=Read-Host "Input end year"
$years=$start..$end
$blackfriday=@()
foreach ($year in $years) {
$blackfriday+=1..12 | foreach { [datetime]"$year-$_-13" } | where { $_.DayOfWeek -eq 'Friday'} | foreach {$_.tostring("yyyy, MMMM dd, dddd")}
}
$blackfriday
Without Built-in:
$months=@(
[PSCustomObject]@{Month='January';Days=31}
[PSCustomObject]@{Month='February';Days=28}
[PSCustomObject]@{Month='March';Days=31}
[PSCustomObject]@{Month='April';Days=30}
[PSCustomObject]@{Month='May';Days=31}
[PSCustomObject]@{Month='June';Days=30}
[PSCustomObject]@{Month='July';Days=31}
[PSCustomObject]@{Month='August';Days=31}
[PSCustomObject]@{Month='September';Days=30}
[PSCustomObject]@{Month='October';Days=31}
[PSCustomObject]@{Month='November';Days=30}
[PSCustomObject]@{Month='December';Days=31}
)
function BlackFriday {
param(
[Parameter(ValueFromPipeline=$true, Mandatory=$true, Position=0)] [int64] $start,
[Parameter(ValueFromPipeline=$true, Mandatory=$true, Position=1)] [int64] $end
)
$years=$start..$end
$blackfriday=@()
foreach ($year in $years) {
$array=1..12
foreach ($arra in $array) {
$month=0
for ($i=0;$i -lt $arra-1;$i++) {
$month+=$months[$i].Days
}
[int]$ye=$year
if ($arra -le 2) { $ye-=1}
if ($ye % 4 -eq 0) {$leap=$ye/4}
else {while ($ye % 4 -ne 0) {$ye-=1}
$leap=$ye/4}
if ($ye % 100 -eq 0) {$century=$ye/100}
else {while ($ye % 100 -ne 0) {$ye-=4}
$century=$ye/100}
if ($ye % 400 -eq 0) {$cycle=$ye/400}
else {while ($ye % 400 -ne 0) {$ye-=100}
$cycle=$ye/400}
$leap=$leap-$century+$cycle
$date=[int64](($year-1)*365+$month+13+$leap)
if ($date % 7 -eq 5) {
$name=$months[$arra-1].Month
$blackfriday+=[string]"$year, $name 13, Friday"
}
}
}
$blackfriday
}
$start=Read-Host "Input start year"
$end=Read-Host "Input end year"
BlackFriday $start $end
But wait, I have also written a script based on Zeller's algorithm from here: https://en.wikipedia.org/wiki/Determination_of_the_day_of_the_week Which is not working, I don't know where I did wrong, I don't know whose fault this is, please help me make all three scripts better, I will post it below:
$months=@(
'January'
'February'
'March'
'April'
'May'
'June'
'July'
'August'
'September'
'October'
'November'
'December'
)
function BlackFriday {
param(
[Parameter(ValueFromPipeline=$true, Mandatory=$true, Position=0)] [int64] $start,
[Parameter(ValueFromPipeline=$true, Mandatory=$true, Position=1)] [int64] $end
)
$years=$start..$end
$blackfriday=@()
foreach ($year in $years) {
$array=1..12
foreach ($arra in $array) {
$m=$arra
$ye=$year
if ($arra -le 2) {
$m=$m+12
$ye-=1
}
[int64]$y=([string]$ye).substring(([string]$ye).length-2)
[int64]$c=([char[]]"$ye"|Select-Object -First 2) -Join ''
$week=[int](((13*($m+1))/5 + $y/4 + $c/4 + 13 + $y - 2*$c) % 7)
if ($week -eq 6) {
$name=$months[$arra-1]
$blackfriday+=[string]"$year, $name 13, Friday"
}
}
}
$blackfriday
}
$start=Read-Host "Input start year"
$end=Read-Host "Input end year"
BlackFriday $start $end