104 $monthRegexParts = [];
105 for ( $i = 1; $i <= 12; $i++ ) {
106 $monthName =
$lang->getMonthName( $i );
107 $monthAbbrev =
$lang->getMonthAbbreviation( $i );
108 $this->monthNames[$i] = $monthName;
109 $monthRegexParts[] = preg_quote( $monthName,
'/' );
110 $monthRegexParts[] = preg_quote( $monthAbbrev,
'/' );
111 $this->xMonths[mb_strtolower( $monthName )] = $i;
112 $this->xMonths[mb_strtolower( $monthAbbrev )] = $i;
117 $dm =
"(?<day>\d{1,2})[ _](?<monthName>{$monthNames})";
118 $md =
"(?<monthName>{$monthNames})[ _](?<day>\d{1,2})";
119 $y =
'(?<year>\d{1,4}([ _]BC|))';
120 $iso =
'(?<isoYear>-?\d{4})-(?<isoMonth>\d{2})-(?<isoDay>\d{2})';
123 self::DMY =>
"/^{$dm}(?: *, *| +){$y}$/iu",
124 self::YDM =>
"/^{$y}(?: *, *| +){$dm}$/iu",
125 self::MDY =>
"/^{$md}(?: *, *| +){$y}$/iu",
126 self::YMD =>
"/^{$y}(?: *, *| +){$md}$/iu",
127 self::DM =>
"/^{$dm}$/iu",
128 self::MD =>
"/^{$md}$/iu",
129 self::ISO =>
"/^{$iso}$/iu",
133 $this->targetFormats = [
134 self::DMY =>
'j F Y',
135 self::YDM =>
'Y, j F',
136 self::MDY =>
'F j, Y',
137 self::YMD =>
'Y F j',
140 self::ISO =>
'y-m-d',
151 $this->preferenceIDs = [
170 $lang =
$lang ?? MediaWikiServices::getInstance()->getContentLanguage();
171 return MediaWikiServices::getInstance()->getDateFormatterFactory()->get(
$lang );
183 public function reformat( $preference, $text, $options = [] ) {
184 if ( isset( $this->preferenceIDs[$preference] ) ) {
185 $preference = $this->preferenceIDs[$preference];
190 if ( isset( $this->rules[$preference][
$source] ) ) {
192 $target = $this->rules[$preference][
$source];
193 } elseif ( isset( $this->rules[self::ALL][
$source] ) ) {
196 } elseif ( $preference ) {
198 $target = $preference;
203 $regex = $this->regexes[
$source];
205 $text = preg_replace_callback( $regex,
206 function ( $match ) use ( $target ) {
207 $format = $this->targetFormats[$target];
212 if ( !isset( $match[
'isoYear'] ) && isset( $match[
'year'] ) ) {
213 $match[
'isoYear'] = $this->
makeIsoYear( $match[
'year'] );
215 if ( !isset( $match[
'year'] ) && isset( $match[
'isoYear'] ) ) {
219 if ( !isset( $match[
'isoMonth'] ) ) {
221 if ( $m ===
false ) {
225 $match[
'isoMonth'] = $m;
229 if ( !isset( $match[
'isoDay'] ) ) {
230 $match[
'isoDay'] = sprintf(
'%02d', $match[
'day'] );
233 $formatLength = strlen( $format );
234 for ( $p = 0; $p < $formatLength; $p++ ) {
238 $text .= $match[
'isoDay'];
241 $text .= $match[
'isoMonth'];
244 $text .= $match[
'isoYear'];
247 if ( !isset( $match[
'day'] ) ) {
248 $text .= intval( $match[
'isoDay'] );
250 $text .= $match[
'day'];
254 $m = intval( $match[
'isoMonth'] );
255 if ( $m > 12 || $m < 1 ) {
259 $text .= $this->monthNames[$m];
263 $text .= $match[
'year'];
271 if ( isset( $match[
'isoYear'] ) ) {
272 $isoBits[] = $match[
'isoYear'];
274 $isoBits[] = $match[
'isoMonth'];
275 $isoBits[] = $match[
'isoDay'];
276 $isoDate = implode(
'-', $isoBits );
279 $text = Html::rawElement(
'span',
280 [
'class' =>
'mw-formatted-date',
'title' => $isoDate ], $text );
295 $isoMonth = $this->xMonths[mb_strtolower( $monthName )] ??
false;
296 if ( $isoMonth ===
false ) {
299 return sprintf(
'%02d', $isoMonth );
309 if ( substr( $year, -2 ) ==
'BC' ) {
310 $num = intval( substr( $year, 0, -3 ) ) - 1;
312 $text = sprintf(
'-%04d', $num );
314 $text = sprintf(
'%04d', $year );
326 if ( $iso[0] ==
'-' ) {
327 $text = ( intval( substr( $iso, 1 ) ) + 1 ) .
' BC';
329 $text = intval( $iso );