From 0a810a5a8757238a47fead67bddaa64380f1d53c Mon Sep 17 00:00:00 2001 From: umherirrender Date: Sat, 6 Jul 2013 21:59:35 +0200 Subject: [PATCH] Avoid date()/gmdate() for date formatting Added a MWTimestamp::format method to format a timestamp object in the given pattern. This avoids date(), which needs the local time zone corretly set on the server, which is assumed at the moment in Setup.php Added MWTimestamp::getInstance for gmdate() and MWTimestamp::getLocalInstance for date() to create a MWTimestamp object and use it as inline statement. Also MWTimestamp::setTimezone and MWTimestamp::getTimzone was added for timezone handling. Change-Id: I812aa013be2f4380e0cf10dc465202756fe8347b --- includes/Pager.php | 5 +- includes/Preferences.php | 9 ++-- includes/Timestamp.php | 61 ++++++++++++++++++++++ includes/UserMailer.php | 2 +- includes/Xml.php | 5 +- includes/actions/HistoryAction.php | 2 +- includes/db/DatabaseOracle.php | 2 +- includes/filerepo/FileRepo.php | 2 +- includes/parser/Parser.php | 60 ++++++++++----------- includes/specials/SpecialContributions.php | 2 +- includes/specials/SpecialVersion.php | 2 +- 11 files changed, 108 insertions(+), 44 deletions(-) diff --git a/includes/Pager.php b/includes/Pager.php index c7f51a3a1a..89930e2a77 100644 --- a/includes/Pager.php +++ b/includes/Pager.php @@ -872,9 +872,10 @@ abstract class ReverseChronologicalPager extends IndexPager { $year = $this->mYear; } else { // If no year given, assume the current one - $year = gmdate( 'Y' ); + $timestamp = MWTimestamp::getInstance(); + $year = $timestamp->format( 'Y' ); // If this month hasn't happened yet this year, go back to last year's month - if ( $this->mMonth > gmdate( 'n' ) ) { + if ( $this->mMonth > $timestamp->format( 'n' ) ) { $year--; } } diff --git a/includes/Preferences.php b/includes/Preferences.php index 6b5b5ebaa9..d5c0470916 100644 --- a/includes/Preferences.php +++ b/includes/Preferences.php @@ -1290,10 +1290,11 @@ class Preferences { static function getTimezoneOptions( IContextSource $context ) { $opt = array(); - global $wgLocalTZoffset, $wgLocaltimezone; - // Check that $wgLocalTZoffset is the same as $wgLocaltimezone - if ( $wgLocalTZoffset == date( 'Z' ) / 60 ) { - $server_tz_msg = $context->msg( 'timezoneuseserverdefault', $wgLocaltimezone )->text(); + global $wgLocalTZoffset; + $timestamp = MWTimestamp::getLocalInstance(); + // Check that $wgLocalTZoffset is the same as the local time zone offset + if ( $wgLocalTZoffset == $timestamp->format( 'Z' ) / 60 ) { + $server_tz_msg = $context->msg( 'timezoneuseserverdefault', $timestamp->getTimezone()->getName() )->text(); } else { $tzstring = sprintf( '%+03d:%02d', floor( $wgLocalTZoffset / 60 ), abs( $wgLocalTZoffset ) % 60 ); $server_tz_msg = $context->msg( 'timezoneuseserverdefault', $tzstring )->text(); diff --git a/includes/Timestamp.php b/includes/Timestamp.php index 5296122ef1..c77f9a4835 100644 --- a/includes/Timestamp.php +++ b/includes/Timestamp.php @@ -289,6 +289,67 @@ class MWTimestamp { public function diff( MWTimestamp $relativeTo ) { return $this->timestamp->diff( $relativeTo->timestamp ); } + + /** + * Set the timezone of this timestamp to the specified timezone. + * + * @since 1.22 + * @param String $timezone Timezone to set + * @throws TimestampException + */ + public function setTimezone( $timezone ) { + try { + $this->timestamp->setTimezone( new DateTimeZone( $timezone ) ); + } catch ( Exception $e ) { + throw new TimestampException( __METHOD__ . ' Invalid timezone.' ); + } + } + + /** + * Get the timezone of this timestamp. + * + * @since 1.22 + * @return DateTimeZone The timezone + */ + public function getTimezone() { + return $this->timestamp->getTimezone(); + } + + /** + * Format the timestamp in a given format. + * + * @since 1.22 + * @param string $format Pattern to format in + * @return string The formatted timestamp + */ + public function format( $format ) { + return $this->timestamp->format( $format ); + } + + /** + * Get a timestamp instance in the server local timezone ($wgLocaltimezone) + * + * @since 1.22 + * @param bool|string $ts Timestamp to set, or false for current time + * @return MWTimestamp the local instance + */ + public static function getLocalInstance( $ts = false ) { + global $wgLocaltimezone; + $timestamp = new self( $ts ); + $timestamp->setTimezone( $wgLocaltimezone ); + return $timestamp; + } + + /** + * Get a timestamp instance in GMT + * + * @since 1.22 + * @param bool|string $ts Timestamp to set, or false for current time + * @return MWTimestamp the instance + */ + public static function getInstance( $ts = false ) { + return new self( $ts ); + } } /** diff --git a/includes/UserMailer.php b/includes/UserMailer.php index 8e3f048dbb..049db6a63b 100644 --- a/includes/UserMailer.php +++ b/includes/UserMailer.php @@ -241,7 +241,7 @@ class UserMailer { $headers['Reply-To'] = $replyto->toString(); } - $headers['Date'] = date( 'r' ); + $headers['Date'] = MWTimestamp::getLocalInstance()->format( 'r' ); $headers['Message-ID'] = self::makeMsgId(); $headers['X-Mailer'] = 'MediaWiki mailer'; diff --git a/includes/Xml.php b/includes/Xml.php index d5501fea31..ac0539d16c 100644 --- a/includes/Xml.php +++ b/includes/Xml.php @@ -195,8 +195,9 @@ class Xml { if ( $year ) { $encYear = intval( $year ); } elseif ( $encMonth ) { - $thisMonth = intval( gmdate( 'n' ) ); - $thisYear = intval( gmdate( 'Y' ) ); + $timestamp = MWTimestamp::getInstance(); + $thisMonth = intval( $timestamp->format( 'n' ) ); + $thisYear = intval( $timestamp->format( 'Y' ) ); if ( intval( $encMonth ) > $thisMonth ) { $thisYear--; } diff --git a/includes/actions/HistoryAction.php b/includes/actions/HistoryAction.php index f43736bea5..ddcaa1026a 100644 --- a/includes/actions/HistoryAction.php +++ b/includes/actions/HistoryAction.php @@ -178,7 +178,7 @@ class HistoryAction extends FormlessAction { ) . Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) . "\n" . Html::hidden( 'action', 'history' ) . "\n" . - Xml::dateMenu( ( $year == null ? date( "Y" ) : $year ), $month ) . ' ' . + Xml::dateMenu( ( $year == null ? MWTimestamp::getLocalInstance()->format( 'Y' ) : $year ), $month ) . ' ' . ( $tagSelector ? ( implode( ' ', $tagSelector ) . ' ' ) : '' ) . $checkDeleted . Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "\n" . diff --git a/includes/db/DatabaseOracle.php b/includes/db/DatabaseOracle.php index c0d3805d58..2ccc056273 100644 --- a/includes/db/DatabaseOracle.php +++ b/includes/db/DatabaseOracle.php @@ -341,7 +341,7 @@ class DatabaseOracle extends DatabaseBase { $union_unique = ( preg_match( '/\/\* UNION_UNIQUE \*\/ /', $sql ) != 0 ); // EXPLAIN syntax in Oracle is EXPLAIN PLAN FOR and it return nothing // you have to select data from plan table after explain - $explain_id = date( 'dmYHis' ); + $explain_id = MWTimestamp::getLocalInstance()->format( 'dmYHis' ); $sql = preg_replace( '/^EXPLAIN /', 'EXPLAIN PLAN SET STATEMENT_ID = \'' . $explain_id . '\' FOR', $sql, 1, $explain_count ); diff --git a/includes/filerepo/FileRepo.php b/includes/filerepo/FileRepo.php index b82a0b8fb1..bc1ad914e0 100644 --- a/includes/filerepo/FileRepo.php +++ b/includes/filerepo/FileRepo.php @@ -965,7 +965,7 @@ class FileRepo { public function storeTemp( $originalName, $srcPath ) { $this->assertWritableRepo(); // fail out if read-only - $date = gmdate( "YmdHis" ); + $date = MWTimestamp::getInstance()->format( 'YmdHis' ); $hashPath = $this->getHashPath( $originalName ); $dstUrlRel = $hashPath . $date . '!' . rawurlencode( $originalName ); $virtualUrl = $this->getVirtualUrl( 'temp' ) . '/' . $dstUrlRel; diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php index fbde56d706..813aacad4d 100644 --- a/includes/parser/Parser.php +++ b/includes/parser/Parser.php @@ -2685,46 +2685,46 @@ class Parser { switch ( $index ) { case 'currentmonth': - $value = $pageLang->formatNum( gmdate( 'm', $ts ) ); + $value = $pageLang->formatNum( MWTimestamp::getInstance( $ts )->format( 'm' ) ); break; case 'currentmonth1': - $value = $pageLang->formatNum( gmdate( 'n', $ts ) ); + $value = $pageLang->formatNum( MWTimestamp::getInstance( $ts )->format( 'n' ) ); break; case 'currentmonthname': - $value = $pageLang->getMonthName( gmdate( 'n', $ts ) ); + $value = $pageLang->getMonthName( MWTimestamp::getInstance( $ts )->format( 'n' ) ); break; case 'currentmonthnamegen': - $value = $pageLang->getMonthNameGen( gmdate( 'n', $ts ) ); + $value = $pageLang->getMonthNameGen( MWTimestamp::getInstance( $ts )->format( 'n' ) ); break; case 'currentmonthabbrev': - $value = $pageLang->getMonthAbbreviation( gmdate( 'n', $ts ) ); + $value = $pageLang->getMonthAbbreviation( MWTimestamp::getInstance( $ts )->format( 'n' ) ); break; case 'currentday': - $value = $pageLang->formatNum( gmdate( 'j', $ts ) ); + $value = $pageLang->formatNum( MWTimestamp::getInstance( $ts )->format( 'j' ) ); break; case 'currentday2': - $value = $pageLang->formatNum( gmdate( 'd', $ts ) ); + $value = $pageLang->formatNum( MWTimestamp::getInstance( $ts )->format( 'd' ) ); break; case 'localmonth': - $value = $pageLang->formatNum( date( 'm', $ts ) ); + $value = $pageLang->formatNum( MWTimestamp::getLocalInstance( $ts )->format( 'm' ) ); break; case 'localmonth1': - $value = $pageLang->formatNum( date( 'n', $ts ) ); + $value = $pageLang->formatNum( MWTimestamp::getLocalInstance( $ts )->format( 'n' ) ); break; case 'localmonthname': - $value = $pageLang->getMonthName( date( 'n', $ts ) ); + $value = $pageLang->getMonthName( MWTimestamp::getLocalInstance( $ts )->format( 'n' ) ); break; case 'localmonthnamegen': - $value = $pageLang->getMonthNameGen( date( 'n', $ts ) ); + $value = $pageLang->getMonthNameGen( MWTimestamp::getLocalInstance( $ts )->format( 'n' ) ); break; case 'localmonthabbrev': - $value = $pageLang->getMonthAbbreviation( date( 'n', $ts ) ); + $value = $pageLang->getMonthAbbreviation( MWTimestamp::getLocalInstance( $ts )->format( 'n' ) ); break; case 'localday': - $value = $pageLang->formatNum( date( 'j', $ts ) ); + $value = $pageLang->formatNum( MWTimestamp::getLocalInstance( $ts )->format( 'j' ) ); break; case 'localday2': - $value = $pageLang->formatNum( date( 'd', $ts ) ); + $value = $pageLang->formatNum( MWTimestamp::getLocalInstance( $ts )->format( 'd' ) ); break; case 'pagename': $value = wfEscapeWikiText( $this->mTitle->getText() ); @@ -2870,44 +2870,44 @@ class Parser { $value = ( wfUrlencode( $this->mTitle->getSubjectNsText() ) ); break; case 'currentdayname': - $value = $pageLang->getWeekdayName( gmdate( 'w', $ts ) + 1 ); + $value = $pageLang->getWeekdayName( MWTimestamp::getInstance( $ts )->format( 'w' ) + 1 ); break; case 'currentyear': - $value = $pageLang->formatNum( gmdate( 'Y', $ts ), true ); + $value = $pageLang->formatNum( MWTimestamp::getInstance( $ts )->format( 'Y' ), true ); break; case 'currenttime': $value = $pageLang->time( wfTimestamp( TS_MW, $ts ), false, false ); break; case 'currenthour': - $value = $pageLang->formatNum( gmdate( 'H', $ts ), true ); + $value = $pageLang->formatNum( MWTimestamp::getInstance( $ts )->format( 'H' ), true ); break; case 'currentweek': # @bug 4594 PHP5 has it zero padded, PHP4 does not, cast to # int to remove the padding - $value = $pageLang->formatNum( (int)gmdate( 'W', $ts ) ); + $value = $pageLang->formatNum( (int)MWTimestamp::getInstance( $ts )->format( 'W' ) ); break; case 'currentdow': - $value = $pageLang->formatNum( gmdate( 'w', $ts ) ); + $value = $pageLang->formatNum( MWTimestamp::getInstance( $ts )->format( 'w' ) ); break; case 'localdayname': - $value = $pageLang->getWeekdayName( date( 'w', $ts ) + 1 ); + $value = $pageLang->getWeekdayName( MWTimestamp::getLocalInstance( $ts )->format( 'w' ) + 1 ); break; case 'localyear': - $value = $pageLang->formatNum( date( 'Y', $ts ), true ); + $value = $pageLang->formatNum( MWTimestamp::getLocalInstance( $ts )->format( 'Y' ), true ); break; case 'localtime': - $value = $pageLang->time( date( 'YmdHis', $ts ), false, false ); + $value = $pageLang->time( MWTimestamp::getLocalInstance( $ts )->format( 'YmdHis' ), false, false ); break; case 'localhour': - $value = $pageLang->formatNum( date( 'H', $ts ), true ); + $value = $pageLang->formatNum( MWTimestamp::getLocalInstance( $ts )->format( 'H' ), true ); break; case 'localweek': # @bug 4594 PHP5 has it zero padded, PHP4 does not, cast to # int to remove the padding - $value = $pageLang->formatNum( (int)date( 'W', $ts ) ); + $value = $pageLang->formatNum( (int)MWTimestamp::getLocalInstance( $ts )->format( 'W' ) ); break; case 'localdow': - $value = $pageLang->formatNum( date( 'w', $ts ) ); + $value = $pageLang->formatNum( MWTimestamp::getLocalInstance( $ts )->format( 'w' ) ); break; case 'numberofarticles': $value = $pageLang->formatNum( SiteStats::articles() ); @@ -2938,7 +2938,7 @@ class Parser { $value = wfTimestamp( TS_MW, $ts ); break; case 'localtimestamp': - $value = date( 'YmdHis', $ts ); + $value = MWTimestamp::getLocalInstance( $ts )->format( 'YmdHis' ); break; case 'currentversion': $value = SpecialVersion::getVersion(); @@ -4540,11 +4540,11 @@ class Parser { # than the one selected in each user's preferences. # (see also bug 12815) $ts = $this->mOptions->getTimestamp(); - $unixts = wfTimestamp( TS_UNIX, $ts ); - $ts = date( 'YmdHis', $unixts ); - $tzMsg = date( 'T', $unixts ); # might vary on DST changeover! + $timestamp = MWTimestamp::getLocalInstance( $ts ); + $ts = $timestamp->format( 'YmdHis' ); + $tzMsg = $timestamp->format( 'T' ); # might vary on DST changeover! - # Allow translation of timezones through wiki. date() can return + # Allow translation of timezones through wiki. format() can return # whatever crap the system uses, localised or not, so we cannot # ship premade translations. $key = 'timezone-' . strtolower( trim( $tzMsg ) ); diff --git a/includes/specials/SpecialContributions.php b/includes/specials/SpecialContributions.php index 2f37cb48db..7a3e7c80d1 100644 --- a/includes/specials/SpecialContributions.php +++ b/includes/specials/SpecialContributions.php @@ -567,7 +567,7 @@ class SpecialContributions extends SpecialPage { $dateSelectionAndSubmit = Xml::tags( 'td', array( 'colspan' => 2 ), Xml::dateMenu( - $this->opts['year'] === '' ? gmdate( 'Y' ) : $this->opts['year'], + $this->opts['year'] === '' ? MWTimestamp::getInstance()->format( 'Y' ) : $this->opts['year'], $this->opts['month'] ) . ' ' . Xml::submitButton( diff --git a/includes/specials/SpecialVersion.php b/includes/specials/SpecialVersion.php index c257dd4a4f..beb7a1ccde 100644 --- a/includes/specials/SpecialVersion.php +++ b/includes/specials/SpecialVersion.php @@ -129,7 +129,7 @@ class SpecialVersion extends SpecialPage { 'Timo Tijhof', 'Daniel Kinzler', 'Jeroen De Dauw', $othersLink ); - return wfMessage( 'version-poweredby-credits', date( 'Y' ), + return wfMessage( 'version-poweredby-credits', MWTimestamp::getLocalInstance()->format( 'Y' ), $wgLang->listToText( $authorList ) )->text(); } -- 2.20.1