Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15629821
D16664.id40148.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
15 KB
Referenced Files
None
Subscribers
None
D16664.id40148.diff
View Options
diff --git a/resources/sql/autopatches/20160715.event.03.allday.php b/resources/sql/autopatches/20160715.event.03.allday.php
--- a/resources/sql/autopatches/20160715.event.03.allday.php
+++ b/resources/sql/autopatches/20160715.event.03.allday.php
@@ -1,52 +1,3 @@
<?php
-$table = new PhabricatorCalendarEvent();
-$conn = $table->establishConnection('w');
-
-// Previously, "All Day" events were stored with a start and end date set to
-// the earliest possible start and end seconds for the corresponding days. We
-// now store all day events with their "date" epochs as UTC, separate from
-// individual event times.
-$zone_min = new DateTimeZone('Pacific/Midway');
-$zone_max = new DateTimeZone('Pacific/Kiritimati');
-$zone_utc = new DateTimeZone('UTC');
-
-foreach (new LiskMigrationIterator($table) as $event) {
- // If this event has already migrated, skip it.
- if ($event->getAllDayDateFrom()) {
- continue;
- }
-
- $is_all_day = $event->getIsAllDay();
-
- $epoch_min = $event->getDateFrom();
- $epoch_max = $event->getDateTo();
-
- $date_min = new DateTime('@'.$epoch_min);
- $date_max = new DateTime('@'.$epoch_max);
-
- if ($is_all_day) {
- $date_min->setTimeZone($zone_min);
- $date_min->modify('+2 days');
- $date_max->setTimeZone($zone_max);
- $date_max->modify('-2 days');
- } else {
- $date_min->setTimeZone($zone_utc);
- $date_max->setTimeZone($zone_utc);
- }
-
- $string_min = $date_min->format('Y-m-d');
- $string_max = $date_max->format('Y-m-d 23:59:00');
-
- $allday_min = id(new DateTime($string_min, $zone_utc))->format('U');
- $allday_max = id(new DateTime($string_max, $zone_utc))->format('U');
-
- queryfx(
- $conn,
- 'UPDATE %T SET allDayDateFrom = %d, allDayDateTo = %d
- WHERE id = %d',
- $table->getTableName(),
- $allday_min,
- $allday_max,
- $event->getID());
-}
+// This migration was replaced by "20161004.cal.01.noepoch.php".
diff --git a/resources/sql/autopatches/20161004.cal.01.noepoch.php b/resources/sql/autopatches/20161004.cal.01.noepoch.php
new file mode 100644
--- /dev/null
+++ b/resources/sql/autopatches/20161004.cal.01.noepoch.php
@@ -0,0 +1,125 @@
+<?php
+
+$table = new PhabricatorCalendarEvent();
+$conn = $table->establishConnection('w');
+$table_name = 'calendar_event';
+
+// Long ago, "All Day" events were stored with a start and end date set to
+// the earliest possible start and end seconds for the corresponding days. We
+// then moved to store all day events with their "date" epochs as UTC, separate
+// from individual event times. Both systems were later replaced with use of
+// CalendarDateTime.
+$zone_min = new DateTimeZone('Pacific/Midway');
+$zone_max = new DateTimeZone('Pacific/Kiritimati');
+$zone_utc = new DateTimeZone('UTC');
+
+foreach (new LiskRawMigrationIterator($conn, $table_name) as $row) {
+ $parameters = phutil_json_decode($row['parameters']);
+ if (isset($parameters['startDateTime'])) {
+ // This event has already been migrated.
+ continue;
+ }
+
+ $is_all_day = $row['isAllDay'];
+
+ if (empty($row['allDayDateFrom'])) {
+ // No "allDayDateFrom" means this is an old event which was never migrated
+ // by the earlier "20160715.event.03.allday.php" migration. The dateFrom
+ // and dateTo will be minimum and maximum earthly seconds for the event. We
+ // convert them to UTC if they were in extreme timezones.
+ $epoch_min = $row['dateFrom'];
+ $epoch_max = $row['dateTo'];
+
+ if ($is_all_day) {
+ $date_min = new DateTime('@'.$epoch_min);
+ $date_max = new DateTime('@'.$epoch_max);
+
+ $date_min->setTimeZone($zone_min);
+ $date_min->modify('+2 days');
+ $date_max->setTimeZone($zone_max);
+ $date_max->modify('-2 days');
+
+ $string_min = $date_min->format('Y-m-d');
+ $string_max = $date_max->format('Y-m-d 23:59:00');
+
+ $utc_min = id(new DateTime($string_min, $zone_utc))->format('U');
+ $utc_max = id(new DateTime($string_max, $zone_utc))->format('U');
+ } else {
+ $utc_min = $epoch_min;
+ $utc_max = $epoch_max;
+ }
+ } else {
+ // This is an event which was migrated already. We can pick the correct
+ // epoch timestamps based on the "isAllDay" flag.
+ if ($is_all_day) {
+ $utc_min = $row['allDayDateFrom'];
+ $utc_max = $row['allDayDateTo'];
+ } else {
+ $utc_min = $row['dateFrom'];
+ $utc_max = $row['dateTo'];
+ }
+ }
+
+ $utc_until = $row['recurrenceEndDate'];
+
+ $start_datetime = PhutilCalendarAbsoluteDateTime::newFromEpoch($utc_min);
+ if ($is_all_day) {
+ $start_datetime->setIsAllDay(true);
+ }
+
+ $end_datetime = PhutilCalendarAbsoluteDateTime::newFromEpoch($utc_max);
+ if ($is_all_day) {
+ $end_datetime->setIsAllDay(true);
+ }
+
+ if ($utc_until) {
+ $until_datetime = PhutilCalendarAbsoluteDateTime::newFromEpoch($utc_until);
+ } else {
+ $until_datetime = null;
+ }
+
+ $parameters['startDateTime'] = $start_datetime->toDictionary();
+ $parameters['endDateTime'] = $end_datetime->toDictionary();
+ if ($until_datetime) {
+ $parameters['untilDateTime'] = $until_datetime->toDictionary();
+ }
+
+ queryfx(
+ $conn,
+ 'UPDATE %T SET parameters = %s WHERE id = %d',
+ $table_name,
+ phutil_json_encode($parameters),
+ $row['id']);
+}
+
+// Generate UTC epochs for all events. We can't readily do this one at a
+// time because instance UTC epochs rely on having the parent event.
+$viewer = PhabricatorUser::getOmnipotentUser();
+
+$all_events = id(new PhabricatorCalendarEventQuery())
+ ->setViewer($viewer)
+ ->execute();
+foreach ($all_events as $event) {
+ if ($event->getUTCInitialEpoch()) {
+ // Already migrated.
+ continue;
+ }
+
+ try {
+ $event->updateUTCEpochs();
+ } catch (Exception $ex) {
+ continue;
+ }
+
+ queryfx(
+ $conn,
+ 'UPDATE %T SET
+ utcInitialEpoch = %d,
+ utcUntilEpoch = %nd,
+ utcInstanceEpoch = %nd WHERE id = %d',
+ $table_name,
+ $event->getUTCInitialEpoch(),
+ $event->getUTCUntilEpoch(),
+ $event->getUTCInstanceEpoch(),
+ $event->getID());
+}
diff --git a/src/applications/calendar/query/PhabricatorCalendarEventQuery.php b/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
--- a/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
+++ b/src/applications/calendar/query/PhabricatorCalendarEventQuery.php
@@ -352,14 +352,14 @@
if ($this->rangeBegin) {
$where[] = qsprintf(
$conn,
- 'event.dateTo >= %d OR event.isRecurring = 1',
+ '(event.utcUntilEpoch >= %d) OR (event.utcUntilEpoch IS NULL)',
$this->rangeBegin - phutil_units('16 hours in seconds'));
}
if ($this->rangeEnd) {
$where[] = qsprintf(
$conn,
- 'event.dateFrom <= %d',
+ 'event.utcInitialEpoch <= %d',
$this->rangeEnd + phutil_units('16 hours in seconds'));
}
diff --git a/src/applications/calendar/storage/PhabricatorCalendarEvent.php b/src/applications/calendar/storage/PhabricatorCalendarEvent.php
--- a/src/applications/calendar/storage/PhabricatorCalendarEvent.php
+++ b/src/applications/calendar/storage/PhabricatorCalendarEvent.php
@@ -17,10 +17,6 @@
protected $name;
protected $hostPHID;
- protected $dateFrom;
- protected $dateTo;
- protected $allDayDateFrom;
- protected $allDayDateTo;
protected $description;
protected $isCancelled;
protected $isAllDay;
@@ -30,7 +26,6 @@
protected $isRecurring = 0;
protected $recurrenceFrequency = array();
- protected $recurrenceEndDate;
private $isGhostEvent = false;
protected $instanceOfEventPHID;
@@ -51,6 +46,13 @@
private $viewerTimezone;
+ // TODO: DEPRECATED. Remove once we're sure the migrations worked.
+ protected $allDayDateFrom;
+ protected $allDayDateTo;
+ protected $dateFrom;
+ protected $dateTo;
+ protected $recurrenceEndDate;
+
// Frequency Constants
const FREQUENCY_DAILY = 'daily';
const FREQUENCY_WEEKLY = 'weekly';
@@ -70,20 +72,6 @@
$now = PhabricatorTime::getNow();
- $start = new DateTime('@'.$now);
- $start->setTimeZone($actor->getTimeZone());
-
- $start->setTime($start->format('H'), 0, 0);
- $start->modify('+1 hour');
- $end = id(clone $start)->modify('+1 hour');
-
- $epoch_min = $start->format('U');
- $epoch_max = $end->format('U');
-
- $now_date = new DateTime('@'.$now);
- $now_min = id(clone $now_date)->setTime(0, 0)->format('U');
- $now_max = id(clone $now_date)->setTime(23, 59)->format('U');
-
$default_icon = 'fa-calendar';
$datetime_start = PhutilCalendarAbsoluteDateTime::newFromEpoch(
@@ -106,10 +94,10 @@
->setEditPolicy($edit_policy)
->setSpacePHID($actor->getDefaultSpacePHID())
->attachInvitees(array())
- ->setDateFrom($epoch_min)
- ->setDateTo($epoch_max)
- ->setAllDayDateFrom($now_min)
- ->setAllDayDateTo($now_max)
+ ->setDateFrom(0)
+ ->setDateTo(0)
+ ->setAllDayDateFrom(0)
+ ->setAllDayDateTo(0)
->setStartDateTime($datetime_start)
->setEndDateTime($datetime_end)
->applyViewerTimezone($actor);
@@ -130,7 +118,11 @@
->setSequenceIndex($sequence)
->setIsRecurring(true)
->setRecurrenceFrequency($this->getRecurrenceFrequency())
- ->attachParentEvent($this);
+ ->attachParentEvent($this)
+ ->setAllDayDateFrom(0)
+ ->setAllDayDateTo(0)
+ ->setDateFrom(0)
+ ->setDateTo(0);
return $child->copyFromParent($actor);
}
@@ -187,11 +179,16 @@
$duration = $parent->getDuration();
$epochs = $parent->getSequenceIndexEpochs($actor, $sequence, $duration);
+ $start_datetime = PhutilCalendarAbsoluteDateTime::newFromEpoch(
+ $epochs['dateFrom'],
+ $parent->newStartDateTime()->getTimezone());
+ $end_datetime = PhutilCalendarAbsoluteDateTime::newFromEpoch(
+ $epochs['dateTo'],
+ $parent->newEndDateTime()->getTimezone());
+
$this
- ->setDateFrom($epochs['dateFrom'])
- ->setDateTo($epochs['dateTo'])
- ->setAllDayDateFrom($epochs['allDayDateFrom'])
- ->setAllDayDateTo($epochs['allDayDateTo']);
+ ->setStartDateTime($start_datetime)
+ ->setEndDateTime($end_datetime);
return $this;
}
@@ -213,12 +210,14 @@
$frequency = $this->getFrequencyUnit();
$modify_key = '+'.$sequence.' '.$frequency;
- $date = $this->getDateFrom();
- $date_time = PhabricatorTime::getDateTimeFromEpoch($date, $viewer);
+ $date_time = $this->newStartDateTime()
+ ->setViewerTimezone($viewer->getTimezoneIdentifier())
+ ->newPHPDateTime();
+
$date_time->modify($modify_key);
$date = $date_time->format('U');
- $end_date = $this->getRecurrenceEndDate();
+ $end_date = $this->getUntilDateTimeEpoch();
if ($end_date && $date > $end_date) {
throw new Exception(
pht(
@@ -227,21 +226,9 @@
$sequence));
}
- $utc = new DateTimeZone('UTC');
-
- $allday_from = $this->getAllDayDateFrom();
- $allday_date = new DateTime('@'.$allday_from, $utc);
- $allday_date->setTimeZone($utc);
- $allday_date->modify($modify_key);
-
- $allday_min = $allday_date->format('U');
- $allday_duration = ($this->getAllDayDateTo() - $allday_from);
-
return array(
'dateFrom' => $date,
'dateTo' => $date + $duration,
- 'allDayDateFrom' => $allday_min,
- 'allDayDateTo' => $allday_min + $allday_duration,
);
}
@@ -280,24 +267,6 @@
return ($this->getEndDateTimeEpoch() - $this->getStartDateTimeEpoch());
}
- public function getDateEpochForTimezone(
- $epoch,
- $src_zone,
- $format,
- $adjust,
- $dst_zone) {
-
- $src = new DateTime('@'.$epoch);
- $src->setTimeZone($src_zone);
-
- if (strlen($adjust)) {
- $adjust = ' '.$adjust;
- }
-
- $dst = new DateTime($src->format($format).$adjust, $dst_zone);
- return $dst->format('U');
- }
-
public function updateUTCEpochs() {
// The "intitial" epoch is the start time of the event, in UTC.
$start_date = $this->newStartDateTime()
@@ -314,9 +283,9 @@
$until_epoch = $end_date->getEpoch();
} else {
$until_epoch = null;
- $until_date = $this->newUntilDateTime()
- ->setViewerTimezone('UTC');
+ $until_date = $this->newUntilDateTime();
if ($until_date) {
+ $until_date->setViewerTimezone('UTC');
$duration = $this->newDuration();
$until_epoch = id(new PhutilCalendarRelativeDateTime())
->setOrigin($until_date)
@@ -377,23 +346,25 @@
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'text',
- 'dateFrom' => 'epoch',
- 'dateTo' => 'epoch',
- 'allDayDateFrom' => 'epoch',
- 'allDayDateTo' => 'epoch',
'description' => 'text',
'isCancelled' => 'bool',
'isAllDay' => 'bool',
'icon' => 'text32',
'mailKey' => 'bytes20',
'isRecurring' => 'bool',
- 'recurrenceEndDate' => 'epoch?',
'instanceOfEventPHID' => 'phid?',
'sequenceIndex' => 'uint32?',
'isStub' => 'bool',
'utcInitialEpoch' => 'epoch',
'utcUntilEpoch' => 'epoch?',
'utcInstanceEpoch' => 'epoch?',
+
+ // TODO: DEPRECATED.
+ 'allDayDateFrom' => 'epoch',
+ 'allDayDateTo' => 'epoch',
+ 'dateFrom' => 'epoch',
+ 'dateTo' => 'epoch',
+ 'recurrenceEndDate' => 'epoch?',
),
self::CONFIG_KEY_SCHEMA => array(
'key_date' => array(
@@ -814,7 +785,7 @@
return null;
}
- $epochs = $this->getParent()->getSequenceIndexEpochs(
+ $epochs = $this->getParentEvent()->getSequenceIndexEpochs(
new PhabricatorUser(),
$this->getSequenceIndex(),
$this->getDuration());
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventEndDateTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventEndDateTransaction.php
--- a/src/applications/calendar/xaction/PhabricatorCalendarEventEndDateTransaction.php
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventEndDateTransaction.php
@@ -13,16 +13,6 @@
public function applyInternalEffects($object, $value) {
$actor = $this->getActor();
- // TODO: DEPRECATED.
- $object->setDateTo($value);
- $object->setAllDayDateTo(
- $object->getDateEpochForTimezone(
- $value,
- $actor->getTimeZone(),
- 'Y-m-d 23:59:00',
- null,
- new DateTimeZone('UTC')));
-
$datetime = PhutilCalendarAbsoluteDateTime::newFromEpoch(
$value,
$actor->getTimezoneIdentifier());
diff --git a/src/applications/calendar/xaction/PhabricatorCalendarEventStartDateTransaction.php b/src/applications/calendar/xaction/PhabricatorCalendarEventStartDateTransaction.php
--- a/src/applications/calendar/xaction/PhabricatorCalendarEventStartDateTransaction.php
+++ b/src/applications/calendar/xaction/PhabricatorCalendarEventStartDateTransaction.php
@@ -13,16 +13,6 @@
public function applyInternalEffects($object, $value) {
$actor = $this->getActor();
- // TODO: DEPRECATED.
- $object->setDateFrom($value);
- $object->setAllDayDateFrom(
- $object->getDateEpochForTimezone(
- $value,
- $actor->getTimeZone(),
- 'Y-m-d',
- null,
- new DateTimeZone('UTC')));
-
$datetime = PhutilCalendarAbsoluteDateTime::newFromEpoch(
$value,
$actor->getTimezoneIdentifier());
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, May 19, 7:48 PM (10 h, 15 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
8006197
Default Alt Text
D16664.id40148.diff (15 KB)
Attached To
Mode
D16664: Migrate Calendar away from stored-epoch fields
Attached
Detach File
Event Timeline
Log In to Comment