1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-09-20 09:18:48 +02: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:
epriestley 2013-06-03 12:58:11 -07:00
parent d016309def
commit 0b233e461e
8 changed files with 182 additions and 44 deletions

View file

@ -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',

View file

@ -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

View file

@ -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); 'like \'2011-06-26 13:33:37\' to create an event at '.
$timestamp = $date->format('U'); '13:33:37 on the 26th of June 2011.');
} catch (Exception $e) { }
$errors[] = pht('You entered an incorrect date. You can enter date'. } else {
' like \'2011-06-26 13:33:37\' to create an event at'. $e_epoch = pht('Required');
' 13:33:37 on the 26th of June 2011.'); $errors[] = pht('You must specify the end date for a countdown.');
$timestamp = null;
} }
$countdown->setTitle($title);
$countdown->setEpoch($timestamp);
if (!count($errors)) { if (!count($errors)) {
$countdown->setTitle($title);
$countdown->setEpoch($timestamp);
$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');
} }

View file

@ -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);
} }

View file

@ -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;
} }

View 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;
}
}

View 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);
}
}

View file

@ -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);
}
}