MediaWiki  master
UserTimeCorrection.php
Go to the documentation of this file.
1 <?php
2 
23 namespace MediaWiki\User;
24 
25 use DateInterval;
26 use DateTime;
27 use DateTimeZone;
28 use Exception;
29 
42 
47  public const SYSTEM = 'System';
48 
50  public const OFFSET = 'Offset';
51 
53  public const ZONEINFO = 'ZoneInfo';
54 
55  /* @var DateTime */
56  private $date;
57 
58  /* @var bool */
59  private $valid;
60 
61  /* @var string */
62  private $correctionType;
63 
64  /* @var int Offset in minutes */
65  private $offset;
66 
67  /* @var DateTimeZone|null */
68  private $timeZone;
69 
76  public function __construct(
77  string $timeCorrection,
78  DateTime $relativeToDate = null,
79  int $offset = 0
80  ) {
81  $this->date = $relativeToDate ?? new DateTime();
82  $this->offset = $offset;
83  $this->valid = false;
84  $this->parse( $timeCorrection );
85  }
86 
92  public function getCorrectionType(): string {
93  return $this->correctionType;
94  }
95 
101  public function getTimeOffset(): int {
102  return $this->offset;
103  }
104 
110  public function getTimeOffsetInterval(): DateInterval {
111  $offset = abs( $this->offset );
112  $interval = new DateInterval( "PT{$offset}M" );
113  if ( $this->offset < 1 ) {
114  $interval->invert = 1;
115  }
116  return $interval;
117  }
118 
124  public function getTimeZone(): ?DateTimeZone {
125  return $this->timeZone;
126  }
127 
132  public function isValid(): bool {
133  return $this->valid;
134  }
135 
163  private function parse( string $timeCorrection ) {
164  $data = explode( '|', $timeCorrection, 3 );
165 
166  // First handle the case of an actual timezone being specified.
167  if ( $data[0] === self::ZONEINFO ) {
168  try {
169  $this->correctionType = self::ZONEINFO;
170  $this->timeZone = new DateTimeZone( $data[2] );
171  $this->offset = floor( $this->timeZone->getOffset( $this->date ) / 60 );
172  $this->valid = true;
173  return;
174  } catch ( Exception $e ) {
175  // Not a valid/known timezone.
176  // Fall back to any specified offset
177  }
178  }
179 
180  // If $timeCorrection is in fact a pipe-separated value, check the
181  // first value.
182  switch ( $data[0] ) {
183  case self::OFFSET:
184  case self::ZONEINFO:
185  $this->correctionType = self::OFFSET;
186  // First value is Offset, so use the specified offset
187  $this->offset = (int)( $data[1] ?? 0 );
188  // If this is ZoneInfo, then we didn't recognize the TimeZone
189  $this->valid = isset( $data[1] ) && $data[0] === self::OFFSET;
190  return;
191  case self::SYSTEM:
192  $this->correctionType = self::SYSTEM;
193  $this->valid = true;
194  return;
195  }
196 
197  // $timeCorrection actually isn't a pipe separated value, but instead
198  // a colon separated value. This is only used by the userinput of the preferences
199  // but can also still be present in the Db. (but shouldn't be)
200  $diff = 0;
201  $data = explode( ':', $timeCorrection, 2 );
202  if ( count( $data ) >= 2 ) {
203  // Combination hours and minutes.
204  $diff = abs( (int)$data[0] ) * 60 + (int)$data[1];
205  if ( (int)$data[0] < 0 ) {
206  $diff *= -1;
207  }
208  } elseif ( ctype_digit( $data[0] ) ) {
209  // Just hours.
210  $diff = (int)$data[0] * 60;
211  } else {
212  // We really don't know this. Fallback to System
213  $this->correctionType = self::SYSTEM;
214  return;
215  }
216 
217  // Max is +14:00 and min is -12:00, see:
218  // https://en.wikipedia.org/wiki/Timezone
219  if ( $diff >= -12 * 60 && $diff <= 14 * 60 ) {
220  $this->valid = true;
221  }
222  // 14:00
223  $diff = min( $diff, 14 * 60 );
224  // -12:00
225  $diff = max( $diff, -12 * 60 );
226 
227  $this->correctionType = self::OFFSET;
228  $this->offset = $diff;
229  }
230 
235  public function toString(): string {
236  switch ( $this->correctionType ) {
237  case self::ZONEINFO:
238  if ( $this->timeZone ) {
239  return "ZoneInfo|{$this->offset}|{$this->timeZone->getName()}";
240  }
241  // If not, fallback:
242  case self::SYSTEM:
243  case self::OFFSET:
244  default:
245  return "{$this->correctionType}|{$this->offset}";
246  }
247  }
248 
249  public function __toString() {
250  return $this->toString();
251  }
252 }
MediaWiki\User\UserTimeCorrection
Utility class to parse the TimeCorrection string value.
Definition: UserTimeCorrection.php:41
MediaWiki\User\UserTimeCorrection\$date
$date
Definition: UserTimeCorrection.php:52
MediaWiki\User\UserTimeCorrection\__toString
__toString()
Definition: UserTimeCorrection.php:249
MediaWiki\User\UserTimeCorrection\$valid
$valid
Definition: UserTimeCorrection.php:59
MediaWiki\User\UserTimeCorrection\parse
parse(string $timeCorrection)
Parse the timecorrection string as stored in the database for a user or as entered into the Preferenc...
Definition: UserTimeCorrection.php:163
MediaWiki\User\UserTimeCorrection\getTimeOffset
getTimeOffset()
Get corresponding time offset for this correction Note: When correcting dates/times,...
Definition: UserTimeCorrection.php:101
MediaWiki\User\UserTimeCorrection\getCorrectionType
getCorrectionType()
Get time offset for a user.
Definition: UserTimeCorrection.php:92
MediaWiki\User\UserTimeCorrection\isValid
isValid()
Was the original correction specification valid.
Definition: UserTimeCorrection.php:132
MediaWiki\User\UserTimeCorrection\getTimeZone
getTimeZone()
The time zone if known Note: When correcting dates/times, apply only the offset OR the time zone,...
Definition: UserTimeCorrection.php:124
MediaWiki\User
Definition: ActorCache.php:21
MediaWiki\User\UserTimeCorrection\$correctionType
$correctionType
Definition: UserTimeCorrection.php:62
MediaWiki\User\UserTimeCorrection\toString
toString()
Note: The string value of this object might not be equal to the original value.
Definition: UserTimeCorrection.php:235
MediaWiki\User\UserTimeCorrection\$offset
$offset
Definition: UserTimeCorrection.php:65
MediaWiki\User\UserTimeCorrection\getTimeOffsetInterval
getTimeOffsetInterval()
Get corresponding time offset for this correction Note: When correcting dates/times,...
Definition: UserTimeCorrection.php:110
MediaWiki\User\UserTimeCorrection\__construct
__construct(string $timeCorrection, DateTime $relativeToDate=null, int $offset=0)
Definition: UserTimeCorrection.php:76
MediaWiki\User\UserTimeCorrection\$timeZone
$timeZone
Definition: UserTimeCorrection.php:68