[california/wip/725783-time] WallTime.round_down() -> WallTime.round()
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [california/wip/725783-time] WallTime.round_down() -> WallTime.round()
- Date: Tue, 5 Aug 2014 23:09:24 +0000 (UTC)
commit d4b47dbdc00b09bb6bad646f5eb39277fa56ed8e
Author: Jim Nelson <jim yorba org>
Date: Tue Aug 5 14:10:55 2014 -0700
WallTime.round_down() -> WallTime.round()
src/calendar/calendar-wall-time.vala | 77 +++++++++++++++++++++------
src/host/host-event-time-settings.vala | 3 +-
src/tests/tests-calendar-wall-time.vala | 91 ++++++++++++++++++++++++-------
src/view/week/week-day-pane.vala | 2 +-
src/view/week/week-grid.vala | 4 +-
5 files changed, 137 insertions(+), 40 deletions(-)
---
diff --git a/src/calendar/calendar-wall-time.vala b/src/calendar/calendar-wall-time.vala
index 57de06d..57d6d8e 100644
--- a/src/calendar/calendar-wall-time.vala
+++ b/src/calendar/calendar-wall-time.vala
@@ -348,60 +348,105 @@ public class WallTime : BaseObject, Gee.Comparable<WallTime>, Gee.Hashable<WallT
/**
* Round a unit of the { link WallTime} to a multiple of a supplied value.
*
- * By rounding wall-clock time, not only is the unit in question rounded down to a multiple of
+ * Supply a positive integer to round up, a negative integer to round down.
+ *
+ * By rounding wall-clock time, not only is the unit in question rounded to a multiple of
* the supplied value, but the lesser units are truncated to zero. Thus, 17:23:54 rounded down
* to a multiple of 10 minutes returns 17:20:00.
*
+ * rollover is set to true if rounding by the multiple rolls the WallTime over to the next day.
+ * Rolling back to the previous day isn't possible with this interface; rounding down any value
+ * earlier than midnight results in midnight. Rollover can occur when rounding up.
+ *
+ * It's important to note that zero is treated as a multiple of all values. Hence rounding
+ * 11:56:00 up to a multiple of 17 minutes will result in 12:00:00. (In other words, don't
+ * confuse this method with { link adjust}.
+ *
* If the { link TimeUnit} is already a multiple of the value, no change is made (although
* there's no guarantee that the same WallTime instance will be returned, especially if the
* lesser units are truncated).
*
- * A multiple of zero or a negative value is always rounded to the current WallTime.
- *
- * TODO: An interface to round up (which will need to deal with overflow).
+ * A multiple of zero is always rounded to the current WallTime.
*/
- public WallTime round_down(int multiple, TimeUnit time_unit) {
- if (multiple <= 0)
+ public WallTime round(int multiple, TimeUnit time_unit, out bool rollover) {
+ rollover = false;
+
+ if (multiple == 0)
return this;
- // get value being manipulated
- int current;
+ // get value being manipulated and its max value (min is always zero)
+ int current, max;
switch (time_unit) {
case TimeUnit.HOUR:
current = hour;
+ max = MAX_HOUR;
break;
case TimeUnit.MINUTE:
current = minute;
+ max = MAX_MINUTE;
break;
case TimeUnit.SECOND:
current = second;
+ max = MAX_SECOND;
break;
default:
assert_not_reached();
}
- // round down and watch for underflow (which shouldn't happen)
- int rounded = current - (current % multiple.abs());
- if (rounded < 0)
- rounded = 0;
+ int rounded;
+ if (multiple < 0) {
+ // round down and watch for underflow (which shouldn't happen)
+ rounded = current - (current % multiple.abs());
+ assert(rounded >= 0);
+ } else {
+ assert(multiple > 0);
+
+ // round up and watch for overflow (which can definitely happen)
+ int rem = current % multiple;
+ if (rem != 0) {
+ rounded = current + (multiple - rem);
+ if (rounded > max) {
+ rounded = 0;
+ rollover = true;
+ }
+ } else {
+ // no remainder then on the money
+ rounded = current;
+ }
+ }
- // return new value
+ // construct new value and deal with rollover
+ Calendar.WallTime rounded_wall_time;
+ bool adjust_rollover = false;
switch (time_unit) {
case TimeUnit.HOUR:
- return new WallTime(rounded, 0, 0);
+ // no adjust can be done, rollover is rollover here
+ rounded_wall_time = new WallTime(rounded, 0, 0);
+ break;
case TimeUnit.MINUTE:
- return new WallTime(hour, rounded, 0);
+ rounded_wall_time = new WallTime(hour, rounded, 0);
+ if (rollover)
+ rounded_wall_time = rounded_wall_time.adjust(1, TimeUnit.HOUR, out adjust_rollover);
+ break;
case TimeUnit.SECOND:
- return new WallTime(hour, minute, rounded);
+ rounded_wall_time = new WallTime(hour, minute, rounded);
+ if (rollover)
+ rounded_wall_time = rounded_wall_time.adjust(1, TimeUnit.MINUTE, out adjust_rollover);
+ break;
default:
assert_not_reached();
}
+
+ // handle adjustment causing rollover
+ rollover = rollover || adjust_rollover;
+
+ return rounded_wall_time;
}
/**
diff --git a/src/host/host-event-time-settings.vala b/src/host/host-event-time-settings.vala
index a2ea75b..9440ce2 100644
--- a/src/host/host-event-time-settings.vala
+++ b/src/host/host-event-time-settings.vala
@@ -124,7 +124,8 @@ public class EventTimeSettings : Gtk.Box, Toolkit.Card {
to_widget.wall_time = time_span.end_exact_time.to_wall_time();
} else {
// set to defaults in case user wants to change from all-day to timed event
- from_widget.wall_time = Calendar.System.now.to_wall_time().round_down(15,
Calendar.TimeUnit.MINUTE);
+ from_widget.wall_time = Calendar.System.now.to_wall_time().round(15, Calendar.TimeUnit.MINUTE,
+ null);
if (date_span.is_same_day) {
// one-hour event is default
to_widget.wall_time = from_widget.wall_time.adjust(1, Calendar.TimeUnit.HOUR, null);
diff --git a/src/tests/tests-calendar-wall-time.vala b/src/tests/tests-calendar-wall-time.vala
index ef974de..5844cfd 100644
--- a/src/tests/tests-calendar-wall-time.vala
+++ b/src/tests/tests-calendar-wall-time.vala
@@ -8,12 +8,17 @@ namespace California.Tests {
internal class CalendarWallTime : UnitTest.Harness {
public CalendarWallTime() {
- add_case("round-down-perverse", round_down_perverse);
- add_case("round-down-zero", round_down_zero);
+ add_case("round-zero", round_zero);
add_case("round-down-hour-no-change", round_down_hour_no_change);
add_case("round-down-hour-change", round_down_hour_change);
add_case("round-down-minute", round_down_minute);
add_case("round-down-second", round_down_second);
+ add_case("round-down-no-rollover", round_down_no_rollover);
+ add_case("round-up-hour-no-change", round_up_hour_no_change);
+ add_case("round-up-hour-change", round_up_hour_change);
+ add_case("round-up-minute", round_up_minute);
+ add_case("round-up-second", round_up_second);
+ add_case("round-up-rollover", round_up_rollover);
}
protected override void setup() throws Error {
@@ -24,46 +29,92 @@ internal class CalendarWallTime : UnitTest.Harness {
Calendar.terminate();
}
- private bool round_down_perverse() throws Error {
+ private bool round_zero() throws Error {
Calendar.WallTime wall_time = new Calendar.WallTime(10, 12, 14);
- Calendar.WallTime round_down = wall_time.round_down(-1, Calendar.TimeUnit.MINUTE);
+ bool rollover;
+ Calendar.WallTime rounded = wall_time.round(0, Calendar.TimeUnit.HOUR, out rollover);
- return wall_time.equal_to(round_down);
- }
-
- private bool round_down_zero() throws Error {
- Calendar.WallTime wall_time = new Calendar.WallTime(10, 12, 14);
- Calendar.WallTime round_down = wall_time.round_down(0, Calendar.TimeUnit.HOUR);
-
- return wall_time.equal_to(round_down);
+ return !rollover && wall_time.equal_to(rounded);
}
private bool round_down_hour_no_change() throws Error {
Calendar.WallTime wall_time = new Calendar.WallTime(10, 12, 14);
- Calendar.WallTime round_down = wall_time.round_down(2, Calendar.TimeUnit.HOUR);
+ bool rollover;
+ Calendar.WallTime round_down = wall_time.round(-2, Calendar.TimeUnit.HOUR, out rollover);
- return round_down.hour == 10 && round_down.minute == 0 && round_down.second == 0;
+ return !rollover && round_down.hour == 10 && round_down.minute == 0 && round_down.second == 0;
}
private bool round_down_hour_change() throws Error {
Calendar.WallTime wall_time = new Calendar.WallTime(9, 12, 14);
- Calendar.WallTime round_down = wall_time.round_down(2, Calendar.TimeUnit.HOUR);
+ bool rollover;
+ Calendar.WallTime round_down = wall_time.round(-2, Calendar.TimeUnit.HOUR, out rollover);
- return round_down.hour == 8 && round_down.minute == 0 && round_down.second == 0;
+ return !rollover && round_down.hour == 8 && round_down.minute == 0 && round_down.second == 0;
}
private bool round_down_minute() throws Error {
Calendar.WallTime wall_time = new Calendar.WallTime(10, 12, 14);
- Calendar.WallTime round_down = wall_time.round_down(10, Calendar.TimeUnit.MINUTE);
+ bool rollover;
+ Calendar.WallTime round_down = wall_time.round(-10, Calendar.TimeUnit.MINUTE, out rollover);
- return round_down.hour == 10 && round_down.minute == 10 && round_down.second == 0;
+ return !rollover && round_down.hour == 10 && round_down.minute == 10 && round_down.second == 0;
}
private bool round_down_second() throws Error {
Calendar.WallTime wall_time = new Calendar.WallTime(10, 12, 16);
- Calendar.WallTime round_down = wall_time.round_down(15, Calendar.TimeUnit.SECOND);
+ bool rollover;
+ Calendar.WallTime round_down = wall_time.round(-15, Calendar.TimeUnit.SECOND, out rollover);
+
+ return !rollover && round_down.hour == 10 && round_down.minute == 12 && round_down.second == 15;
+ }
+
+ private bool round_down_no_rollover() throws Error {
+ Calendar.WallTime wall_time = Calendar.WallTime.earliest;
+ bool rollover;
+ Calendar.WallTime round_down = wall_time.round(-15, Calendar.TimeUnit.SECOND, out rollover);
+
+ return !rollover && round_down.equal_to(wall_time);
+ }
+
+ private bool round_up_hour_no_change() throws Error {
+ Calendar.WallTime wall_time = new Calendar.WallTime(10, 12, 14);
+ bool rollover;
+ Calendar.WallTime round_up = wall_time.round(2, Calendar.TimeUnit.HOUR, out rollover);
+
+ return !rollover && round_up.hour == 10 && round_up.minute == 0 && round_up.second == 0;
+ }
+
+ private bool round_up_hour_change() throws Error {
+ Calendar.WallTime wall_time = new Calendar.WallTime(9, 12, 14);
+ bool rollover;
+ Calendar.WallTime round_up = wall_time.round(2, Calendar.TimeUnit.HOUR, out rollover);
+
+ return !rollover && round_up.hour == 10 && round_up.minute == 0 && round_up.second == 0;
+ }
+
+ private bool round_up_minute() throws Error {
+ Calendar.WallTime wall_time = new Calendar.WallTime(10, 12, 14);
+ bool rollover;
+ Calendar.WallTime round_up = wall_time.round(10, Calendar.TimeUnit.MINUTE, out rollover);
+
+ return !rollover && round_up.hour == 10 && round_up.minute == 20 && round_up.second == 0;
+ }
+
+ private bool round_up_second() throws Error {
+ Calendar.WallTime wall_time = new Calendar.WallTime(10, 12, 16);
+ bool rollover;
+ Calendar.WallTime round_up = wall_time.round(15, Calendar.TimeUnit.SECOND, out rollover);
+
+ return !rollover && round_up.hour == 10 && round_up.minute == 12 && round_up.second == 30;
+ }
+
+ private bool round_up_rollover() throws Error {
+ Calendar.WallTime wall_time = new Calendar.WallTime(23, 55, 16);
+ bool rollover;
+ Calendar.WallTime round_up = wall_time.round(15, Calendar.TimeUnit.MINUTE, out rollover);
- return round_down.hour == 10 && round_down.minute == 12 && round_down.second == 15;
+ return rollover && round_up.hour == 0 && round_up.minute == 0 && round_up.second == 0;
}
}
diff --git a/src/view/week/week-day-pane.vala b/src/view/week/week-day-pane.vala
index 5090355..cf3a558 100644
--- a/src/view/week/week-day-pane.vala
+++ b/src/view/week/week-day-pane.vala
@@ -152,7 +152,7 @@ internal class DayPane : Pane, Common.InstanceContainer {
public void update_selection(Calendar.WallTime wall_time) {
// round down to the nearest 15-minute mark
- Calendar.WallTime rounded_time = wall_time.round_down(15, Calendar.TimeUnit.MINUTE);
+ Calendar.WallTime rounded_time = wall_time.round(-15, Calendar.TimeUnit.MINUTE, null);
// assign start first, end second (ordering doesn't matter, possible to select upwards)
if (selection_start == null) {
diff --git a/src/view/week/week-grid.vala b/src/view/week/week-grid.vala
index ea82fdc..6556a02 100644
--- a/src/view/week/week-grid.vala
+++ b/src/view/week/week-grid.vala
@@ -345,8 +345,8 @@ internal class Grid : Gtk.Box {
DayPane? day_pane = instance_container as DayPane;
if (day_pane != null) {
// convert click into starting time on the day pane rounded down to the nearest half-hour
- Calendar.WallTime wall_time = day_pane.get_wall_time(details.press_point.y).round_down(
- 30, Calendar.TimeUnit.MINUTE);
+ Calendar.WallTime wall_time = day_pane.get_wall_time(details.press_point.y).round(-30,
+ Calendar.TimeUnit.MINUTE, null);
Calendar.ExactTime start_time = new Calendar.ExactTime(Calendar.Timezone.local,
day_pane.date, wall_time);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]