Viewed   81 times

The DateTime class in PHP (5.3+) works just great as long as the first day of the week in your country is Sunday. In the Netherlands the first day of the week is Monday and that just makes the class useless for building a calendar with week view and calculations.

I can't seem to find an answer on Stackoverflow or the rest of the Internet on how to have DateTime act as if the first day of the week is Monday.

I found this piece on Stackoverflow, but it doesn't fix all the ways you can get into trouble and it's not an elegant solution.

$dateTime = new DateTime('2012-05-14');
$monday = clone $dateTime->modify(('Sunday' == $dateTime->format('l')) ? 'Monday last week' : 'Monday this week');

Is there a way to change this or extent DateTime? Can't imagine it's not a setting as most of Europe starts their weeks on monday.

Added: Posting the full calendar and functions code will not make things clearer. But here is one one line for example. I often have to check what the first day of the week is or calculate from the first day of the week to a different date and time in that week. My code is getting full of these:

$startOfWeek = $date->modify(('Sunday' == $date->format('l')) ? 'Monday last week' : 'Monday this week')->modify('+3 hours')->format(DATETIME);

I also get an unwanted result trying to get the first full week of the month or year. As my $date object doesn't always contain the same date I have to keep checking it this way, making the code difficult to read. Having a lot more programming to do on this calendar I can't forsee where it's going to bug again.

EDIT There are some inconsistencies though. For some strange reason DateTime does get this next one right:

$test = new DateTime('2012-10-29'); // Monday
echo $test->modify('Sunday this week')->format('Y-m-d');  // 2012-11-04

// But...

$test = new DateTime('2012-11-04'); // Sunday
echo $test->modify('Monday this week')->format('Y-m-d');  // 2012-11-05 instead of 2012-10-29   

But I think I can make the question clearer: Can the DateTime() class be used with monday as the first day of the week. If not, can the class be extended to use monday as the first day of the week.

UPDATE: Ok, I think I'm getting somewhere... I'm not a pro at coding classes..but this seems to work for the weeks. But it still needs rules for first day, second day... and also for the day name Sunday itself. I don't think this is foolproof. I would appreciate any help to fix it.

class EuroDateTime extends DateTime {

// Fields
private $weekModifiers = array (
    'this week',
    'next week',
    'previous week',
    'last week'
);

// Override "modify()"
public function modify($string) {

    // Search pattern
    $pattern = '/'.implode('|', $this->weekModifiers).'/';

    // Change the modifier string if needed
    if ( $this->format('N') == 7 ) { // It's Sunday
        $matches = array();
        if ( preg_match( $pattern, $string, $matches )) {
            $string = str_replace($matches[0], '-7 days '.$matches[0], $string);
        }
    }
    return parent::modify($string);

}

}
// This works
$test = new EuroDateTime('2012-11-04');
echo $test->modify('Monday this week')->format('Y-m-d');
// And I can still concatenate calls like the DateTime class was intended
echo $test->modify('Monday this week')->modify('+3 days')->format('Y-m-d');

 Answers

2

I found this to work, yet there are some inconsistencies in PHP's DateTime class.

If the departing date is a sunday the previous monday is not considered the same week (fixed by this class). But departing from a monday, the next sunday is considered as the same week. If they fix that in the future this class will need some additions.

class EuroDateTime extends DateTime {

// Override "modify()"
public function modify($string) {

    // Change the modifier string if needed
    if ( $this->format('N') == 7 ) { // It's Sunday and we're calculating a day using relative weeks
        $matches = array();
        $pattern = '/this week|next week|previous week|last week/i';
        if ( preg_match( $pattern, $string, $matches )) {
            $string = str_replace($matches[0], '-7 days '.$matches[0], $string);
        }
    }
    return parent::modify($string);

}

}
Thursday, December 22, 2022
5

You probably don't really want to be doing this, as it's going to be a nightmare to debug, but it seems to be possible. The key is the part where you assign by reference in the constructor.

$GLOBALS = array(
    'MyNumber' => 1
);

class Foo {
    protected $glob;

    public function __construct() {
        global $GLOBALS;
        $this->glob =& $GLOBALS;
    }

    public function getGlob() {
        return $this->glob['MyNumber'];
    }
}

$f = new Foo;

echo $f->getGlob() . "n";
$GLOBALS['MyNumber'] = 2;
echo $f->getGlob() . "n";

The output will be

1
2

which indicates that it's being assigned by reference, not value.

As I said, it will be a nightmare to debug, so you really shouldn't do this. Have a read through the wikipedia article on encapsulation; basically, your object should ideally manage its own data and the methods in which that data is modified; even public properties are generally, IMHO, a bad idea.

Friday, August 19, 2022
 
smeis
 
2

http://php.net/manual/en/datetime.formats.relative.php says that as of PHP version 5.6.23, 7.0.8 "Weeks always start on monday. Formerly, sunday would also be considered to start a week." That said, is your problem that the number of weeks returned might be incorrect depending on whether today falls on or before Thursday of the current week? Maybe try something like this:

$date = new DateTime();
$week = intval($date->format('W'));
$day = intval($date->format('N'));
echo $day < 4 ? $week-1 : $week;

If subtracting 1 isn't the answer you could play around with addition/subtraction, comparing the result with the actual answer you know to be true until you get the right formula. Hope this helps!

Sunday, October 30, 2022
 
2

You're currently in the AcmeStoreBundleRepositoryDateTime napespace. To address to the default namespace in this case you need to put leading before your classname, like

$dt = new DateTime(...);

so

namespace foo;
$obj = new class();

will try to find class definition within foo namespace.

And

namespace foo;
$obj = new class();

will try to find class definition within global namespace.

As an alternative you could import the class using

use DateTime;

or create alias (in case if you already have the class with the same name in current NS):

use DateTime as NewDT;
Sunday, August 7, 2022
2
WEEK(date[mode]); 

date = a date value.    
mode = An integer indicating the starting of the week. 

The default arugment is 0 which is sunday, setting this to 1 will be monday, 2 tuesday and so on.

week(date,1);
Sunday, September 4, 2022
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :