001: /*
002: * $Id: TimeFrame.java 455983 2005-02-22 17:48:25Z jonl $ $Revision:
003: * 1.4 $ $Date: 2005-02-22 18:48:25 +0100 (Tue, 22 Feb 2005) $
004: *
005: * ==============================================================================
006: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
007: * use this file except in compliance with the License. You may obtain a copy of
008: * the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
014: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
015: * License for the specific language governing permissions and limitations under
016: * the License.
017: */
018: package wicket.util.time;
019:
020: /**
021: * Immutable class which represents an interval of time with a beginning and an
022: * end. The beginning value is inclusive and the end value is exclusive. In
023: * other words, the time frame of 1pm to 2pm includes 1pm, but not 2pm. 1:59:59
024: * is the last value in the timeframe.
025: * <p>
026: * TimeFrames can be constructed by calling the valueOf static factory methods
027: * valueOf(Time, Time) (yielding a TimeFrame between two absolute times) and
028: * valueOf(Time, Duration) yielding a TimeFrame starting at an absolute time and
029: * having a given length.
030: * <p>
031: * The start and end of a TimeFrame can be retrieved by calling getStart() and
032: * getEnd(). Its duration can be retrieved by calling getDuration().
033: * <p>
034: * The contains(Time) method can be called to determine if a TimeFrame contains
035: * a given point in time. The overlaps(TimeFrame) method can be called to
036: * determine if two TimeFrames overlap.
037: * <p>
038: * The eachDay(TimeOfDay, TimeOfDay) will return a TimeFrameSource which
039: * generates a timeframe using the two times of day. In other words, if the
040: * start is 3pm and the end is 4pm, the TimeFrameSource returned will yield
041: * 3-4pm on the day it is called (each day).
042: *
043: * @author Jonathan Locke
044: */
045: public final class TimeFrame implements ITimeFrameSource {
046: /** End of this timeframe */
047: private final Time end;
048:
049: /** Begining of this timeframe */
050: private final Time start;
051:
052: /**
053: * Returns a timeframe source for a start and end time-of-day. For example,
054: * called with 3pm and 5pm as parameters, the timeframe source returned
055: * would produce timeframe objects representing 3pm-5pm on whatever day it
056: * is when the caller calls the timeframesource interface.
057: *
058: * @param startTimeOfDay
059: * The start time for this time frame each day
060: * @param endTimeOfDay
061: * The end time for this time frame each day
062: * @return A timeframe source which will return the specified timeframe each
063: * day
064: */
065: public static ITimeFrameSource eachDay(
066: final TimeOfDay startTimeOfDay, final TimeOfDay endTimeOfDay) {
067: check(startTimeOfDay, endTimeOfDay);
068:
069: return new ITimeFrameSource() {
070: public TimeFrame getTimeFrame() {
071: return new TimeFrame(Time.valueOf(startTimeOfDay), Time
072: .valueOf(endTimeOfDay));
073: }
074: };
075: }
076:
077: /**
078: * Creates a time frame for a start and duration
079: *
080: * @param start
081: * The start time
082: * @param duration
083: * The duration
084: * @return The time frame
085: * @throws IllegalArgumentException
086: * Thrown if start time is before end time
087: */
088: public static TimeFrame valueOf(final Time start,
089: final Duration duration) {
090: return new TimeFrame(start, start.add(duration));
091: }
092:
093: /**
094: * Creates a time frame for a start and end time
095: *
096: * @param start
097: * The start time
098: * @param end
099: * The end time
100: * @return The time frame
101: * @throws IllegalArgumentException
102: * Thrown if start time is before end time
103: */
104: public static TimeFrame valueOf(final Time start, final Time end) {
105: return new TimeFrame(start, end);
106: }
107:
108: /**
109: * Checks consistency of start and end values, ensuring that the end value
110: * is less than the start value.
111: *
112: * @param start
113: * Start value
114: * @param end
115: * End value
116: * @throws IllegalArgumentException
117: * Thrown if end is less than start
118: */
119: private static void check(final AbstractTimeValue start,
120: final AbstractTimeValue end) {
121: // Throw illegal argument exception if end is less than start
122: if (end.lessThan(start)) {
123: throw new IllegalArgumentException(
124: "Start time of time frame " + start
125: + " was after end time " + end);
126: }
127: }
128:
129: /**
130: * Private constructor to force use of static factory methods
131: *
132: * @param start
133: * The start time
134: * @param end
135: * The end time
136: * @throws IllegalArgumentException
137: * Thrown if start time is before end time
138: */
139: private TimeFrame(final Time start, final Time end) {
140: check(start, end);
141: this .start = start;
142: this .end = end;
143: }
144:
145: /**
146: * @param time
147: * The time to check
148: * @return True if this time frame contains the given time
149: */
150: public boolean contains(final Time time) {
151: return (start.equals(time) || start.before(time))
152: && end.after(time);
153: }
154:
155: /**
156: * @return The duration of this time frame
157: */
158: public Duration getDuration() {
159: return end.subtract(start);
160: }
161:
162: /**
163: * @return The end of this time frame
164: */
165: public Time getEnd() {
166: return end;
167: }
168:
169: /**
170: * @return The start of this time frame
171: */
172: public Time getStart() {
173: return start;
174: }
175:
176: /**
177: * Implementation of ITimeFrameSource that simply returns this timeframe
178: *
179: * @return Gets this timeframe
180: */
181: public TimeFrame getTimeFrame() {
182: return this ;
183: }
184:
185: /**
186: * @param timeframe
187: * The timeframe to test
188: * @return True if the given timeframe overlaps this one
189: */
190: public boolean overlaps(final TimeFrame timeframe) {
191: return contains(timeframe.start) || contains(timeframe.end)
192: || timeframe.contains(start) || timeframe.contains(end);
193: }
194:
195: /**
196: * @return String representation of this object
197: */
198: public String toString() {
199: return "[start=" + start + ", end=" + end + "]";
200: }
201: }
|