Jump to content

[4.7.15] DATE form helper bug with timezones when checking min/max date


Recommended Posts

The \IPS\Helpers\Form\Date class does not account properly for a member's timezone when the min and/or max options are set.

 

This is the file's code on lines 303-314 in the validate() function:

		if ( $this->value and $this->options['min'] !== NULL and $this->options['min'] > $this->value )
		{
			$string = $this->options['min']->setTimeZone( $timezone )->localeDate( \IPS\Member::loggedIn() );
			if( $this->options['time'] )
			{
				$string .=' ' . $this->options['min']->setTimeZone( $timezone )->localeTime( \IPS\Member::loggedIn() );
			}
			throw new \LengthException( \IPS\Member::loggedIn()->language()->addToStack('form_date_min', FALSE, array( 'sprintf' => array( $string ) ) ) );
		}
		
		/* Check maximum */
		if ( $this->value and $this->options['max'] !== NULL and $this->options['max'] < $this->value )
		{
			$string = $this->options['max']->setTimeZone( $timezone )->localeDate( \IPS\Member::loggedIn() );
			if( $this->options['time'] )
			{
				$string .=' ' . $this->options['max']->setTimeZone( $timezone )->localeTime( \IPS\Member::loggedIn() );
			}
			throw new \LengthException( \IPS\Member::loggedIn()->language()->addToStack('form_date_max', FALSE, array( 'sprintf' => array( $string ) ) ) );
		}

 

The code doesn't account at all for the timezone when checking the min/max values against the entered value:

$this->options['min'] > $this->value

$this->options['max'] < $this->value

The timezone is added only inside the IF check to display the error, but not before it for the check:

$string = $this->options['min']->setTimeZone( $timezone )->localeDate( \IPS\Member::loggedIn() );

$string = $this->options['max']->setTimeZone( $timezone )->localeDate( \IPS\Member::loggedIn() );

 

This causes the check to fail for a user close to the UTC timezone, while it passes for a user with a more distant timezone.

 

Here is an example with 2 different timezones (Rome & New York):

DEBUG CODE:
==================================================
print_r( $this->value );
print_r( $this->options['min'] );
print_r( $this->options['min']->setTimeZone( $timezone ) );
var_dump( $this->options['min'] > $this->value );
exit;
==================================================

OUTPUT FOR ROME TIMEZONE:
==================================================
IPS\DateTime Object
(
    [date] => 2024-03-02 00:01:00.000000
    [timezone_type] => 3
    [timezone] => Europe/Rome
)
IPS\DateTime Object
(
    [date] => 2024-03-02 00:58:41.440303
    [timezone_type] => 3
    [timezone] => UTC
)
IPS\DateTime Object
(
    [date] => 2024-03-02 01:58:41.440303
    [timezone_type] => 3
    [timezone] => Europe/Rome
)

bool(true)
==================================================

OUTPUT FOR NEW YORK TIMEZONE:
==================================================
IPS\DateTime Object
(
    [date] => 2024-03-02 02:41:00.000000
    [timezone_type] => 3
    [timezone] => America/New_York
)

IPS\DateTime Object
(
    [date] => 2024-03-02 00:52:00.648474
    [timezone_type] => 3
    [timezone] => UTC
)
IPS\DateTime Object
(
    [date] => 2024-03-01 19:52:00.648474
    [timezone_type] => 3
    [timezone] => America/New_York
)

bool(false)

 

As you can see from the debug output above, the member with a Rome timezone fails to pass the check (TRUE triggers the error), while the New York timezone passes the check (FALSE doesn't trigger the error).

 

The timezone must be added to the min/max checks before the check is done, and not after to display only the error.

Edited by teraßyte
Link to comment
Share on other sites

Thank you for bringing this issue to our attention! I can confirm this should be further reviewed and I have logged an internal bug report for our development team to investigate and address as necessary, in a future maintenance release.

 

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...