diff -r 1fbce408813c -r f70d764aab33 includes/functions.php --- a/includes/functions.php Tue Sep 16 08:22:47 2008 -0400 +++ b/includes/functions.php Sun Sep 21 09:01:27 2008 -0400 @@ -271,31 +271,117 @@ if ( !is_int($timestamp) && !is_double($timestamp) && strval(intval($timestamp)) !== $timestamp ) $timestamp = time(); - /* - // List of valid characters for date() - $date_chars = 'dDjlNSwzWFmMntLoYyaABgGhHisueIOPTZFcrU'; - // Split them into an array - $date_chars = enano_str_split($date_chars); - // Emulate date() formatting by replacing date characters with their - // percentage-signed counterparts, but not escaped characters which - // shouldn't be parsed. - foreach ( $date_chars as $char ) - { - $string = str_replace($char, "%$char", $string); - $string = str_replace("\\%$char", $char, $string); - } - */ - // perform timestamp offset global $timezone; // it's gonna be in minutes, so multiply by 60 to offset the unix timestamp $timestamp = $timestamp + ( $timezone * 60 ); + // are we in DST? + global $dst_params; + if ( check_timestamp_dst($timestamp, $dst_params[0], $dst_params[1], $dst_params[2], $dst_params[3]) ) + { + // offset for DST + $timestamp += ( $dst_params[4] * 60 ); + } + // Let PHP do the work for us =) return gmdate($string, $timestamp); } /** + * Determine if a timestamp is within DST. + * @param int Timestamp + * @param int Start month (1-12) of DST + * @param int Which Sunday DST starts on (*_SUNDAY constants) + * @param int End month of DST + * @param int Which Sunday DST ends on + * @return bool + */ + +function check_timestamp_dst($time, $start_month, $start_sunday, $end_month, $end_sunday) +{ + static $sundays = array(FIRST_SUNDAY, SECOND_SUNDAY, THIRD_SUNDAY, LAST_SUNDAY); + + // perform timestamp offset + global $timezone; + // it's gonna be in minutes, so multiply by 60 to offset the unix timestamp + $time = $time + ( $timezone * 60 ); + $year = intval(gmdate('Y', $time)); + + // one-pass validation + if ( !in_array($start_sunday, $sundays) || !in_array($end_sunday, $sundays) || + $start_month < 1 || $start_month > 12 || $end_month < 1 || $end_month > 12 ) + return false; + + // get timestamp of the selected sunday (start) + $dst_start = get_sunday_timestamp($start_month, $start_sunday, $year); + $dst_end = get_sunday_timestamp($end_month, $end_sunday, $year); + + if ( $dst_start > $dst_end ) + { + // start time is past the end time, this means we're in the southern hemisphere + // as a result, if we're within the range, DST is NOT in progress. + return !( $time >= $dst_start && $time <= $dst_end ); + } + + return $time >= $dst_start && $time <= $dst_end; +} + +/** + * Returns a timestamp for the given *_SUNDAY index. + * @param int Month + * @param int Which Sunday (FIRST, SECOND, THIRD, or LAST) + * @param int Year that we're doing our calculations in + * @return int + */ + +function get_sunday_timestamp($month, $sunday, $year) +{ + $days_in_month = array( + 1 => 31, + 2 => $year % 4 == 0 && ( $year % 100 != 0 || ( $year % 100 == 0 && $year % 400 == 0 ) ) ? 29 : 28, + 3 => 31, + 4 => 30, + 5 => 31, + 6 => 30, + 7 => 31, + 8 => 31, + 9 => 30, + 10 => 31, + 11 => 30, + 12 => 31 + ); + + $result = mktime(0, 0, 0, $month, 1, $year); + + // hack. allows a specific day of the month to be set instead of a sunday. not a good place to do this. + if ( is_string($sunday) && substr($sunday, -1) === 'd' ) + { + $result += 86400 * ( intval($sunday) - 1); + return $result; + } + + $tick = 0; + $days_remaining = $days_in_month[$month]; + while ( true ) + { + if ( date('D', $result) == 'Sun' ) + { + $tick++; + if ( ( $tick == 1 && $sunday == FIRST_SUNDAY ) || + ( $tick == 2 && $sunday == SECOND_SUNDAY ) || + ( $tick == 3 && $sunday == THIRD_SUNDAY ) || + ( $sunday == LAST_SUNDAY && $days_remaining < 7 ) ) + break; + } + $days_remaining--; + $result += 86400; + } + + return $result; +} + +/** * Tells you the title for the given page ID string * @param string Page ID string (ex: Special:Administration) * @param bool Optional. If true, and if the namespace turns out to be something other than Article, the namespace prefix will be prepended to the return value.