Refactor MWTimestamp::getHumanTimestamp and add hook.
Changed logic in MWTimestamp::getHumanTimestamp so that all the message and formatting was offloaded into the Language class, keeping only actual timestamp logic in the MWTimestamp class. Also added a hook so extensions can override the human timestamp format. Change-Id: Ie667088010e24eb6cb569f9e8e8e2553005223eb
This commit is contained in:
parent
af125df519
commit
7e3386d417
7 changed files with 377 additions and 58 deletions
|
|
@ -1138,6 +1138,15 @@ $title: Title object of page
|
|||
$url: string value as output (out parameter, can modify)
|
||||
$query: query options passed to Title::getFullURL()
|
||||
|
||||
'GetHumanTimestamp': Pre-emptively override the human-readable timestamp generated
|
||||
by MWTimestamp::getHumanTimestamp(). Return false in this hook to use the custom
|
||||
output.
|
||||
&$output: string for the output timestamp
|
||||
$timestamp: MWTimestamp object of the current (user-adjusted) timestamp
|
||||
$relativeTo: MWTimestamp object of the relative (user-adjusted) timestamp
|
||||
$user: User whose preferences are being used to make timestamp
|
||||
$lang: Language that will be used to render the timestamp
|
||||
|
||||
'GetInternalURL': Modify fully-qualified URLs used for squid cache purging.
|
||||
$title: Title object of page
|
||||
$url: string value as output (out parameter, can modify)
|
||||
|
|
|
|||
|
|
@ -45,26 +45,10 @@ class MWTimestamp {
|
|||
);
|
||||
|
||||
/**
|
||||
* Different units for human readable timestamps.
|
||||
* @see MWTimestamp::getHumanTimestamp
|
||||
* The actual timestamp being wrapped (DateTime object).
|
||||
* @var DateTime
|
||||
*/
|
||||
private static $units = array(
|
||||
"milliseconds" => 1,
|
||||
"seconds" => 1000, // 1000 milliseconds per second
|
||||
"minutes" => 60, // 60 seconds per minute
|
||||
"hours" => 60, // 60 minutes per hour
|
||||
"days" => 24, // 24 hours per day
|
||||
"months" => 30, // approximately 30 days per month
|
||||
"years" => 12, // 12 months per year
|
||||
);
|
||||
|
||||
/**
|
||||
* The actual timestamp being wrapped. Either a DateTime
|
||||
* object or a string with a Unix timestamp depending on
|
||||
* PHP.
|
||||
* @var string|DateTime
|
||||
*/
|
||||
private $timestamp;
|
||||
public $timestamp;
|
||||
|
||||
/**
|
||||
* Make a new timestamp and set it to the specified time,
|
||||
|
|
@ -168,16 +152,7 @@ class MWTimestamp {
|
|||
throw new TimestampException( __METHOD__ . ' : Illegal timestamp output type.' );
|
||||
}
|
||||
|
||||
if ( is_object( $this->timestamp ) ) {
|
||||
// DateTime object was used, call DateTime::format.
|
||||
$output = $this->timestamp->format( self::$formats[$style] );
|
||||
} elseif ( TS_UNIX == $style ) {
|
||||
// Unix timestamp was used and is wanted, just return it.
|
||||
$output = $this->timestamp;
|
||||
} else {
|
||||
// Unix timestamp was used, use gmdate().
|
||||
$output = gmdate( self::$formats[$style], $this->timestamp );
|
||||
}
|
||||
$output = $this->timestamp->format( self::$formats[$style] );
|
||||
|
||||
if ( ( $style == TS_RFC2822 ) || ( $style == TS_POSTGRES ) ) {
|
||||
$output .= ' GMT';
|
||||
|
|
@ -194,31 +169,105 @@ class MWTimestamp {
|
|||
* largest possible unit is used.
|
||||
*
|
||||
* @since 1.20
|
||||
* @since 1.22 Uses Language::getHumanTimestamp to produce the timestamp
|
||||
*
|
||||
* @return Message Formatted timestamp
|
||||
* @param MWTimestamp|null $relativeTo The base timestamp to compare to (defaults to now)
|
||||
* @param User|null $user User the timestamp is being generated for (or null to use main context's user)
|
||||
* @param Language|null $lang Language to use to make the human timestamp (or null to use main context's language)
|
||||
* @return string Formatted timestamp
|
||||
*/
|
||||
public function getHumanTimestamp() {
|
||||
$then = $this->getTimestamp( TS_UNIX );
|
||||
$now = time();
|
||||
$timeago = ($now - $then) * 1000;
|
||||
$message = false;
|
||||
public function getHumanTimestamp( MWTimestamp $relativeTo = null, User $user = null, Language $lang = null ) {
|
||||
if ( $relativeTo === null ) {
|
||||
$relativeTo = new self();
|
||||
}
|
||||
if ( $user === null ) {
|
||||
$user = RequestContext::getMain()->getUser();
|
||||
}
|
||||
if ( $lang === null ) {
|
||||
$lang = RequestContext::getMain()->getLanguage();
|
||||
}
|
||||
|
||||
foreach ( self::$units as $unit => $factor ) {
|
||||
$next = $timeago / $factor;
|
||||
if ( $next < 1 ) {
|
||||
break;
|
||||
// Adjust for the user's timezone.
|
||||
$offsetThis = $this->offsetForUser( $user );
|
||||
$offsetRel = $relativeTo->offsetForUser( $user );
|
||||
|
||||
$ts = '';
|
||||
if ( wfRunHooks( 'GetHumanTimestamp', array( &$ts, $this, $relativeTo, $user, $lang ) ) ) {
|
||||
$ts = $lang->getHumanTimestamp( $this, $relativeTo, $user );
|
||||
}
|
||||
|
||||
// Reset the timezone on the objects.
|
||||
$this->timestamp->sub( $offsetThis );
|
||||
$relativeTo->timestamp->sub( $offsetRel );
|
||||
|
||||
return $ts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust the timestamp depending on the given user's preferences.
|
||||
*
|
||||
* @since 1.22
|
||||
*
|
||||
* @param User $user User to take preferences from
|
||||
* @param[out] MWTimestamp $ts Timestamp to adjust
|
||||
* @return DateInterval Offset that was applied to the timestamp
|
||||
*/
|
||||
public function offsetForUser( User $user ) {
|
||||
global $wgLocalTZOffset;
|
||||
|
||||
$option = $user->getOption( 'timecorrection' );
|
||||
$data = explode( '|', $option, 3 );
|
||||
|
||||
// First handle the case of an actual timezone being specified.
|
||||
if ( $data[0] == 'ZoneInfo' ) {
|
||||
try {
|
||||
$tz = new DateTimeZone( $data[2] );
|
||||
} catch ( Exception $e ) {
|
||||
$tz = false;
|
||||
}
|
||||
|
||||
if ( $tz ) {
|
||||
$this->timestamp->setTimezone( $tz );
|
||||
return new DateInterval( 'P0Y' );
|
||||
} else {
|
||||
$timeago = $next;
|
||||
$message = array( $unit, floor( $timeago ) );
|
||||
$data[0] = 'Offset';
|
||||
}
|
||||
}
|
||||
|
||||
if ( $message ) {
|
||||
$initial = call_user_func_array( 'wfMessage', $message );
|
||||
return wfMessage( 'ago', $initial->parse() );
|
||||
$diff = 0;
|
||||
// If $option is in fact a pipe-separated value, check the
|
||||
// first value.
|
||||
if ( $data[0] == 'System' ) {
|
||||
// First value is System, so use the system offset.
|
||||
if ( isset( $wgLocalTZOffset ) ) {
|
||||
$diff = $wgLocalTZOffset;
|
||||
}
|
||||
} elseif ( $data[0] == 'Offset' ) {
|
||||
// First value is Offset, so use the specified offset
|
||||
$diff = (int)$data[1];
|
||||
} else {
|
||||
return wfMessage( 'just-now' );
|
||||
// $option actually isn't a pipe separated value, but instead
|
||||
// a comma separated value. Isn't MediaWiki fun?
|
||||
$data = explode( ':', $option );
|
||||
if ( count( $data ) >= 2 ) {
|
||||
// Combination hours and minutes.
|
||||
$diff = abs( (int)$data[0] ) * 60 + (int)$data[1];
|
||||
if ( (int) $data[0] < 0 ) {
|
||||
$diff *= -1;
|
||||
}
|
||||
} else {
|
||||
// Just hours.
|
||||
$diff = (int)$data[0] * 60;
|
||||
}
|
||||
}
|
||||
|
||||
$interval = new DateInterval('PT' . abs( $diff ) . 'M');
|
||||
if ( $diff < 1 ) {
|
||||
$interval->invert = 1;
|
||||
}
|
||||
|
||||
$this->timestamp->add( $interval );
|
||||
return $interval;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -229,6 +278,17 @@ class MWTimestamp {
|
|||
public function __toString() {
|
||||
return $this->getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the difference between two MWTimestamp objects.
|
||||
*
|
||||
* @since 1.22
|
||||
* @param MWTimestamp $relativeTo Base time to calculate difference from
|
||||
* @return DateInterval|bool The DateInterval object representing the difference between the two dates or false on failure
|
||||
*/
|
||||
public function diff( MWTimestamp $relativeTo ) {
|
||||
return $this->timestamp->diff( $relativeTo->timestamp );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1961,6 +1961,8 @@ class Language {
|
|||
* @param $type string May be date, time or both
|
||||
* @param $pref string The format name as it appears in Messages*.php
|
||||
*
|
||||
* @since 1.22 New type 'pretty' that provides a more readable timestamp format
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function getDateFormatString( $type, $pref ) {
|
||||
|
|
@ -1970,7 +1972,12 @@ class Language {
|
|||
$df = self::$dataCache->getSubitem( $this->mCode, 'dateFormats', "$pref $type" );
|
||||
} else {
|
||||
$df = self::$dataCache->getSubitem( $this->mCode, 'dateFormats', "$pref $type" );
|
||||
if ( is_null( $df ) ) {
|
||||
|
||||
if ( $type === 'pretty' && $df === null ) {
|
||||
$df = $this->getDateFormatString( 'date', $pref );
|
||||
}
|
||||
|
||||
if ( $df === null ) {
|
||||
$pref = $this->getDefaultDateFormat();
|
||||
$df = self::$dataCache->getSubitem( $this->mCode, 'dateFormats', "$pref $type" );
|
||||
}
|
||||
|
|
@ -2203,6 +2210,79 @@ class Language {
|
|||
return $this->internalUserTimeAndDate( 'both', $ts, $user, $options );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an MWTimestamp into a pretty human-readable timestamp using
|
||||
* the given user preferences and relative base time.
|
||||
*
|
||||
* DO NOT USE THIS FUNCTION DIRECTLY. Instead, call MWTimestamp::getHumanTimestamp
|
||||
* on your timestamp object, which will then call this function. Calling
|
||||
* this function directly will cause hooks to be skipped over.
|
||||
*
|
||||
* @see MWTimestamp::getHumanTimestamp
|
||||
* @param MWTimestamp $ts Timestamp to prettify
|
||||
* @param MWTimestamp $relativeTo Base timestamp
|
||||
* @param User $user User preferences to use
|
||||
* @return string Human timestamp
|
||||
* @since 1.21
|
||||
*/
|
||||
public function getHumanTimestamp( MWTimestamp $ts, MWTimestamp $relativeTo, User $user ) {
|
||||
$diff = $ts->diff( $relativeTo );
|
||||
$diffDay = (bool)( (int)$ts->timestamp->format( 'w' ) - (int)$relativeTo->timestamp->format( 'w' ) );
|
||||
$days = $diff->days ?: (int)$diffDay;
|
||||
if ( $diff->invert || $days > 5 && $ts->timestamp->format( 'Y' ) !== $relativeTo->timestamp->format( 'Y' ) ) {
|
||||
// Timestamps are in different years: use full timestamp
|
||||
// Also do full timestamp for future dates
|
||||
/**
|
||||
* @FIXME Add better handling of future timestamps.
|
||||
*/
|
||||
$format = $this->getDateFormatString( 'both', $user->getDatePreference() ?: 'default' );
|
||||
$ts = $this->sprintfDate( $format, $ts->getTimestamp( TS_MW ) );
|
||||
} elseif ( $days > 5 ) {
|
||||
// Timestamps are in same year, but more than 5 days ago: show day and month only.
|
||||
$format = $this->getDateFormatString( 'pretty', $user->getDatePreference() ?: 'default' );
|
||||
$ts = $this->sprintfDate( $format, $ts->getTimestamp( TS_MW ) );
|
||||
} elseif ( $days > 1 ) {
|
||||
// Timestamp within the past week: show the day of the week and time
|
||||
$format = $this->getDateFormatString( 'time', $user->getDatePreference() ?: 'default' );
|
||||
$weekday = self::$mWeekdayMsgs[$ts->timestamp->format( 'w' )];
|
||||
$ts = wfMessage( "$weekday-at" )
|
||||
->inLanguage( $this )
|
||||
->params( $this->sprintfDate( $format, $ts->getTimestamp( TS_MW ) ) )
|
||||
->text();
|
||||
} elseif ( $days == 1 ) {
|
||||
// Timestamp was yesterday: say 'yesterday' and the time.
|
||||
$format = $this->getDateFormatString( 'time', $user->getDatePreference() ?: 'default' );
|
||||
$ts = wfMessage( 'yesterday-at' )
|
||||
->inLanguage( $this )
|
||||
->params( $this->sprintfDate( $format, $ts->getTimestamp( TS_MW ) ) )
|
||||
->text();
|
||||
} elseif ( $diff->h > 1 || $diff->h == 1 && $diff->i > 30 ) {
|
||||
// Timestamp was today, but more than 90 minutes ago: say 'today' and the time.
|
||||
$format = $this->getDateFormatString( 'time', $user->getDatePreference() ?: 'default' );
|
||||
$ts = wfMessage( 'today-at' )
|
||||
->inLanguage( $this )
|
||||
->params( $this->sprintfDate( $format, $ts->getTimestamp( TS_MW ) ) )
|
||||
->text();
|
||||
|
||||
// From here on in, the timestamp was soon enough ago so that we can simply say
|
||||
// XX units ago, e.g., "2 hours ago" or "5 minutes ago"
|
||||
} elseif ( $diff->h == 1 ) {
|
||||
// Less than 90 minutes, but more than an hour ago.
|
||||
$ts = wfMessage( 'hours-ago' )->inLanguage( $this )->numParams( 1 )->text();
|
||||
} elseif ( $diff->i >= 1 ) {
|
||||
// A few minutes ago.
|
||||
$ts = wfMessage( 'minutes-ago' )->inLanguage( $this )->numParams( $diff->i )->text();
|
||||
} elseif ( $diff->s >= 30 ) {
|
||||
// Less than a minute, but more than 30 sec ago.
|
||||
$ts = wfMessage( 'seconds-ago' )->inLanguage( $this )->numParams( $diff->s )->text();
|
||||
} else {
|
||||
// Less than 30 seconds ago.
|
||||
$ts = wfMessage( 'just-now' )->text();
|
||||
}
|
||||
|
||||
return $ts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key string
|
||||
* @return array|null
|
||||
|
|
|
|||
|
|
@ -162,18 +162,22 @@ $dateFormats = array(
|
|||
'mdy time' => 'H:i',
|
||||
'mdy date' => 'F j, Y',
|
||||
'mdy both' => 'H:i, F j, Y',
|
||||
'mdy pretty' => 'F j',
|
||||
|
||||
'dmy time' => 'H:i',
|
||||
'dmy date' => 'j F Y',
|
||||
'dmy both' => 'H:i, j F Y',
|
||||
'dmy pretty' => 'j F',
|
||||
|
||||
'ymd time' => 'H:i',
|
||||
'ymd date' => 'Y F j',
|
||||
'ymd both' => 'H:i, Y F j',
|
||||
'ymd pretty' => 'F j',
|
||||
|
||||
'ISO 8601 time' => 'xnH:xni:xns',
|
||||
'ISO 8601 date' => 'xnY-xnm-xnd',
|
||||
'ISO 8601 both' => 'xnY-xnm-xnd"T"xnH:xni:xns',
|
||||
'ISO 8601 pretty' => 'xnm-xnd'
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
@ -3880,11 +3884,27 @@ By executing it, your system may be compromised.",
|
|||
'minutes' => '{{PLURAL:$1|$1 minute|$1 minutes}}',
|
||||
'hours' => '{{PLURAL:$1|$1 hour|$1 hours}}',
|
||||
'days' => '{{PLURAL:$1|$1 day|$1 days}}',
|
||||
'weeks' => '{{PLURAL:$1|$1 week|$1 weeks}}',
|
||||
'months' => '{{PLURAL:$1|$1 month|$1 months}}',
|
||||
'years' => '{{PLURAL:$1|$1 year|$1 years}}',
|
||||
'ago' => '$1 ago',
|
||||
'just-now' => 'just now',
|
||||
|
||||
'hours-ago' => '$1 {{PLURAL:$1|hour|hours}} ago',
|
||||
'minutes-ago' => '$1 {{PLURAL:$1|minute|minutes}} ago',
|
||||
'seconds-ago' => '$1 {{PLURAL:$1|seconds|seconds}} ago',
|
||||
|
||||
'monday-at' => 'Monday at $1',
|
||||
'tuesday-at' => 'Tuesday at $1',
|
||||
'wednesday-at' => 'Wednesday at $1',
|
||||
'thursday-at' => 'Thursday at $1',
|
||||
'friday-at' => 'Friday at $1',
|
||||
'saturday-at' => 'Saturday at $1',
|
||||
'sunday-at' => 'Sunday at $1',
|
||||
|
||||
'today-at' => '$1',
|
||||
'yesterday-at' => 'Yesterday at $1',
|
||||
|
||||
# Bad image list
|
||||
'bad_image_list' => 'The format is as follows:
|
||||
|
||||
|
|
|
|||
|
|
@ -7019,6 +7019,9 @@ See also {{msg-mw|Days-abbrev}}
|
|||
|
||||
Part of variable $1 in {{msg-mw|Ago}}
|
||||
{{Identical|Day}}',
|
||||
'weeks' => 'Full word for "weeks". $1 is the number of weeks.
|
||||
|
||||
Part of variable $1 in {{msg-mw|Ago}}',
|
||||
'months' => 'Full word for "months". $1 is the number of months.
|
||||
|
||||
Part of variable $1 in {{msg-mw|Ago}}',
|
||||
|
|
@ -7034,6 +7037,20 @@ Part of variable $1 in {{msg-mw|Ago}}',
|
|||
*{{msg-mw|Years}}',
|
||||
'just-now' => 'Phrase for indicating something happened just now.',
|
||||
|
||||
'hours-ago' => 'Phrase for indicating that something occurred a certain number of hours ago',
|
||||
'minutes-ago' => 'Phrase for indicating that something occurred a certain number of minutes ago',
|
||||
'seconds-ago' => 'Phrase for indicating that something occurred a certain number of seconds ago',
|
||||
|
||||
'monday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Monday. $1 is the time.',
|
||||
'tuesday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Tuesday. $1 is the time.',
|
||||
'wednesday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Wednesday. $1 is the time.',
|
||||
'thursday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Thursday. $1 is the time.',
|
||||
'friday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Friday. $1 is the time.',
|
||||
'saturday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Saturday. $1 is the time.',
|
||||
'sunday-at' => 'Phrase for indicating that something occurred at a particular time on the most recent Sunday. $1 is the time.',
|
||||
'today-at' => 'Phrase for indicating that something occurred at a particular time today. $1 is the time.',
|
||||
'yesterday-at' => 'Phrase for indicating that something occurred at a particular time yesterday. $1 is the time.',
|
||||
|
||||
# Bad image list
|
||||
'bad_image_list' => 'This message only appears to guide administrators to add links with the right format. This will not appear anywhere else in MediaWiki.',
|
||||
|
||||
|
|
|
|||
|
|
@ -136,6 +136,17 @@ $wgMessageStructure = array(
|
|||
'nov',
|
||||
'dec',
|
||||
),
|
||||
'human-timestamps' => array(
|
||||
'monday-at',
|
||||
'tuesday-at',
|
||||
'wednesday-at',
|
||||
'thursday-at',
|
||||
'friday-at',
|
||||
'saturday-at',
|
||||
'sunday-at',
|
||||
'today-at',
|
||||
'yesterday-at',
|
||||
),
|
||||
'categorypages' => array(
|
||||
'pagecategories',
|
||||
'pagecategorieslink',
|
||||
|
|
@ -2808,6 +2819,7 @@ $wgMessageStructure = array(
|
|||
'minutes',
|
||||
'hours',
|
||||
'days',
|
||||
'weeks',
|
||||
'months',
|
||||
'years',
|
||||
'ago',
|
||||
|
|
|
|||
|
|
@ -50,18 +50,6 @@ class TimestampTest extends MediaWikiTestCase {
|
|||
$timestamp->getTimestamp( 98 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test human readable timestamp format.
|
||||
*/
|
||||
function testHumanOutput() {
|
||||
$timestamp = new MWTimestamp( time() - 3600 );
|
||||
$this->assertEquals( "1 hour ago", $timestamp->getHumanTimestamp()->inLanguage( 'en' )->text() );
|
||||
$timestamp = new MWTimestamp( time() - 5184000 );
|
||||
$this->assertEquals( "2 months ago", $timestamp->getHumanTimestamp()->inLanguage( 'en' )->text() );
|
||||
$timestamp = new MWTimestamp( time() - 31536000 );
|
||||
$this->assertEquals( "1 year ago", $timestamp->getHumanTimestamp()->inLanguage( 'en' )->text() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of valid timestamps in the format:
|
||||
* array( type, timestamp_of_type, timestamp_in_MW )
|
||||
|
|
@ -83,4 +71,137 @@ class TimestampTest extends MediaWikiTestCase {
|
|||
array( TS_UNIX, '-62135596801', '00001231235959' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @dataProvider provideHumanTimestampTests
|
||||
*/
|
||||
public function testHumanTimestamp(
|
||||
$tsTime, // The timestamp to format
|
||||
$currentTime, // The time to consider "now"
|
||||
$timeCorrection, // The time offset to use
|
||||
$dateFormat, // The date preference to use
|
||||
$expectedOutput, // The expected output
|
||||
$desc // Description
|
||||
) {
|
||||
$user = $this->getMock( 'User' );
|
||||
$user->expects( $this->any() )
|
||||
->method( 'getOption' )
|
||||
->with( 'timecorrection' )
|
||||
->will( $this->returnValue( $timeCorrection ) );
|
||||
|
||||
$user->expects( $this->any() )
|
||||
->method( 'getDatePreference' )
|
||||
->will( $this->returnValue( $dateFormat ) );
|
||||
|
||||
$tsTime = new MWTimestamp( $tsTime );
|
||||
$currentTime = new MWTimestamp( $currentTime );
|
||||
|
||||
$this->assertEquals(
|
||||
$expectedOutput,
|
||||
$tsTime->getHumanTimestamp( $currentTime, $user ),
|
||||
$desc
|
||||
);
|
||||
}
|
||||
|
||||
public static function provideHumanTimestampTests() {
|
||||
return array(
|
||||
array(
|
||||
'20111231170000',
|
||||
'20120101000000',
|
||||
'Offset|0',
|
||||
'mdy',
|
||||
'Yesterday at 17:00',
|
||||
'"Yesterday" across years',
|
||||
),
|
||||
array(
|
||||
'20120717190900',
|
||||
'20120717190929',
|
||||
'Offset|0',
|
||||
'mdy',
|
||||
'just now',
|
||||
'"Just now"',
|
||||
),
|
||||
array(
|
||||
'20120717190900',
|
||||
'20120717191530',
|
||||
'Offset|0',
|
||||
'mdy',
|
||||
'6 minutes ago',
|
||||
'X minutes ago',
|
||||
),
|
||||
array(
|
||||
'20121006173100',
|
||||
'20121006173200',
|
||||
'Offset|0',
|
||||
'mdy',
|
||||
'1 minute ago',
|
||||
'"1 minute ago"',
|
||||
),
|
||||
array(
|
||||
'20120617190900',
|
||||
'20120717190900',
|
||||
'Offset|0',
|
||||
'mdy',
|
||||
'June 17',
|
||||
'Another month'
|
||||
),
|
||||
array(
|
||||
'19910130151500',
|
||||
'20120716193700',
|
||||
'Offset|0',
|
||||
'mdy',
|
||||
'15:15, January 30, 1991',
|
||||
'Different year',
|
||||
),
|
||||
array(
|
||||
'20120101050000',
|
||||
'20120101080000',
|
||||
'Offset|-360',
|
||||
'mdy',
|
||||
'Yesterday at 23:00',
|
||||
'"Yesterday" across years with time correction',
|
||||
),
|
||||
array(
|
||||
'20120714184300',
|
||||
'20120716184300',
|
||||
'Offset|-420',
|
||||
'mdy',
|
||||
'Saturday at 11:43',
|
||||
'Recent weekday with time correction',
|
||||
),
|
||||
array(
|
||||
'20120714184300',
|
||||
'20120715040000',
|
||||
'Offset|-420',
|
||||
'mdy',
|
||||
'11:43',
|
||||
'Today at another time with time correction',
|
||||
),
|
||||
array(
|
||||
'20120617190900',
|
||||
'20120717190900',
|
||||
'Offset|0',
|
||||
'dmy',
|
||||
'17 June',
|
||||
'Another month with dmy'
|
||||
),
|
||||
array(
|
||||
'20120617190900',
|
||||
'20120717190900',
|
||||
'Offset|0',
|
||||
'ISO 8601',
|
||||
'06-17',
|
||||
'Another month with ISO-8601'
|
||||
),
|
||||
array(
|
||||
'19910130151500',
|
||||
'20120716193700',
|
||||
'Offset|0',
|
||||
'ISO 8601',
|
||||
'1991-01-30T15:15:00',
|
||||
'Different year with ISO-8601',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue