2

We need to determine "first week of the month". As far as I've read there's no ISO standard for this but I've encountered two definitions:

  1. First week of the month is the week that contains 1st day of the month.
  2. First week of the month is the first full week of that month.

In our application, we are frequently using the ISO week format which is like '2022-W09' that means (obviously) 9th week of 2022.

So, we can easily find first week of the year '2022-W01' and the dates it includes: from 2022-01-03 to 2022-01-09 (according to HTML5 input type week).

First week of 2022 for locale tr (Turkey)

And this shows me that (even though I liked and implemented the first definition in the first place) we should accept the second definition because HTML follows that.

As a conclusion, I need an algorithm to find "first week of the month" which I accept to be "the first full week of that month" (2nd definition).

Hereby I put the code I use to find "the week that contains 1st day of the month" which is "first week of the month" in the 1st definition above. You may modify it to suggest a solution:

public function isFirstWeekOfMonth()
{
    $carbon = Carbon::create()->setISODate(2022, 9);
    $startOfWeekCarbon = $carbon->startOfWeek();
    $endOfWeekCarbon = $carbon->endOfWeek();
    $startOfMonthCarbon = $carbon->endOfWeek()->startOfMonth();

    return $startOfMonthCarbon->betweenIncluded($startOfWeekCarbon, $endOfWeekCarbon);
}
Adem Tepe
  • 564
  • 5
  • 10
  • 1
    Take a look at this [`Carbon First Day Of The Month`](https://stackoverflow.com/questions/30614948/carbon-get-first-day-of-month) – Relcode Feb 01 '22 at 13:49

2 Answers2

2

Depending of what you consider a first day of the week, you can do it like this:

I will consider that you consider Monday as a first day of the week.

// Create a date (carbon)
$carbon = Carbon::create()->setISODate(2022, 9); 

// Find the first Monday in the month for given date. For Tuesday use 2, Wednesday 3 ... 
$firstMondayInTheMonth = $carbon->firstOfMonth(1); // This is also a start of that week

// Find the end of the week.
$endOfTheWeek = $firstMondayInTheMonth->endOfWeek();

In the image below you can see how it works in practice:

Working example.

With that, you have a first Monday in the month - which means first start of the week, and using endOfWeek you can get Sunday of that week (end of the first week). Using betweenIncluded you can figure out if one date is between that Monday and Sunday of first week in that month.

Ben
  • 2,060
  • 9
  • 21
  • This is a good solution indeed, I didn't know about Carbon firstOfMonth() function and that you can pass a day number to it. Cool. – Adem Tepe Feb 01 '22 at 14:40
2

I have updated my function according to the accepted answer:

public function isFirstWeekOfMonth()
{
    $carbon = Carbon::create()->setISODate(2022, 10);
    $startOfWeekDate = $carbon->startOfWeek()->format('Y-m-d');
    $endOfWeekDate = $carbon->endOfWeek()->format('Y-m-d');

    $firstMondayInMonth = $carbon->firstOfMonth(1);

    return $firstMondayInMonth->betweenIncluded($startOfWeekDate, $endOfWeekDate);
}

And I have tested it, it is working as expected.

For this week (2022-W09), it's false:

enter image description here

For next week (2022-W10), it's true:

enter image description here

Note: I realized that I was using betweenIncluded() function wrongly, it is accepting dates as parameters, not Carbon objects.

=== FINAL ===

I think I have made the function its best which has the simplest algorithm:

"If the first Monday of the month is equal to first date of this week, then it is the first week of the month."

public function isFirstWeekOfMonth()
{
    $currentWeekCarbon = Week::carbon($this->week);
    $startOfWeekCarbon = $currentWeekCarbon->startOfWeek();
    $firstMondayInMonthCarbon = $currentWeekCarbon->firstOfMonth(1);

    return $startOfWeekCarbon->equalTo($firstMondayInMonthCarbon);
}

Again I have tested it, it is working as expected.

Adem Tepe
  • 564
  • 5
  • 10