Jump to content

Recommended Posts

Hello Freaks,

 

Currently I have this:

<div>Week:
            <input  type="text" name="weekNo" id="weekNo" placeholder="<?php echo $weekNumber = date("W"); ?>"/>
</div>

Then on form submission, the week of the year number is part of WHERE statement in my query. In results I get all entries withing this week.

 

Until now it has work great, but I have been requested to change it to calculate data not from Monday to Sunday, but from Wednesday to Tuesday.

I have probably spent 4ish hours browsing through search engines but can't find a solution.

 

Can anyone be so kind and help me with this, please?

OK, how will the first week of the year be determined and how are you going to determine how many weeks there are in a year (hint: it is not always 52)? You can't simply "shift" the results of "W" to get the right answer (well depends on what your rules are I guess).

 

The "W" format is for specifying the ISO-8601 week number. Here are the "rules" for determining the first and last week for that model

 

 

First week

The ISO 8601 definition for week 01 is the week with the Gregorian year's first Thursday in it. The following definitions based on properties of this week are mutually equivalent, since the ISO week starts with Monday:

  • It is the first week with a majority (4 or more) of its days in January.
  • Its first day is the Monday nearest to 1 January.
  • It has 4 January in it. Hence the earliest possible first week extends from Monday 29 December (previous Gregorian year) to Sunday 4 January, the latest possible first week extends from Monday 4 January to Sunday 10 January.
  • It has the year's first working day in it, if Saturdays, Sundays and 1 January are not working days.

If 1 January is on a Monday, Tuesday, Wednesday or Thursday, it is in week 01. If 1 January is on a Friday, it is part of week 53 of the previous year; if on a Saturday, it is part of week 52 (or 53 if the previous Gregorian year was a leap year); if on a Sunday, it is part of week 52 of the previous year.

Last week

The last week of the ISO week-numbering year, i.e. the 52nd or 53rd one, is the week before week 01. This week’s properties are:

  • It has the year's last Thursday in it.
  • It is the last week with a majority (4 or more) of its days in December.
  • Its middle day, Thursday, falls in the ending year.
  • Its last day is the Sunday nearest to 31 December.
  • It has 28 December in it. Hence the earliest possible last week extends from Monday 22 December to Sunday 28 December, the latest possible last week extends from Monday 28 December to Sunday 3 January (next gregorian year).

If 31 December is on a Monday, Tuesday or Wednesday, it is in week 01 of the next year. If it is on a Thursday, it is in week 53 of the year just ending; if on a Friday it is in week 52 (or 53 if the year just ending is a leap year); if on a Saturday or Sunday, it is in week 52 of the year just ending.

 

So, determine your rules for determining how you will decide the first and last week - THEN we can help write code for it.

Edited by Psycho

After four hours of searching, maybe it's time to try to solve the problem rather than continue trying to find somebody who has done it before.

 

Assuming that "W" worked perfectly for you before (because it may do unexpected things at the beginning of the year) then,

 

As documented, "W" starts on a Monday. That means Monday and Tuesday dates will be one week number ahead of where you want them to be. You could just -1 but that will cause problems for the first M/Tu of the year.

 

- If today is a Monday or Tuesday, pick the day one week earlier, otherwise use today

- Get the "W"eek number of that date

if (date("N") <= 2) { // monday or tuesday
	$date = strtotime("-1 week");
} else {
	$date = time();
}

echo date("W", $date);

- If today is a Monday or Tuesday, pick the day one week earlier, otherwise use today

- Get the "W"eek number of that date

if (date("N") <= 2) { // monday or tuesday
	$date = strtotime("-1 week");
} else {
	$date = time();
}

echo date("W", $date);

 

I think that would cause scenarios where the "first week" of the year, will be mis-calculated. Take the following example where Jan 1 starts on a Friday

 

   Mon Tue Wed Thu Fri Sat Sun
DEC  28  29  30  31  1   2   3
JAN  4   5   6   7   8   9   10  - First week

 

For a standard ISO week, the first week of the year is the one beginning on Jan 4, because it has at least four days in the current year. Using the logic above, the 4th and 5th of January would be counted as the last week of the previous year.

 

For a Wed - Tue week, the first week for that same year should begin on Dec 30th (of the prior year).

 

           Wed Thu Fri Sat Sun Mon Tue
DEC          30  31  1   2   3   4   5  - First week
JAN          6   7   8   9   10
  • Like 1

Then it's more complicated.

 

Can we get some clarification about exactly how week numbers are supposed to work? Is it ISO 8601 but using Wednesday as the start of the week, so week 1 is

- First week with 4+ days in January

- First week with the Monday Wednesday closest to Jan 1

- The one with Jan 4 in it

- The one with the first working day, not counting Saturday or Sunday (weekends) or Jan 1 (New Year's Day)

 

I suspect so, in which case you'd have to emulate the same logic. Not sure if there's an easy way that works for all days of the year, or else just do a condition on whether the day is December 29 - January 10 for the special logic and the -1 week stuff for the rest of the year.

. . .  or else just do a condition on whether the day is December 29 - January 10 for the special logic and the -1 week stuff for the rest of the year.

 

Without determining the FIRST week of the year, you cannot know the logic for determining the "week" for any other dates in the year. I've already got a solution - except it doesn't handling the "remaining" days at the end of the year that should belong to week one. Should have a complete solution shortly.

I think I could be acceptable to have an error in calculation just for one week as long as the rest of year would calculate properly. Today is Wednesday and 9th week of the year just started.

 

I could go around the problem by giving users 2 fields with pick date and then query the range. But I would like to remain with just single entry of week number as it looks neat.

This is ugly, but it works. I would likely go through and refactor make it more efficient. I'm sure it could be done in a simpler fashion, but I had to change direction multiple times. It works on the same logic as the ISO logic. For any weeks that span Dec/Jan, the week will belong to the prior year or the next year based on which year has the most days in that week (i.e. at least 4).

 

Note; There is debugging code at the bottom that shows the results for the days at the end/beginning of each year to validate the results

<?php
 
function weekNo($dateTs)
{
    //Create return variable and set initial 'year' value
    $result = array();
    $result['year'] = date('Y', $dateTs);
    //Get Jan 1 for the provided timestamp and the DOW
    $janFirst = strtotime(date("1/1/Y", $dateTs));
    $janFirstDow = date('N', $janFirst);
    //Determine first day of first week
    if($janFirstDow == 3) {
        //First day of first week is Jan 1
        $firstDayOfFirstWeek = $janFirst;
    } elseif(in_array($janFirstDow, [3,4,5,6]))    {
        //First day of first week is Wed prior to Jan 1
        $firstDayOfFirstWeek = strtotime('last Wednesday', $janFirst);
    } else {
        //First day of first week is Wed following Jan 1
        $firstDayOfFirstWeek = strtotime('next Wednesday', $janFirst);
    }
    //Calculate number of weeks since first day of first week
    $startDate = new DateTime(date('m/d/Y', $firstDayOfFirstWeek));
    $currDate  = new DateTime(date('m/d/Y', $dateTs));
    $daysDiff = $currDate->diff($startDate)->format("%a");
    //Calculate the Week NO
    $result['week'] = ceil( ($daysDiff+1) / 7);
    //Handle the first three days or last three days of the year
    //if they should fall in the adjoining year's first/last week
 
    //If selected date is Jan 1 - 3
    if(date('m', $dateTs)==1 && date('j', $dateTs)<=3)
    {
        //If Jan 1st falls on Sun/Mon/Tue AND selected date is on Sun/Mon/Tue
        if(in_array($janFirstDow, [7,1,2]) && in_array(date('N', $dateTs), [7,1,2]))
        {
            //Get year/week no for the last week of prior year
            $result = weekNo(strtotime(date("m/d/Y", $dateTs).' -3 days'));
            //Increment year & set to week 1
        }
    }
    //If selected date is Dec 29 - 31
    if(date('m', $dateTs)==12 && date('d', $dateTs)>=29)
    {
        //If 12-31 falls on Wed/Thu/Fri AND selected date is on Wed/Thu/Fri
        if(in_array(date('N', strtotime(date('12/31/Y', $dateTs))), [3,4,5])
            AND in_array(date('N', $dateTs), [3,4,5]))
        {
            //Increment year & set to week 1
            $result['year']++; $result['week'] = 1;
        }
    }
    //Return result
    return $result;
}
 
//Debugging code
echo "<pre>";
for($year=2005; $year<=2015; $year++)
{
    $startDate = "12/15/{$year}";
    $noOfDays = 30;
    echo "<h1>{$year}</h1>";
    for($day=0; $day<$noOfDays; $day++)
    {
        $timeStamp = strtotime("{$startDate} + {$day} days");
        //$isoWeek = date("W", $timeStamp);
        $weekNo = weekNo($timeStamp);
        $dow = date('N',$timeStamp);
        if( date('N',$timeStamp) == 3 ) { echo "<br>\n"; }
        echo "<b>" . date('D, m/d/Y', $timeStamp) . "</b> -- Year: {$weekNo['year']}, Week: {$weekNo['week']}\n";
        
    }
}
echo "</pre>";
?>
Edited by Psycho
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.