Is there any DateTimePicker function to get the number of full weeks in a month?
Im looking for something like:
WeeksInMonth("01/01/2020") = 5
This will be the number of weeks per month manually calculated of this year:
Corrigendum: September has 4 weeks.
EDIT:
If the month starts in the mid of a week it should count as full week. It should also counts as full week if the month ends in the mid of a week.
From Monday to Sunday.
EDIT 2:
By mid week i mean if the week starts in Thursday it considers it as a complete week, because it was 4 days (thursday,friday,saturday and sunday) out of 7.
Same for the end, if the week end in thursday it will count as a complete Week, if the week finish in Monday, Tuesday or Wednesday it wont count because it only has 3 days out of 7.
Im taking in to consideration that my complete week starts in Monday and ends in Sunday.
Ex. January 2020 First complete week is: 30-dec-2019 to 05-jan-2020.
Another Example will be March 2020, Last complete week for me is 23-Mar-2020 to 29-Mar-2020, the 2 remaining days (30,31) would be part of April 1st complete week.
According to your logic, a week is in a month as long as its Thursday is in that month. If Thursday is in a month, then so are at least Monday, Tuesday, and Wednesday (if at the end) or Friday, Saturday, and Sunday (if at the beginning). So if you count the number of Thursdays in a month, you should get the number of weeks in that month.
Simply use LINQ to get all the days in a month, then take only days which are Thursday, then count those days
Public Function GetNumberOfWeeksInMonth(year As Integer, month As Integer) As Integer
Return Enumerable.Range(1, DateTime.DaysInMonth(year, month)).
Select(Function(d) New DateTime(year, month, d)).
Where(Function(d) d.DayOfWeek = DayOfWeek.Thursday).
Count()
End Function
' Concise version with Count with predicate
Public Function GetNumberOfWeeksInMonth(year As Integer, month As Integer) As Integer
Return Enumerable.Range(1, DateTime.DaysInMonth(year, month)).
Count(Function(d) (New DateTime(year, month, d)).DayOfWeek = DayOfWeek.Thursday)
End Function
Call it
For i = 1 To 12
Console.WriteLine($"{New DateTime(2020, i, 1):MMM}{vbTab}{GetNumberOfWeeksInMonth(2020, i)}")
Next
Jan 5
Feb 4
Mar 4
Apr 5
May 4
Jun 4
Jul 5
Aug 4
Sep 4
Oct 5
Nov 4
Dec 5
I assume this is something similar to the ISO 8601 scheme for year-weeks, where a week (a Mon-Sun period) falls into the year which contains it's Thursday.
Here a month contains a week if the Thursday of that week falls in the month.
Logically the number of such weeks in a month is the same as the number of Thursdays in that month.
You can derive this figure from the number of month-days in the month, and the week-day of the first month-day of the month.
A 28-day month always contains exactly 4 Thursdays. Months with more than 28 month-days may contain 5 Thursdays.
You can convert an ISO week-day number (Mon = 1, Sun = 7) to the following format like so: ((weekday + 2) Mod 7) - 2
Mon = 1, Tue = 2, Wed = 3, Thu = 4, Fri = -2, Sat = -1, Sun = 0
Then add this adjusted week-day figure to the number of month-days. If the result exceeds 32, then it is a month containing 5 weeks.
So a 31-day month starting on a Monday, produces a figure of 32 (31 + 1). It contains 4 weeks.
A 31-day month starting on a Tuesday, produces a figure of 33 (31 + 2). It contains 5 weeks.
A 31-day month starting on a Friday, produces a figure of 29 (31 + (-2)). It contains 4 weeks.
Hope this helps.
Related
TABLE
INSERT INTO runners
("runner_id", "registration_date")
VALUES
(1, '2021-01-01'),
(2, '2021-01-03'),
(3, '2021-01-08'),
(4, '2021-01-15');
SQL Query
SELECT
DATE_PART('WEEK', R.registration_date) AS week_num,
COUNT(runner_id)
FROM
pizza_runner.runners R
GROUP BY
week_num
ORDER BY
week_num ASC;
I was expecting the query to return weeks 1 and 2 only but for some reason I am getting 53
]1
I was expecting the query to return weeks 1 and 2 only but for some reason I am getting 53
The documentation does a good job explaining the ISO rules for weeks - which Postgres follows:
The number of the ISO 8601 week-numbering week of the year. By definition, ISO weeks start on Mondays and the first week of a year contains January 4 of that year. In other words, the first Thursday of a year is in week 1 of that year.
Using your dataset:
SELECT r.*,
extract(week from registration_date) AS week_num,
extract(isodow from registration_date) as day_of_week
FROM runners r
ORDER BY registration_date;
runner_id
registration_date
week_num
day_of_week
1
2021-01-01
53
5
2
2021-01-03
53
7
3
2021-01-08
1
5
4
2021-01-15
2
5
It turns out that January 3rd, 2021 was a Sunday (day of week 7). January 4st, 2021 was a Monday, and according to the ISO rules this is when the first week of that year began. Previous dates (January 3rd, 2nd, 1st, and so on) belong to the last week of 2020 (week 53), although the dates belong to year 2021.
I am using intnx function.
date1=intnx('qtr',"01APR2021"d,0,'b');
I am thinking of following algo-
1.Check if last month's last day is not Friday.
2.Calculate the number of days till Friday appears(Current Month).
Can anyone help me with this?
Use INTNX to compute the 1st of the month, and then WEEKDAY of that to compute the number of days in the first week.
WEEKDAY function results are
1st-want 1st_want-v2
1 Sunday 1 2
2 Monday 2 3
3 Tuesday 3 4
4 Wednesday 4 5
5 Thursday 5 6
6 Friday 6 7
7 Saturday 7 1
Depending on what you want, (suppose the 1st is a Saturday, do you want 1 or 7 for your result?) For 1, you will need to perform additional calculations.
Example:
Presume if first is a Saturday you want 7 days in first week result.
data have;
call streaminit (2021);
do _n_ = 0 to 23;
date = intnx('month', '01-jan-2019'd, _n_) + rand('integer', 27);
output;
end;
format date date11.;
run;
data want;
set have;
month_1st = intnx('month', date, 0);
sas_weekday_1st = weekday(month_1st);
result = sas_weekday_1st;
result_v2 = mod(sas_weekday_1st,7) + 1;
format month_1st date11.;
run;
Find the first of the month (INTNX() or MDY())
Find the first friday (day=6) of the month (NWKDOM())
Subtract
Assume month and year are provided.
data want;
year = 2020;
month = 1;
start_date = mdy(month, 1, year);
first_friday = nwkdwom(1, 6, month, year);
length_week = start_date - first_friday + 1;
*Toms correction:;
length_week2 = day(nwkdom(1,6,month(date),year(date));
run;
Sounds like you want to know the date of the first Friday in the month. And hence the day of the month of the first Friday in the month.
So let's start with a dataset that has a month that starts on each day of the week.
data example;
input date :date9.;
format date date9.;
dow = weekday(date);
downame=put(date,downame.-l);
cards;
01OCT2000
01MAY2000
01FEB2000
01MAR2000
01JUN2000
01SEP2000
01JAN2000
;
Now we can use the INTNX() function with the WEEK interval to find the date of the first Friday. We could then use the DAY() function to find the day of the month for that Friday and hence how many days are in the first week of the month.
To get the first Friday find the Saturday at the end of the week containing the second day of the month and subtract one to move back to Friday.
data want;
set example;
friday = intnx('week',date+1,0,'e')-1 ;
want = day(friday);
want_name=put(friday,downame.-l);
format friday date9.;
run;
Results:
Obs date dow downame friday want want_name
1 01OCT2000 1 Sunday 06OCT2000 6 Friday
2 01MAY2000 2 Monday 05MAY2000 5 Friday
3 01FEB2000 3 Tuesday 04FEB2000 4 Friday
4 01MAR2000 4 Wednesday 03MAR2000 3 Friday
5 01JUN2000 5 Thursday 02JUN2000 2 Friday
6 01SEP2000 6 Friday 01SEP2000 1 Friday
7 01JAN2000 7 Saturday 07JAN2000 7 Friday
To do it with any day in the month use the INTNX() function with MONTH interval to find the first day of the month (and add one to find the second day of the month).
length_week1=day(intnx('week',intnx('month',date,0,'b')+1,0,'e')-1);
my first post on here so please be gentle...
I'm trying to create a week number variable in Teradata (SQL) that does the following:
Week 1 always starts on 1st January of the given year
Week numbers increment on the specified day of the week
For example: If Saturday was the specified day of the week:
2019-01-01 would be the start of week 1, 2019, changing to week 2 on 2019-01-05
2020-01-01 would be the start of week 1, 2020, changing to week 2 on 2020-01-04
I have come up wit the following based on an Excel function however it doesn't quite work as expected:
ROUND(((DATE_SPECIFIED - CAST(EXTRACT(YEAR FROM DATE_SPECIFIED) || '-01-01' AS DATE) + 1) - ((DATE_SPECIFIED - DATE '0001-01-06') MOD 7 + 1) + 10) / 7) AS REQUIRED_WEEK
The last digit of the section - DATE '0001-01-06' deals with the specified day of the week, where '0001-01-01' would be Monday.
This works in some cases however for some years, the first week number is showing as 0 where it should be 1, e.g. 1st Jan 2018 / 2019 are fine whereas 1st Jan 2020 is not.
Any ideas to correct this would be gratefully received.
Many thanks,
Mike
You can apply NEXT_DAY for both the specified date and Jan 1st of that year, e.g. for Saturday as week start:
(Next_Day(DATE_SPECIFIED,'SAT') - Next_Day(Trunc(DATE_SPECIFIED,'yyyy'),'SAT')) / 7 +1
Hmmm . . . I'm a bit week on Teradata functions. But the idea is to get the start of the second week. This follows the rule:
Jan 1 weekday (TD) 2nd week
Sunday 1 01-02
Monday 2 01-08
Tuesday 3 01-07
Wednesday 4 01-06
Thursday 5 01-05
Friday 6 01-04
Saturday 7 01-03
I think the following logic calculates this:
select t.*,
(case when td_day_of_week(cast(extract(year from DATE_SPECIFIED) || '-01-01' as date) ) = 1
then cast(extract(year from DATE_SPECIFIED) + '-01-02' as date)
else extract(year from DATE_SPECIFIED) + 10 - cast(td_day_of_week(cast(extract(year from DATE_SPECIFIED) || '-01-01') as date)
from t;
Then do you your week calculate either from the second week or subtract one more week to get when the first week really starts.
Need to find weekNumber like 1,2,3,4 but the week starts with Wednesday and ends with Tuesday from date column and after the 4th week, again the week restart by again as the 1st week and so on (no need to consider month).
Need to find the Period based on weekNumber only, 4 weeks as 1 Period and Periods end with 13 (period 1-13) will restart again 1st period.
(4 weeks = 1 period) (no need to consider month).
Now need to calculate the businessyear based on Period. 13 Periods as One businessyear. (13 periods = 1 year)
Calculation logic:
7 days * 4 weeks = 28 days = 1 period
13 periods = 1 businessyear
Example:
A year has 365 days normally
In my scenario, 4 weeks * 7 days = 28 days
28 days *13 periods = 364 days
The remaining days will come as the 5th week and period 14.
Datekey date Year semistor Quarter Month DayName DayNum Wnumber
20090101 01-01-2009 2009 1 1 January 1 Thursday 1 0
20090102 02-01-2009 2009 1 1 January 1 Friday 2 0
20090103 03-01-2009 2009 1 1 January 1 Saturday 3 0
20090104 04-01-2009 2009 1 1 January 1 Sunday 0
20090105 05-01-2009 2009 1 1 January 1 Monday 0
20090106 06-01-2009 2009 1 1 January 1 Tuesday 6 0
20090107 07-01-2009 2009 1 1 January 1 Wednesday 0 0
20090108 08-01-2009 2009 1 1 January 1 Thursday 1 1
20090109 09-01-2009 2009 1 1 January 1 Friday 2 1
20090110 10-01-2009 2009 1 1 January 1 Saturday 3 1
20090111 11-01-2009 2009 1 1 January 1 Sunday 4 1
20090112 12-01-2009 2009 1 1 January 1 Monday 5 1
20090113 13-01-2009 2009 1 1 January 1 Tuesday 6 1
20090114 14-01-2009 2009 1 1 January 1 Wednesday 0 1
No need to consider the month in my scenario, need to consider leap year also (2016, 2020).
The traditional way to do this type of thing is to create a calendar table in the database. Then, your queries can simply JOIN to the calendar table to extract the relevant value.
I find that the easiest way to create the calendar table is to use Excel. Simply write some formulas that provide the desired values and Copy Down for the next decade or so. Then, save the sheet as CSV and load it into the database.
This way, you can totally avoid complex calculations involving database functions and you can use whatever rules you wish.
We do patching of servers on a 4 week cycle starting the first Tuesday of the month on today/Wednesday and Thursday and I'm looking for a way to determine what number week cycle we would be on based on the current date.
For example first week cycle which has all three days the Tuesday falls on the 5th so wed(6th) and Thursday(7th) = week 1 and so on for the 4 week cycle.
But if the first Tuesday happened to be a 1st then in the month there would be 5 sets of these days. So no patching would occur on the 5th set of these days.
So I would like something like that would output the week number or display "no patching"
If week contains (Tuesday (maxdates 1st -7th), Wednesday (maxdates 2nd-8th), Thursday (maxdates 3rd-9th) = week 1
Then if week contains (Tuesday (maxdates 8th -14th), Wednesday (maxdates 9th-15th), Thursday (maxdates 10th-16th) = week 2
Then if week contains (Tuesday (maxdates 15th -21st), Wednesday (maxdates 16th-22nd), Thursday (maxdates 17th-23rd) = week 3
Then if week contains (Tuesday (maxdates 22nd -28th), Wednesday (maxdates 23rd-29th), Thursday (maxdates 24th-30th) = week 4
Else "no patching due to take place"
But if the month didn't contain a 29th or 30th for week 4 then I would need to include the 1st and the 2nd.
This would ideally allow me to incorporate this in my daily task list without the fear of the tasks accidently showing up on a week where no patching is due to take place. The task list is pulled daily from a sql database.
declare #v datetime = getdate()
select
DATENAME(weekday,#v) weekday,
#v date,
case
when DATENAME(weekday,#v) in ('Wednesday','Thursday')
AND 1 + ((DATEPART(day,#v) / 7) * 7) > 1
AND (DATEPART(day,#v) - ((DATEPART(day,#v) / 7) * 7) between 0 and 2)
then (DATEPART(day,#v) / 7)
else 1 + DATEPART(day,#v) / 7
end week_no