Last modified: 2007-06-27 04:15:29 UTC
I've fixed some bugs in the regex for parsing/replacing dates, and also added a user preference and associated rewrite code to handle BC vs. BCE era naming. This should make a long-standing debate about whether to use BC or BCE in dates go away entirely, since users can decide for themselves. diff -ru --exclude=.svn phase3/includes/DateFormatter.php phase3.new/includes/DateFormatter.php --- phase3/includes/DateFormatter.php Mon Sep 4 21:07:04 2006 +++ phase3.new/includes/DateFormatter.php Mon Sep 4 21:03:26 2006 @@ -49,9 +49,9 @@ # Partial regular expressions $this->prxDM = '\[\[(\d{1,2})[ _](' . $this->monthNames . ')]]'; $this->prxMD = '\[\[(' . $this->monthNames . ')[ _](\d{1,2})]]'; - $this->prxY = '\[\[(\d{1,4}([ _]BC|))]]'; - $this->prxISO1 = '\[\[(-?\d{4})]]-\[\[(\d{2})-(\d{2})]]'; - $this->prxISO2 = '\[\[(-?\d{4})-(\d{2})-(\d{2})]]'; + $this->prxY = '\[\[(\d{1,4}([ _]BCE?|))]]'; + $this->prxISO1 = '\[\[(-?\d{1,4})]]-\[\[(\d{2})-(\d{2})]]'; + $this->prxISO2 = '\[\[(-?\d{1,4})-(\d{2})-(\d{2})]]'; # Real regular expressions $this->regexes[self::DMY] = "/{$this->prxDM} *,? *{$this->prxY}{$this->regexTrail}"; @@ -121,12 +121,13 @@ * @param string $preference User preference * @param string $text Text to reformat */ - function reformat( $preference, $text ) { + function reformat( $preference, $eraPreference, $text ) { if ( isset( $this->preferences[$preference] ) ) { $preference = $this->preferences[$preference]; } else { $preference = self::NONE; } + $this->eraPreference = $eraPreference; for ( $i=1; $i<=self::LAST; $i++ ) { $this->mSource = $i; if ( @$this->rules[$preference][$i] ) { @@ -219,7 +220,13 @@ if ( !isset( $bits['Y'] ) ) { $text .= $this->makeNormalYear( $bits['y'] ); } else { - $text .= $bits['Y']; + if ( $this->eraPreference == 'BCE' ) { + $text .= preg_replace( '/BC$/', 'BCE', $bits['Y']); + } elseif ( $this->eraPreference == 'BC' ) { + $text .= preg_replace( '/BCE$/', 'BC', $bits['Y']); + } else { + $text .= $bits['Y']; + } } break; default: @@ -264,7 +271,11 @@ */ function makeIsoYear( $year ) { # Assumes the year is in a nice format, as enforced by the regex - if ( substr( $year, -2 ) == 'BC' ) { + if ( substr( $year, -3 ) == 'BCE' ) { + $num = intval(substr( $year, 0, -4 )) - 1; + # PHP bug note: sprintf( "%04d", -1 ) fails poorly + $text = sprintf( '-%04d', $num ); + } elseif ( substr( $year, -2 ) == 'BC' ) { $num = intval(substr( $year, 0, -3 )) - 1; # PHP bug note: sprintf( "%04d", -1 ) fails poorly $text = sprintf( '-%04d', $num ); @@ -280,7 +291,11 @@ */ function makeNormalYear( $iso ) { if ( $iso{0} == '-' ) { - $text = (intval( substr( $iso, 1 ) ) + 1) . ' BC'; + if ( $this->eraPreference == 'BCE' ) { + $text = (intval( substr( $iso, 1 ) ) + 1) . ' BCE'; + } else { + $text = (intval( substr( $iso, 1 ) ) + 1) . ' BC'; + } } else { $text = intval( $iso ); } diff -ru --exclude=.svn phase3/includes/Parser.php phase3.new/includes/Parser.php --- phase3/includes/Parser.php Mon Sep 4 21:07:04 2006 +++ phase3.new/includes/Parser.php Mon Sep 4 20:28:24 2006 @@ -961,7 +961,7 @@ $text = $this->doHeadings( $text ); if($this->mOptions->getUseDynamicDates()) { $df =& DateFormatter::getInstance(); - $text = $df->reformat( $this->mOptions->getDateFormat(), $text ); + $text = $df->reformat( $this->mOptions->getDateFormat(), $this->mOptions->getEraFormat(), $text ); } $text = $this->doAllQuotes( $text ); $text = $this->replaceInternalLinks( $text ); @@ -4613,6 +4613,13 @@ $this->mDateFormat = $this->mUser->getDatePreference(); } return $this->mDateFormat; + } + + function getEraFormat() { + if ( !isset( $this->mEraFormat ) ) { + $this->mEraFormat = $this->mUser->getEraPreference(); + } + return $this->mEraFormat; } function setUseTeX( $x ) { return wfSetVar( $this->mUseTeX, $x ); } diff -ru --exclude=.svn phase3/includes/SpecialPreferences.php phase3.new/includes/SpecialPreferences.php --- phase3/includes/SpecialPreferences.php Mon Sep 4 21:07:05 2006 +++ phase3.new/includes/SpecialPreferences.php Mon Sep 4 20:14:50 2006 @@ -23,7 +23,7 @@ */ class PreferencesForm { var $mQuickbar, $mOldpass, $mNewpass, $mRetypePass, $mStubs; - var $mRows, $mCols, $mSkin, $mMath, $mDate, $mUserEmail, $mEmailFlag, $mNick; + var $mRows, $mCols, $mSkin, $mMath, $mDate, $mEra, $mUserEmail, $mEmailFlag, $mNick; var $mUserLanguage, $mUserVariant; var $mSearch, $mRecent, $mHourDiff, $mSearchLines, $mSearchChars, $mAction; var $mReset, $mPosted, $mToggles, $mSearchNs, $mRealName, $mImageSize; @@ -46,6 +46,7 @@ $this->mSkin = $request->getVal( 'wpSkin' ); $this->mMath = $request->getVal( 'wpMath' ); $this->mDate = $request->getVal( 'wpDate' ); + $this->mEra = $request->getVal( 'wpEra' ); $this->mUserEmail = $request->getVal( 'wpUserEmail' ); $this->mRealName = $wgAllowRealName ? $request->getVal( 'wpRealName' ) : ''; $this->mEmailFlag = $request->getCheck( 'wpEmailFlag' ) ? 0 : 1; @@ -169,6 +170,21 @@ } /** + * @access private + */ + function validateEra( $val ) { + global $wgLang, $wgContLang; + if ( $val !== false && ( + in_array( $val, (array)$wgLang->getEraPreferences() ) || + in_array( $val, (array)$wgContLang->getEraPreferences() ) ) ) + { + return $val; + } else { + return $wgLang->getDefaultEraFormat(); + } + } + + /** * Used to validate the user inputed timezone before saving it as * 'timeciorrection', will return '00:00' if fed bogus data. * Note: It's not a 100% correct implementation timezone-wise, it will @@ -263,6 +279,7 @@ $wgUser->setOption( 'math', $this->mMath ); } $wgUser->setOption( 'date', $this->validateDate( $this->mDate ) ); + $wgUser->setOption( 'era', $this->validateEra( $this->mEra ) ); $wgUser->setOption( 'searchlimit', $this->validateIntOrNull( $this->mSearch ) ); $wgUser->setOption( 'contextlines', $this->validateIntOrNull( $this->mSearchLines ) ); $wgUser->setOption( 'contextchars', $this->validateIntOrNull( $this->mSearchChars ) ); @@ -362,6 +379,7 @@ $this->mSkin = Skin::normalizeKey( $wgUser->getOption( 'skin' ) ); $this->mMath = $wgUser->getOption( 'math' ); $this->mDate = $wgUser->getDatePreference(); + $this->mEra = $wgUser->getEraPreference(); $this->mRows = $wgUser->getOption( 'rows' ); $this->mCols = $wgUser->getOption( 'cols' ); $this->mStubs = $wgUser->getOption( 'stubthreshold' ); @@ -476,6 +494,7 @@ $skinNames = $wgLang->getSkinNames(); $mathopts = $wgLang->getMathNames(); $dateopts = $wgLang->getDatePreferences(); + $eraopts = $wgLang->getEraPreferences(); $togs = User::getToggles(); $titleObj = Title::makeTitle( NS_SPECIAL, 'Preferences' ); @@ -805,6 +824,19 @@ $wgOut->addHTML( "</fieldset>\n" ); } + if ($eraopts) { + $wgOut->addHTML( "<fieldset>\n<legend>" . wfMsg( 'eraformat' ) . "</legend>\n" ); + $idCnt = 0; + foreach( $eraopts as $key ) { + $formatted = wfMsgHtml( 'era'.$key ); + ($key == $this->mEra) ? $checked = ' checked="checked"' : $checked = ''; + $wgOut->addHTML( "<div><input type='radio' name=\"wpEra\" id=\"wpEra$idCnt\" ". + "value=\"$key\"$checked /> <label for=\"wpEra$idCnt\">$formatted</label></div>\n" ); + $idCnt++; + } + $wgOut->addHTML( "</fieldset>\n" ); + } + $nowlocal = $wgLang->time( $now = wfTimestampNow(), true ); $nowserver = $wgLang->time( $now, false ); @@ -820,6 +852,7 @@ </td></tr></table></fieldset> <div class='prefsectiontip'>¹" . wfMsg( 'timezonetext' ) . "</div> </fieldset>\n\n" ); + # Editing # diff -ru --exclude=.svn phase3/includes/User.php phase3.new/includes/User.php --- phase3/includes/User.php Mon Sep 4 21:07:04 2006 +++ phase3.new/includes/User.php Mon Sep 4 20:13:47 2006 @@ -1174,6 +1174,18 @@ } /** + * Get the user's era names preference. + */ + function getEraPreference() { + if ( is_null( $this->mEraPreference ) ) { + global $wgLang; + $value = $this->getOption( 'era' ); + $this->mEraPreference = $value; + } + return $this->mEraPreference; + } + + /** * @param string $oname The option to check * @return bool False if the option is not selected, true if it is */ diff -ru --exclude=.svn phase3/languages/Language.php phase3.new/languages/Language.php --- phase3/languages/Language.php Mon Sep 4 21:07:24 2006 +++ phase3.new/languages/Language.php Mon Sep 4 20:01:35 2006 @@ -67,7 +67,7 @@ 'separatorTransformTable', 'fallback8bitEncoding', 'linkPrefixExtension', 'defaultUserOptionOverrides', 'linkTrail', 'namespaceAliases', 'dateFormats', 'datePreferences', 'datePreferenceMigrationMap', - 'defaultDateFormat', 'extraUserToggles' ); + 'defaultDateFormat', 'eraPreferences', 'extraUserToggles' ); static public $mMergeableMapKeys = array( 'messages', 'namespaceNames', 'mathNames', 'dateFormats', 'defaultUserOptionOverrides', 'magicWords' ); @@ -269,6 +269,11 @@ function getDatePreferences() { $this->load(); return $this->datePreferences; + } + + function getEraPreferences() { + $this->load(); + return $this->eraPreferences; } function getDateFormats() { diff -ru --exclude=.svn phase3/languages/MessagesEn.php phase3.new/languages/MessagesEn.php --- phase3/languages/MessagesEn.php Mon Sep 4 21:07:24 2006 +++ phase3.new/languages/MessagesEn.php Mon Sep 4 21:05:23 2006 @@ -179,6 +179,17 @@ 'ISO 8601 both' => 'xnY-xnm-xnd"T"xnH:xni:xns', ); +/** + * A list of era naming preference keys which can be selected in user + * preferences. + * + */ +$eraPreferences = array( + 'default', + 'BC', + 'BCE', +); + $bookstoreList = array( 'AddALL' => 'http://www.addall.com/New/Partner.cgi?query=$1&type=ISBN', 'PriceSCAN' => 'http://www.pricescan.com/books/bookDetail.asp?isbn=$1', @@ -1007,6 +1018,10 @@ 'dateformat' => 'Date format', 'datedefault' => 'No preference', 'datetime' => 'Date and time', +'eraformat' => 'Era Names', +'eradefault' => 'No Preference', +'eraBC' => 'AD/BC', +'eraBCE' => 'CE/BCE', 'math_failure' => 'Failed to parse', 'math_unknown_error' => 'unknown error', 'math_unknown_function' => 'unknown function',
Created attachment 2318 [details] patch to add BC/BCE preferences
It's been suggested that AD/CE also be handled, in addition to BC/BCE. One problem with this is that AD/CE only appear in the right (display) half of a wikilink, e.g.: ... something ancient lasted from [[10 BC]]–[[30|AD 30]] ... Currently, none of the regexes rewrite anything in the display portion of a wikilinked date, and I'm not sure it's a good idea to start. It doesn't seem right to rewrite text that an editor explicitly set to be displayed. The best alternative (short of ignoring AD/CE altogether) might be to change the style guide so that dates are specified in the article title as including AD (or CE). This would be a HUGE change and probably wouldn't go over too well, even though it does make sense upon reflection (why SHOULDN'T [[1995]] be an article about the number, and [[1995 AD]] about the date?)
*** This bug has been marked as a duplicate of bug 5089 ***