使用PHP查找每月的第n个X天,它总是正确的吗?

OK, I've put together some code which, in this particular case, finds the second (2nd) Sunday of every month depending on whether or not you're before or after it (specifically at 5:00PM that day).

<?php
    $count = 0;
    for( $i = 1 ; $i <=30 ; $i++ )//30 is much more than is needed
    {
        $date = date_create_from_format('Y-m-d H:i:s',date('Y-m-').$i.' 17:00:00');
        if( $date->format('D') == 'Sun' )
        {
            $count++;
        }
        if( $count == 2 )
        {
            break;
        }
    }
    $count = 0;
    if( date('Y-m-d H:i:s') > $date->format('Y-m-d H:i:s') )
    {
        for( $i = 1 ; $i <=30 ; $i++ )
        {
            $date = date_create_from_format('Y-m-d H:i:s',date('Y-').(string)(((int)date('n')+1)%12).'-'.$i.' 17:00:00');
            if( $date->format('D') == 'Sun' )
            {
                $count++;
            }
            if( $count == 2 )
            {
                break;
            }
        }
        echo $date->format('F jS, Y');
    }
    else
    {
        echo $date->format('F jS, Y');
    }
?>

So if you are at the green star it will display August 14, and if you're at the blue star it will display September 11:

enter image description here

My question is will this always be correct indefinitely?

Using DateTime class:

$date = new DateTime( 'second sunday of this month, 17:00' );
if( date_create()->diff( $date )->invert )
{
    $date = new DateTime( 'second sunday of next month, 17:00' );
}

To retrieve second sunday of this month... just pass “second sunday of this month” to DateTime, then, if the date is in the past (DateInterval->invert return 1 if the interval is negative, 0 otherwise), you can retrieve second sunday of next month.

The code seems all right. But you don't even need to use all the string comparison and loops. Just pass an argument like "Second Sunday of 2016-04, 17:00" to strtotime() and then check whether the date has passed or not.

Strtotime() takes care of all the exceptional situations like leap-year, next month being Janury of the next year, etc.

$currentMonthSecondSunday = date( 'Y-m-d H:i:s', strtotime( 'Second Sunday of ' . date( 'Y-m' ) . ', 17:00' ) );
$currentDate = date( 'Y-m-d H:i:s' );
if ( $currentDate < $currentMonthSecondSunday ) {
    echo $currentMonthSecondSunday;
} else {
    $nextMonthSecondSunday = date( 'Y-m-d H:i:s', strtotime( 'Second Sunday of ' . date( 'Y-m', strtotime( 'next month' ) ) . ', 17:00' ) );
    echo $nextMonthSecondSunday;
}