Find 3rd Saturday of the month - powershell

I need to find the date of the third saturday of the month.
I've got the following function, which finds me the last saturday of the month
function Get-3rdSaturdayOfMonth {
$Date = Get-Date
$lastDay = new-object DateTime($Date.Year, $Date.Month, [DateTime]::DaysInMonth($Date.Year, $Date.Month))
$diff = ([int] [DayOfWeek]::Saturday) - ([int] $lastDay.DayOfWeek)
if ($diff -ge 0) {
return $lastDay.AddDays(- (7-$diff))
}
else {
return $lastDay.AddDays($diff)
}
}
However, I don't know how to edit it to find the third saturday of the month.
Right now the function goes from last date of the month to the saturday that comes before it. But if I want the third saturday i think i need to calculate from the first day of the month, not the last.

Based on the solution from Brandon, since the third Saturday can't possibly occur before the 15th of the month, we can increment from the 15. until we find a saturday:
$thirdSaturday = [DateTime]::new((Get-Date).Year,(Get-Date).Month,15)
while ($thirdSaturday.DayOfWeek -ne [DayOfWeek]::Saturday)
{
$thirdSaturday = $thirdSaturday.AddDays(1)
}

Related

Finding the Sunday between the 1st and 2nd Tuesday of the month

Fairly new to PS, I want to batch file on Sunday between the 1st and the 2nd Tuesday of the month.
I know how to find the the 1st and 2nd Tuesdays I am looking for, cannot figure out the rest.
$FindNthDay = 1
$WeekDay = 'Tuesday'
[datetime]$Today = [datetime]::NOW
$todayM = $Today.Month.ToString()
$todayY = $Today.Year.ToString()
[datetime]$StrtMonth1 = $todayM + '/1/' + $todayY
while ($StrtMonth1.DayofWeek -ine $WeekDay ) { $StrtMonth1 = $StrtMonth1.AddDays(1) }
$StrtMonth1.AddDays(7 * ($FindNthDay - 1))
#
$FindNthDay = 2
$WeekDay = 'Tuesday'
[datetime]$Today = [datetime]::NOW
$todayM = $Today.Month.ToString()
$todayY = $Today.Year.ToString()
[datetime]$StrtMonth = $todayM + '/1/' + $todayY
while ($StrtMonth.DayofWeek -ine $WeekDay ) { $StrtMonth = $StrtMonth.AddDays(1) }
$StrtMonth.AddDays(7 * ($FindNthDay - 1))
I know how to find the the 1st and 2nd Tuesdays
Since there's only one Sunday in between, you only need to find the first one:
# Get-Date -Day 1 will give us the 1st of the current month
$firstTuesday = Get-Date -Day 1
while($firstTuesday.DayOfWeek -ne 'Tuesday') {
$firstTuesday = $firstTuesday.AddDays(1)
}
And then add another 5 days:
$sundayAfterFirstTuesday = $firstTuesday.AddDays(5).Date
Which (in January 2021) gives us:
PS ~> $sundayAfterFirstTuesday
Sunday, January 10, 2021 12:00:00 AM
In addition to Mathias's fine answer, I got hung up on this. Given that .DayOfWeek is an [enum] that's easily converted to a [Int] I was looking for a mathematically concise way to derive the first Tuesday. Since it's fairly obvious how to then find the following Sunday by just doing .AddDays(5) .
Honestly, I was stumbling a bit because While .DayOfWeek is 0 - 6 how many days to add depends on if the current day, in this case the first of the month, is less than or greater than Tuesday (2). It was worth playing around; here are 2 alternate approaches I came up with:
Example 1: A switch statement that's not at all concise but is very readable:
$Day1 = Get-Date "1/1/2021"
Switch ( $Day1.DayOfWeek )
{
'Sunday' { $Sunday = $Day1.Adddays(2).AddDays( 5 ); Break }
'Monday' { $Sunday = $Day1.Adddays(1).AddDays( 5 ); Break }
'Tuesday' { $Sunday = $Day1.AddDays( 5 ); Break }
'Wednesday' { $Sunday = $Day1.Adddays(6).AddDays( 5 ); Break }
'Thursday' { $Sunday = $Day1.Adddays(5).AddDays( 5 ); Break }
'Friday' { $Sunday = $Day1.Adddays(4).AddDays( 5 ); Break }
'Saturday' { $Sunday = $Day1.Adddays(3).AddDays( 5 ); Break }
}
$Sunday
This is also easy to adjust. For example, if you wanted to switch to 1st Sunday between 1st & 2nd Monday etc...
For the mathematical / logic approach it came out a little more crude:
$Day1 = Get-Date "1/1/2021"
If( [Int]$Day1.DayOfWeek -gt 2 ) { $Interval = 7 - ([Int]$Day1.DayOfWeek - 2) }
Else { $Interval = 2 - [Int]$Day1.DayOfWeek }
$Sunday = $Day1.AddDays( $Interval ).AddDays( 5 )
$Sunday
The above example can be more concise in PowerShell 7+ using the ternary operator:
$Day1 = Get-Date "1/1/2021"
$Interval = $Day1.DayOfWeek -gt 2 ? 7 - ([Int]$Day1.DayOfWeek - 2) : 2 - [Int]$Day1.DayOfWeek
$Sunday = $Day1.AddDays( $Interval ).AddDays( 5 )
$Sunday
Note: all of the examples user 1/1/2021 as the starting date, but I did test across multiple 1st days of the month, For example, if the first day was a Monday, Sunday, Thursday etc...
Note: Some of the [Int] casting can probably be removed if one is careful about PowerShell type conversion system, but I wanted to get this out there. If I have time I'll cleanup further.
Or a slightly different approach:
$BaseDate = (Get-Date 3/1/2021)
$BaseDate.AddDays( (& {if ([int]$BaseDate.DayOfWeek -gt 2) {14}
else { 7 } }) - [int]($BaseDate).DayOfWeek)
Sunday, March 7, 2021 12:00:00 AM

PowerShell Print this business weeks mon-fri

I would like Powershell to determine the current week & print monday - friday in the format:
mm/dd/yyyy - mm/dd/yyyy
I saw a way to get the day of the week which is nice but I would like to just have it show the dates.
What I have so far, it works but if I run any day but Monday the dates would be off:
$bar = "------------------------------------"
$today = (Get-Date)
$dates = #($today.AddDays(0).ToString('MM-dd-yyyy'),
$today.AddDays(1).ToString('MM-dd-yyyy'),
$today.AddDays(2).ToString('MM-dd-yyyy'),
$today.AddDays(3).ToString('MM-dd-yyyy'),
$today.AddDays(4).ToString('MM-dd-yyyy'))
$result = "`n{0}`n{1}`n`n`n{2}`n{3}`n`n`n{4}`n{5}`n`n`n{6}`n{7}`n`n`n{8}`n{9}`n" -f $dates[0], $bar, $dates[1], $bar, $dates[2], $bar, $dates[3], $bar, $dates[4], $bar
echo $result
this seems to do what you want. [grin] it uses the builtin weekday list, indexes into that with the current weekday name, calculates the 1st day of the current week, generates an array of dates for the current week, and finally prints it out with the lines & vertical spacing that you seem to want.
# for my locale, the 1st day is "Sunday"
$WeekDayList = [System.DayOfWeek].GetEnumNames()
$Line = '-' * 40
$Newline = [environment]::NewLine
$BlankLineCount = 3
# the ".Date" property gives you midnite, not "now"
$Today = (Get-Date).Date
$TodayNumber = $WeekDayList.IndexOf($Today.DayOfWeek.ToString())
$WeekStartDate = $Today.AddDays(-$TodayNumber)
$CurrentWeek = foreach ($Offset in 0..6)
{
$WeekStartDate.AddDays($Offset).ToString('yyyy-MM-dd')
}
-join ($CurrentWeek -join "$Newline$Line$($Newline * $BlankLineCount)"), "$Line$($Newline * $BlankLineCount)"
output ...
2019-01-20
----------------------------------------
2019-01-21
----------------------------------------
2019-01-22
----------------------------------------
2019-01-23
----------------------------------------
2019-01-24
----------------------------------------
2019-01-25
----------------------------------------
2019-01-26
----------------------------------------
[not part of the output - needed to show that there are two blank lines above this one. [*grin*]
I have come across the requirement to get a date from a week day, and wrote a function to return a [DateTime].
Using this function and ToString() to format the date to your requirements, gives an output of:
2019/01/21 - 2019/01/25
Code:
Function Get-DateFromDay {
param(
[Parameter(Mandatory = $true)]
[ValidateSet('Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday')]
[string]$WeekDay,
[Int]$AddWeeks = 0
)
$DayNumber = #{
'Saturday' = 1;
'Sunday' = 0;
'Monday' = -1;
'Tuesday' = -2;
'Wednesday' = -3;
'Thursday' = -4
'Friday' = -5
}
[System.Datetime]$Today = Get-Date
$NumDaysSinceDateFromDay = $Today.DayOfWeek.value__ + $DayNumber[$WeekDay]
[System.Datetime]$DateFromDayThisWeek = $Today.AddDays(-$NumDaysSinceDateFromDay)
$DateFromDayThisWeek.AddDays( + ($AddWeeks * 7))
}
$Monday = (Get-DateFromDay -WeekDay Monday).ToString('yyyy/MM/dd')
$Friday = (Get-DateFromDay -WeekDay Friday).ToString('yyyy/MM/dd')
Write-Output "$Monday - $Friday"
And a few examples of use for those who come across this post in the future:
Thursday next week:
Get-DateFromDay -WeekDay Thursday -AddWeeks 1
Tuesday last week:
Get-DateFromDay -WeekDay Tuesday -AddWeeks -1

how to get tuesdays to mondays every week starting from tuesday

I am trying to sum a coloumn in my database and it must start from tuesdays to mondays every week. i.e, the current week of my calculation should be from 4th Oct to 10th Oct and it is meant to reset every tuesdays.
I made this code
<?php
$refdate = strtotime(date('o-\WW'));
$tuesday = strtotime("+1 day",$refdate);
echo date("M j, Y", $tuesday) . "<br>";
?>
to
<?php
$refdate = strtotime(date('o-\WW'));
$monday = strtotime("next monday",$refdate);
echo date("M j, Y", $monday) . "<br>";
?>
But today, instead of getting 4th to 10th Oct, I am getting 11th to 17th Oct. Please someone help me. I am confused.
date function return the current week, which starts from monday (10th), and you are adding one to the date, which makes it 11th.
Next monday is simply 17th.
<?php
//default get last tuesday
$startdate = "last tuesday";
if (date('N') === '2')
{
// its Tuesday today
$startdate = "today";
}
$start_week = strtotime($startdate);
$end_week = strtotime("next monday",$start_week);
$start = date("M j, Y",$start_week);
$end = date("M j, Y",$end_week);
echo $start ."<br>";
echo $end."<br>";
?>

Get Every Tuesday of the month with Coldfusion

I'm currently working with jquery FullCalendar plugin to create a specific calendar.
One of my tasks I have to work out is how to get any given specific day for the month.
I'm currently using Coldfusion 10 for the server side so I'm wondering is there any specific way of getting every instance of a Tuesday into an array of dates?
Ideally I would like to do this on the server side and populate the calendar plugin.
My issue is primarily trying to source every specific day of a calendar month.
Any advice greatly appreciated.
The firstXDayOfMonth() UDF on CFLlib allows you to find the first of a given day-of-week in a given month. From there you just need to loop from that date adding 7 each iteration until the month is no long the selected month.
theMonth = month(now());
startDate = firstXDayOfMonth(3, theMonth, year(now()));
tuesdays = [];
for (date=startDate; month(date) == theMonth; date +=7){
arrayAppend(tuesdays, dateAdd("s",0, date)); // this just converts date from a number back to a date
}
writeDump(tuesdays);
Update:
Actually the approach for that UDF on CFLib is terrible. Use this variation instead:
function firstXDayOfMonth(dayOfWeek,month,year){
var firstOfMonth = createDate(year, month,1);
var dowOfFirst = dayOfWeek(firstOfMonth);
var daysToAdd = (7 - (dowOfFirst - dayOfWeek)) MOD 7;
var dow = dateAdd("d", daysToAdd, firstOfMonth);
return dow;
}
I'll update the UDF on cflib a bit later: I need to write some decent unit tests for it first, and am a bit busy # the moment.
The Short Version:
At this time, there is not a function in CF that gets all the Tuesdays. But here's an easy way to do it:
// assuming a year and month are defined already
var firstDayOfMonth = createDate( year, month, 1 );
var targetDayOfWeek = 3; // Tuesday is 3 if Sunday is 1
var dayOfWeekArray = []; // This is the outcome.
// loop through each day of the month adding the target days to the array.
for( i = 1; i LTE daysInMonth( firstDayOfMonth ); i++){
var loopingDate = createDate( year, month, i );
if( dayOfWeek( loopingDate ) == targetDayOfWeek ){
ArrayAppend( dayOfWeekArray, loopingDate );
}
}
dayOfWeekArray is an array of every Tuesday of a month.
More Detail:
Your title and post seem to conflict as far as what you're looking for, so I'm going to stick with the title, since that's why I came here...
Here's what you can do to find all the Tuesdays in a month:
Create a date Object
Loop through the days in the target month using the date Object
If the current day is Tuesday, add it to an array
Boom, you got all the Tuesdays of a month in an array
Here's the code I used (cfscript):
// assuming a year and month are defined already
var firstDayOfMonth = createDate( year, month, 1 );
var dayOfWeekArray = [];
var targetDayOfWeek = 3; // Tuesday is 3 if Sunday is 1. Do a quick writeDump in the loop if you're not sure.
for( i = 1; i LTE daysInMonth( firstDayOfMonth ); i++){
var loopingDate = createDate( year, month, i );
if( dayOfWeek( loopingDate ) == targetDayOfWeek ){
ArrayAppend( dayOfWeekArray, datePart( "d", loopingDate );
// ArrayAppend( dayOfWeekArray, loopingDate ); - use this if you'd rather have the whole date object
}
}
This gives you dayOfWeekArray which will be the date of each Tuesday of a particular month. For instance, this month (Jan 2019) will be [1, 8, 15, 22, 29]. You can change this to be the entire date object if you want - that's what I did in the short version at the top.

Getting The End Date of the Given Month

I need to get the end date of the given month for some calculation purpose,
how can I do that in PHP, I tried using date() function, but It didn't work.
I used this:
date($year.'-'.$month.'-t');
But this gives the current month's end date.
I think I'm wrong somewhere, I couldn't find where I'm going wrong here.
If I give year as 2012 & month as 03, then it must show me as 2012-03-31.
This code will give you last day for a specific month.
$datetocheck = "2012-03-01";
$lastday = date('t',strtotime($datetocheck));
You want to replace your date() call with:
date('Y-m-t', strtotime($year.'-'.$month.'-01'));
The first parameter to date() is the format you want to be returned, and the second parameter has to be a unix timestamp (or not passed to use the current timestamp). In your case, you can generate a timestamp with the function strtotime(), passing it a date string with the year, the month, and 01 for the day. It will return that same year and month, but the -t in the format will be replaced by the last day of the month.
If you want to return only the last day of the month without year and month:
date('t', strtotime($year.'-'.$month.'-01'));
Just use 't' as your format string.
Current month:
echo date('Y-m-t');
Any month:
echo date('Y-m-t', strtotime("$year-$month-1"));
Try below code.
$m = '03';//
$y = '2012'; //
$first_date = date('Y-m-d',mktime(0, 0, 0, $m , 1, $y));
$last_day = date('t',strtotime($first_date));
$last_date = date('Y-m-d',mktime(0, 0, 0, $m ,$last_day, $y));
function lastday($month = '', $year = '') {
if (empty($month)) {
$month = date('m');
}
if (empty($year)) {
$year = date('Y');
}
$result = strtotime("{$year}-{$month}-01");
$result = strtotime('-1 second', strtotime('+1 month', $result));
return date('Y-m-d', $result);
}
function firstOfMonth() {
return date("Y-m-d", strtotime(date('m').'/01/'.date('Y').' 00:00:00')). 'T00:00:00';}
function lastOfMonth() {
return date("Y-m-d", strtotime('-1 second',strtotime('+1 month',strtotime(date('m').'/01/'.date('Y').' 00:00:00')))). 'T23:59:59';}
$date1 = firstOfMonth();
$date2 = lastOfMonth();
try this ,this give you a current month's starting and ending date.
date("Y-m-d",strtotime("-1 day" ,strtotime("+1 month",strtotime(date("m")."-01-".date("Y")))));
function getEndDate($year, $month)
{
$day = array(1=>31,2=>28,3=>31,4=>30,5=>31,6=>30,7=>31,8=>31,9=>30,10=>31,11=>30,12=>31);
if($year%100 == 0)
{
if($year%400 == 0)
$day[$month] = 29;
}
else if($year%4 == 0)
$day[$month] = 29;
return "{$year}-{$month}-{$day[$month]}";
}
If you are using PHP >= 5.2 I strongly suggest you use the new DateTime object. For example like below:
$a_date = "2012-03-23";
$date = new DateTime($a_date);
$date->modify('last day of this month');
echo $date->format('Y-m-d');