mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-27 01:02:42 +01:00
Consolidate some datetime code and add unit tests
Summary: See D6115. Test Plan: - Ran unit tests. - Viewed reports. - Created a countdown. - Searched chatlog. - Searched pastes by created date. Reviewers: btrahan, chad Reviewed By: btrahan CC: aran Differential Revision: https://secure.phabricator.com/D6116
This commit is contained in:
parent
d016309def
commit
0b233e461e
8 changed files with 182 additions and 44 deletions
|
@ -1481,6 +1481,9 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorTestDataGenerator' => 'applications/lipsum/generator/PhabricatorTestDataGenerator.php',
|
'PhabricatorTestDataGenerator' => 'applications/lipsum/generator/PhabricatorTestDataGenerator.php',
|
||||||
'PhabricatorTestStorageEngine' => 'applications/files/engine/PhabricatorTestStorageEngine.php',
|
'PhabricatorTestStorageEngine' => 'applications/files/engine/PhabricatorTestStorageEngine.php',
|
||||||
'PhabricatorTestWorker' => 'infrastructure/daemon/workers/__tests__/PhabricatorTestWorker.php',
|
'PhabricatorTestWorker' => 'infrastructure/daemon/workers/__tests__/PhabricatorTestWorker.php',
|
||||||
|
'PhabricatorTime' => 'infrastructure/time/PhabricatorTime.php',
|
||||||
|
'PhabricatorTimeGuard' => 'infrastructure/time/PhabricatorTimeGuard.php',
|
||||||
|
'PhabricatorTimeTestCase' => 'infrastructure/time/__tests__/PhabricatorTimeTestCase.php',
|
||||||
'PhabricatorTimelineCursor' => 'infrastructure/daemon/timeline/storage/PhabricatorTimelineCursor.php',
|
'PhabricatorTimelineCursor' => 'infrastructure/daemon/timeline/storage/PhabricatorTimelineCursor.php',
|
||||||
'PhabricatorTimelineDAO' => 'infrastructure/daemon/timeline/storage/PhabricatorTimelineDAO.php',
|
'PhabricatorTimelineDAO' => 'infrastructure/daemon/timeline/storage/PhabricatorTimelineDAO.php',
|
||||||
'PhabricatorTimelineEvent' => 'infrastructure/daemon/timeline/storage/PhabricatorTimelineEvent.php',
|
'PhabricatorTimelineEvent' => 'infrastructure/daemon/timeline/storage/PhabricatorTimelineEvent.php',
|
||||||
|
@ -3028,7 +3031,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorOAuthUnlinkController' => 'PhabricatorAuthController',
|
'PhabricatorOAuthUnlinkController' => 'PhabricatorAuthController',
|
||||||
'PhabricatorObjectHandleStatus' => 'PhabricatorObjectHandleConstants',
|
'PhabricatorObjectHandleStatus' => 'PhabricatorObjectHandleConstants',
|
||||||
'PhabricatorObjectItemListExample' => 'PhabricatorUIExample',
|
'PhabricatorObjectItemListExample' => 'PhabricatorUIExample',
|
||||||
'PhabricatorObjectItemListView' => 'AphrontView',
|
'PhabricatorObjectItemListView' => 'AphrontTagView',
|
||||||
'PhabricatorObjectItemView' => 'AphrontTagView',
|
'PhabricatorObjectItemView' => 'AphrontTagView',
|
||||||
'PhabricatorObjectListView' => 'AphrontView',
|
'PhabricatorObjectListView' => 'AphrontView',
|
||||||
'PhabricatorObjectMailReceiver' => 'PhabricatorMailReceiver',
|
'PhabricatorObjectMailReceiver' => 'PhabricatorMailReceiver',
|
||||||
|
@ -3291,6 +3294,7 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorTestCase' => 'ArcanistPhutilTestCase',
|
'PhabricatorTestCase' => 'ArcanistPhutilTestCase',
|
||||||
'PhabricatorTestStorageEngine' => 'PhabricatorFileStorageEngine',
|
'PhabricatorTestStorageEngine' => 'PhabricatorFileStorageEngine',
|
||||||
'PhabricatorTestWorker' => 'PhabricatorWorker',
|
'PhabricatorTestWorker' => 'PhabricatorWorker',
|
||||||
|
'PhabricatorTimeTestCase' => 'PhabricatorTestCase',
|
||||||
'PhabricatorTimelineCursor' => 'PhabricatorTimelineDAO',
|
'PhabricatorTimelineCursor' => 'PhabricatorTimelineDAO',
|
||||||
'PhabricatorTimelineDAO' => 'PhabricatorLiskDAO',
|
'PhabricatorTimelineDAO' => 'PhabricatorLiskDAO',
|
||||||
'PhabricatorTimelineEvent' => 'PhabricatorTimelineDAO',
|
'PhabricatorTimelineEvent' => 'PhabricatorTimelineDAO',
|
||||||
|
|
|
@ -232,13 +232,7 @@ final class PhabricatorChatLogChannelLogController
|
||||||
);
|
);
|
||||||
|
|
||||||
} else if ($at_date) {
|
} else if ($at_date) {
|
||||||
$timezone = new DateTimeZone($user->getTimezoneIdentifier());
|
$timestamp = PhabricatorTime::parseLocalTime($at_date, $user);
|
||||||
try {
|
|
||||||
$date = new DateTime($at_date, $timezone);
|
|
||||||
$timestamp = $date->format('U');
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$timestamp = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($timestamp) {
|
if ($timestamp) {
|
||||||
$context_logs = $query
|
$context_logs = $query
|
||||||
|
|
|
@ -50,27 +50,25 @@ final class PhabricatorCountdownEditController
|
||||||
$e_text = null;
|
$e_text = null;
|
||||||
if (!strlen($title)) {
|
if (!strlen($title)) {
|
||||||
$e_text = pht('Required');
|
$e_text = pht('Required');
|
||||||
$errors[] = pht('You must give it a name.');
|
$errors[] = pht('You must give the countdown a name.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user types something like "5 PM", convert it to a timestamp
|
if (strlen($epoch)) {
|
||||||
// using their local time, not the server time.
|
$timestamp = PhabricatorTime::parseLocalTime($epoch, $user);
|
||||||
$timezone = new DateTimeZone($user->getTimezoneIdentifier());
|
if (!$timestamp) {
|
||||||
|
$errors[] = pht(
|
||||||
try {
|
'You entered an incorrect date. You can enter date '.
|
||||||
$date = new DateTime($epoch, $timezone);
|
|
||||||
$timestamp = $date->format('U');
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$errors[] = pht('You entered an incorrect date. You can enter date'.
|
|
||||||
'like \'2011-06-26 13:33:37\' to create an event at '.
|
'like \'2011-06-26 13:33:37\' to create an event at '.
|
||||||
'13:33:37 on the 26th of June 2011.');
|
'13:33:37 on the 26th of June 2011.');
|
||||||
$timestamp = null;
|
}
|
||||||
|
} else {
|
||||||
|
$e_epoch = pht('Required');
|
||||||
|
$errors[] = pht('You must specify the end date for a countdown.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!count($errors)) {
|
||||||
$countdown->setTitle($title);
|
$countdown->setTitle($title);
|
||||||
$countdown->setEpoch($timestamp);
|
$countdown->setEpoch($timestamp);
|
||||||
|
|
||||||
if (!count($errors)) {
|
|
||||||
$countdown->setAuthorPHID($user->getPHID());
|
$countdown->setAuthorPHID($user->getPHID());
|
||||||
$countdown->save();
|
$countdown->save();
|
||||||
return id(new AphrontRedirectResponse())
|
return id(new AphrontRedirectResponse())
|
||||||
|
@ -84,9 +82,7 @@ final class PhabricatorCountdownEditController
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($countdown->getEpoch()) {
|
if ($countdown->getEpoch()) {
|
||||||
$display_epoch = phabricator_datetime(
|
$display_epoch = phabricator_datetime($countdown->getEpoch(), $user);
|
||||||
$countdown->getEpoch(),
|
|
||||||
$user);
|
|
||||||
} else {
|
} else {
|
||||||
$display_epoch = $request->getStr('epoch');
|
$display_epoch = $request->getStr('epoch');
|
||||||
}
|
}
|
||||||
|
|
|
@ -709,11 +709,8 @@ final class ManiphestReportController extends ManiphestController {
|
||||||
// Do locale-aware parsing so that the user's timezone is assumed for
|
// Do locale-aware parsing so that the user's timezone is assumed for
|
||||||
// time windows like "3 PM", rather than assuming the server timezone.
|
// time windows like "3 PM", rather than assuming the server timezone.
|
||||||
|
|
||||||
$timezone = new DateTimeZone($user->getTimezoneIdentifier());
|
$window_epoch = PhabricatorTime::parseLocalTime($window_str, $user);
|
||||||
try {
|
if (!$window_epoch) {
|
||||||
$date = new DateTime($window_str, $timezone);
|
|
||||||
$window_epoch = $date->format('U');
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$error = 'Invalid';
|
$error = 'Invalid';
|
||||||
$window_epoch = time() - (60 * 60 * 24 * 7);
|
$window_epoch = time() - (60 * 60 * 24 * 7);
|
||||||
}
|
}
|
||||||
|
|
|
@ -207,18 +207,7 @@ abstract class PhabricatorApplicationSearchEngine {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
$viewer = $this->requireViewer();
|
return PhabricatorTime::parseLocalTime($date_time, $this->requireViewer());
|
||||||
|
|
||||||
$timezone = new DateTimeZone($viewer->getTimezoneIdentifier());
|
|
||||||
|
|
||||||
try {
|
|
||||||
$date = new DateTime($date_time, $timezone);
|
|
||||||
$timestamp = $date->format('U');
|
|
||||||
} catch (Exception $e) {
|
|
||||||
$timestamp = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $timestamp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
61
src/infrastructure/time/PhabricatorTime.php
Normal file
61
src/infrastructure/time/PhabricatorTime.php
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorTime {
|
||||||
|
|
||||||
|
private static $stack = array();
|
||||||
|
private static $originalZone;
|
||||||
|
|
||||||
|
public static function pushTime($epoch, $timezone) {
|
||||||
|
if (empty(self::$stack)) {
|
||||||
|
self::$originalZone = date_default_timezone_get();
|
||||||
|
}
|
||||||
|
|
||||||
|
$ok = date_default_timezone_set($timezone);
|
||||||
|
if (!$ok) {
|
||||||
|
throw new Exception("Invalid timezone '{$timezone}'!");
|
||||||
|
}
|
||||||
|
|
||||||
|
self::$stack[] = array(
|
||||||
|
'epoch' => $epoch,
|
||||||
|
'timezone' => $timezone,
|
||||||
|
);
|
||||||
|
|
||||||
|
return new PhabricatorTimeGuard(last_key(self::$stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function popTime($key) {
|
||||||
|
if ($key !== last_key(self::$stack)) {
|
||||||
|
throw new Exception("PhabricatorTime::popTime with bad key.");
|
||||||
|
}
|
||||||
|
array_pop(self::$stack);
|
||||||
|
|
||||||
|
if (empty(self::$stack)) {
|
||||||
|
date_default_timezone_set(self::$originalZone);
|
||||||
|
} else {
|
||||||
|
$frame = end(self::$stack);
|
||||||
|
date_default_timezone_set($frame['timezone']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getNow() {
|
||||||
|
if (self::$stack) {
|
||||||
|
$frame = end(self::$stack);
|
||||||
|
return $frame['epoch'];
|
||||||
|
}
|
||||||
|
return time();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function parseLocalTime($time, PhabricatorUser $user) {
|
||||||
|
$old_zone = date_default_timezone_get();
|
||||||
|
|
||||||
|
date_default_timezone_set($user->getTimezoneIdentifier());
|
||||||
|
$timestamp = (int)strtotime($time, PhabricatorTime::getNow());
|
||||||
|
if ($timestamp <= 0) {
|
||||||
|
$timestamp = null;
|
||||||
|
}
|
||||||
|
date_default_timezone_set($old_zone);
|
||||||
|
|
||||||
|
return $timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
15
src/infrastructure/time/PhabricatorTimeGuard.php
Normal file
15
src/infrastructure/time/PhabricatorTimeGuard.php
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorTimeGuard {
|
||||||
|
|
||||||
|
private $frameKey;
|
||||||
|
|
||||||
|
public function __construct($frame_key) {
|
||||||
|
$this->frameKey = $frame_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __destruct() {
|
||||||
|
PhabricatorTime::popTime($this->frameKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorTimeTestCase extends PhabricatorTestCase {
|
||||||
|
|
||||||
|
public function testPhabricatorTimeStack() {
|
||||||
|
$t = 1370202281;
|
||||||
|
$time = PhabricatorTime::pushTime($t, 'UTC');
|
||||||
|
|
||||||
|
$this->assertEqual(
|
||||||
|
true,
|
||||||
|
(PhabricatorTime::getNow() === $t));
|
||||||
|
|
||||||
|
unset($time);
|
||||||
|
|
||||||
|
$this->assertEqual(
|
||||||
|
false,
|
||||||
|
(PhabricatorTime::getNow() === $t));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testParseLocalTime() {
|
||||||
|
$u = new PhabricatorUser();
|
||||||
|
$u->setTimezoneIdentifier('UTC');
|
||||||
|
|
||||||
|
$v = new PhabricatorUser();
|
||||||
|
$v->setTimezoneIdentifier('America/Los_Angeles');
|
||||||
|
|
||||||
|
$t = 1370202281; // 2013-06-02 12:44:41 -0700
|
||||||
|
$time = PhabricatorTime::pushTime($t, 'America/Los_Angeles');
|
||||||
|
|
||||||
|
$this->assertEqual(
|
||||||
|
$t,
|
||||||
|
PhabricatorTime::parseLocalTime('now', $u));
|
||||||
|
$this->assertEqual(
|
||||||
|
$t,
|
||||||
|
PhabricatorTime::parseLocalTime('now', $v));
|
||||||
|
|
||||||
|
$this->assertEqual(
|
||||||
|
$t,
|
||||||
|
PhabricatorTime::parseLocalTime('2013-06-02 12:44:41 -0700', $u));
|
||||||
|
$this->assertEqual(
|
||||||
|
$t,
|
||||||
|
PhabricatorTime::parseLocalTime('2013-06-02 12:44:41 -0700', $v));
|
||||||
|
|
||||||
|
$this->assertEqual(
|
||||||
|
$t,
|
||||||
|
PhabricatorTime::parseLocalTime('2013-06-02 12:44:41 PDT', $u));
|
||||||
|
$this->assertEqual(
|
||||||
|
$t,
|
||||||
|
PhabricatorTime::parseLocalTime('2013-06-02 12:44:41 PDT', $v));
|
||||||
|
|
||||||
|
$this->assertEqual(
|
||||||
|
$t,
|
||||||
|
PhabricatorTime::parseLocalTime('2013-06-02 19:44:41', $u));
|
||||||
|
$this->assertEqual(
|
||||||
|
$t,
|
||||||
|
PhabricatorTime::parseLocalTime('2013-06-02 12:44:41', $v));
|
||||||
|
|
||||||
|
$this->assertEqual(
|
||||||
|
$t + 3600,
|
||||||
|
PhabricatorTime::parseLocalTime('+1 hour', $u));
|
||||||
|
$this->assertEqual(
|
||||||
|
$t + 3600,
|
||||||
|
PhabricatorTime::parseLocalTime('+1 hour', $v));
|
||||||
|
|
||||||
|
unset($time);
|
||||||
|
|
||||||
|
$t = 1370239200; // 2013-06-02 23:00:00 -0700
|
||||||
|
$time = PhabricatorTime::pushTime($t, 'America/Los_Angeles');
|
||||||
|
|
||||||
|
// For the UTC user, midnight was 6 hours ago because it's early in the
|
||||||
|
// morning for htem. For the PDT user, midnight was 23 hours ago.
|
||||||
|
$this->assertEqual(
|
||||||
|
$t + (-6 * 3600) + 60,
|
||||||
|
PhabricatorTime::parseLocalTime('12:01:00 AM', $u));
|
||||||
|
$this->assertEqual(
|
||||||
|
$t + (-23 * 3600) + 60,
|
||||||
|
PhabricatorTime::parseLocalTime('12:01:00 AM', $v));
|
||||||
|
|
||||||
|
unset($time);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue