Project Report: fawkez

Packagesummary org.jcoderz.commons.types

org.jcoderz.commons.types.Period

LineHitsNoteSource
1  /*
2   * $Id: Period.java 1011 2008-06-16 17:57:36Z amandel $
3   *
4   * Copyright 2006, The jCoderZ.org Project. All rights reserved.
5   *
6   * Redistribution and use in source and binary forms, with or without
7   * modification, are permitted provided that the following conditions are
8   * met:
9   *
10   *    * Redistributions of source code must retain the above copyright
11   *      notice, this list of conditions and the following disclaimer.
12   *    * Redistributions in binary form must reproduce the above
13   *      copyright notice, this list of conditions and the following
14   *      disclaimer in the documentation and/or other materials
15   *      provided with the distribution.
16   *    * Neither the name of the jCoderZ.org Project nor the names of
17   *      its contributors may be used to endorse or promote products
18   *      derived from this software without specific prior written
19   *      permission.
20   *
21   * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS" AND
22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24   * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS
25   * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30   * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32   */
33  package org.jcoderz.commons.types;
34  
35  
36  import java.io.Serializable;
37  import java.util.Calendar;
38  
39  import org.jcoderz.commons.ArgumentMalformedException;
40  import org.jcoderz.commons.util.Assert;
41  import org.jcoderz.commons.util.HashCodeUtil;
42  
43  
44  
45  /**
46   * A <code>Period</code> data type represents a period in time.
47   * <p>
48   * There are two types of periods. One that is day bound and the other one
49   * is milli-second bound. The day bound period has just set the hours, minutes,
50   * seconds, and milli-seconds set to zero. In other words, the first one is
51   * in day resolution whereas the second one is in milli-second resolution.
52   * <p>
53 (1) * TODO: Refine
54   *
55   * @author Michael Rumpf
56   */
57  public final class Period
58        implements Serializable
59  {
60     /** The name of this type. */
61     public static final String TYPE_NAME = "Period";
62  
63     /** use this serialVersionUID for serialization. */
64     static final long serialVersionUID = 128446267044986064L;
65  
66     private static final String DATE_PARAMETER = "date";
67  
68     /** Lazy init hash code. */
69100    private transient int mHashCode = 0;
70  
71     /** The start time of the period. */
72     private final Date mStartTime;
73  
74     /** The end time of the period. */
75     private final Date mEndTime;
76  
77     /**
78      * This is for easy creation of objects from two longs.
79      *
80      * @param start The start date.
81      * @param end The end date.
82      */
83     private Period (Date start, Date end)
84100    {
85100       Assert.notNull(start, "start date");
86100       Assert.notNull(end, "end date");
87100       if (end.compareTo(start) < 0)
88        {
89100(2)         throw new ArgumentMalformedException(TYPE_NAME,
90                 "start: " + start + " end:" + end,
91                 "The end date must be larger or equal to the start date!");
92        }
93100       mStartTime = start;
94100       mEndTime = end;
95100    }
96  
97     /**
98      * A factory method to create a period from two timestamps of the type
99      * {@link org.jcoderz.commons.types.Date}.
100      *
101      * @param start The start time to create the period from.
102      * @param end The end time to create the period from.
103      * @return The period created by the two timestamps.
104      * @throws ArgumentMalformedException when the end date is before the start
105      * date.
106      */
107     public static Period createPeriod (final Date start, final Date end)
108           throws ArgumentMalformedException
109     {
110100       return new Period(start, end);
111     }
112  
113     /**
114      * A factory method to create a period from two timestamps where the
115      * hours, minutes, seconds, and milli-seconds are stripped off.
116      *
117      * @param start The start time to create the period from.
118      * @param end The end time to create the period from.
119      * @return The period created by the two timestamps.
120      * @throws ArgumentMalformedException when the end date is before the start
121      * date.
122      */
123     public static Period createDayPeriod (Date start, Date end)
124           throws ArgumentMalformedException
125     {
126100       Assert.notNull(start, "start date");
127100       Assert.notNull(end, "end date");
128  
129100       final Calendar s = getCalendarInstance(start);
130100       int year = s.get(Calendar.YEAR);
131100       int month = s.get(Calendar.MONTH);
132100       int day = s.get(Calendar.DAY_OF_MONTH);
133100       s.set(year, month, day, s.getMinimum(Calendar.HOUR_OF_DAY),
134              s.getMinimum(Calendar.MINUTE), s.getMinimum(Calendar.SECOND));
135100       s.set(Calendar.MILLISECOND, s.getMinimum(Calendar.MILLISECOND));
136100       final Calendar e = getCalendarInstance(end);
137100       year  = e.get(Calendar.YEAR);
138100       month = e.get(Calendar.MONTH);
139100       day   = e.get(Calendar.DAY_OF_MONTH);
140100       e.set(year, month, day, e.getMaximum(Calendar.HOUR_OF_DAY),
141              e.getMaximum(Calendar.MINUTE), e.getMaximum(Calendar.SECOND));
142100       e.set(Calendar.MILLISECOND, e.getMaximum(Calendar.MILLISECOND));
143100       return new Period(
144              Date.fromUtilDate(s.getTime()), Date.fromUtilDate(e.getTime()));
145     }
146  
147     /**
148      * A factory method to create a day period. This period starts and ends on
149      * the same day as the given <code>date</code>. The duration of this period
150      * is exactly {@link Date#MILLIS_PER_DAY} milliseconds.
151      * Example: for the date 2004-09-03T11:52:03.437Z this method will return the
152      * period 2004-09-03T00:00:00.000Z-2004-09-03T23:59:59.999Z.
153      *
154      * @param date The date that falls within the returned period.
155      * @return The period created by the two timestamps.
156      * @throws ArgumentMalformedException when the parameter <code>date</code> is
157      * null.
158      */
159     public static Period createDayPeriod (Date date)
160           throws ArgumentMalformedException
161     {
162100       return Period.createDayPeriod(date, date);
163     }
164  
165     /**
166      * A factory method to create a month period. This period starts and ends on
167      * the same month as the given <code>date</code>. The duration of this period
168      * is exactly the duration of the month of the <code>date</code>.
169      * Example: for the date 2004-09-03T11:52:03.437Z this method will return a
170      * period 2004-09-01T00:00:00.000Z-2004-09-30T23:59:59.999Z.
171      *
172      * @param date The date that falls within the returned period.
173      * @return The period created by the two timestamps.
174      * @throws ArgumentMalformedException when the parameter <code>date</code> is
175      * null.
176      */
177     public static Period createMonthPeriod (Date date)
178           throws ArgumentMalformedException
179     {
180100       Assert.notNull(date, DATE_PARAMETER);
181  
182100       final Calendar c = getCalendarInstance(date);
183100       c.set(Calendar.DAY_OF_MONTH, c.getMinimum(Calendar.DAY_OF_MONTH));
184100       final Date s = new Date(c.getTimeInMillis());
185100       c.set(Calendar.DAY_OF_MONTH, c.getActualMaximum(Calendar.DAY_OF_MONTH));
186100       final Date e = new Date(c.getTimeInMillis());
187100       return Period.createDayPeriod(s, e);
188     }
189  
190     /**
191      * Returns the start date of the period.
192      *
193      * @return A Date marking the start of the period.
194      */
195     public Date getStartTime ()
196     {
197100       return mStartTime;
198     }
199  
200     /**
201      * Returns the end date of the period.
202      *
203      * @return A Date marking the end of the period.
204      */
205     public Date getEndTime ()
206     {
207100       return mEndTime;
208     }
209  
210     /**
211      * Returns the intersection of two periods.
212      *
213      * @param other The period that will be intersected with this instance.
214      * @return A new period that is the intersection between the two periods.
215      * Null is returned in case there is no intersection between the two periods.
216      */
217     public Period intersection (final Period other)
218     {
219100       final Date start = Date.latest(mStartTime, other.mStartTime);
220100       final Date end = Date.earliest(mEndTime, other.mEndTime);
221  
222        final Period result;
223100       if (start.beforeOrEqual(end))
224        {
225100          result = new Period(start, end);
226        }
227        else
228        {
229100          result = null;
230        }
231100       return result;
232     }
233  
234     /**
235      * Returns the union of two periods.
236      *
237      * @param other The period to create a union period with this instance.
238      * @return A new period that contains the intersection between the two
239      * periods or null if the two periods do not intersect.
240      */
241     public Period union (final Period other)
242     {
243        final Period result;
244100       if (overlap(other))
245        {
246100          final Date start = Date.earliest(mStartTime, other.mStartTime);
247100          final Date end = Date.latest(mEndTime, other.mEndTime);
248100          result = new Period(start, end);
249100       }
250        else
251        {
252100          result = null;
253        }
254100       return result;
255     }
256  
257     /**
258      * Checks whether a specified date falls into the period defined by the
259      * instance.
260      *
261      * @param date The date that is checked whether it lies in the period.
262      * @return true when the date falls into the period, false otherwise.
263      */
264     public boolean isIncluded (final Date date)
265     {
266100       return mStartTime.beforeOrEqual(date) && mEndTime.afterOrEqual(date);
267     }
268  
269     /**
270      * Checks whether a specified period falls into the period defined by the
271      * instance.
272      *
273      * @param other The period that is checked whether it lies in this period.
274      * @return true when the period falls into the period, false otherwise.
275      */
276     public boolean isIncluded (final Period other)
277     {
2780       return mStartTime.beforeOrEqual(other.getStartTime())
279              && mEndTime.afterOrEqual(other.getEndTime());
280     }
281  
282     /**
283      * Checks whether a specified period overlaps with this period.
284      *
285      * @param period The period to check for overlap with this period.
286      * @return true when the periods overlap, false otherwise.
287      */
288     public boolean overlap (final Period period)
289     {
290100       return isIncluded(period.mStartTime) || period.isIncluded(mStartTime);
291     }
292  
293     /**
294      * Returns the start time for the next period.
295      *
296      * @return the start time for the next period.
297      */
298     public Date getNextPeriodStartTime ()
299     {
300100       return mEndTime.plus(1);
301     }
302  
303     /**
304      * Returns the end time of the previous period.
305      *
306      * @return the end time of the previous period.
307      */
308     public Date getPrevPeriodEndTime ()
309     {
310100       return mStartTime.minus(1);
311     }
312  
313     /**
314      * Returns the duration of this Period in milliseconds.
315      *
316      * @return The duration of this Period in milliseconds.
317      */
318     public long duration ()
319     {
320100       return mEndTime.getTime() - mStartTime.getTime();
321     }
322  
323     /**
324      * Returns the next Period. The duration of the next period is exactly the
325      * same as duration of this Period. The next period starts 1 millisecond
326      * after the end time of this period.
327      *
328      * @return The next Period.
329      */
330     public Period next ()
331     {
332100       return new Period(getNextPeriodStartTime(),
333              getNextPeriodStartTime().plus(duration()));
334     }
335  
336     /**
337      * Returns the previous Period. The duration of the previous period is
338      * exactly the same as duration of this Period. The previous period ends 1
339      * millisecond before the start time of this period.
340      *
341      * @return The previous Period.
342      */
343     public Period previous ()
344     {
345100       return new Period(getPrevPeriodEndTime().minus(duration()),
346              getPrevPeriodEndTime());
347     }
348  
349     /**
350      * Returns a Period object whose start/end time lies exactly
351      * <code>offset</code> milliseconds after the start/end time of this period.
352      *
353      * @param offset The offset in milliseconds.
354      *
355      * @return The Period object whose start/end time lies exactly
356      * <code>offset</code> milliseconds after the start/end time of this period.
357      */
358     public Period plus (long offset)
359     {
3600       return new Period(mStartTime.plus(offset), mEndTime.plus(offset));
361     }
362  
363     /**
364      * Returns the next clock hour period, that lies after the
365      * given <code>date</code>.
366      *
367      * Example: for the date 2004-09-03T11:52:03 this method will return the
368      * period 2004-09-03T12:00:00.000Z-2004-09-03T12:59:59.999Z.
369      *
370      * @param date The date to get the next clock hour period.
371      *
372      * @return The next clock hour period, that lies after the given
373      * <code>date</code>.
374      */
375     public static Period nextHour (Date date)
376     {
377100       Assert.notNull(date, DATE_PARAMETER);
378100       final Calendar s = getCalendarInstance(date);
379100       s.add(Calendar.HOUR, 1);
380100       resetMinorFields(s);
381100       return createPeriod(s, Date.MILLIS_PER_HOUR);
382     }
383  
384     /**
385      * Returns the next clock hour period, that lies after this period.
386      * This method returns Period.nextHour(getEndTime()).
387      *
388      * @return the next clock hour period, that lies after this period.
389      */
390     public Period nextHour ()
391     {
392100(3)      return Period.nextHour(mEndTime);
393     }
394  
395     /**
396      * Returns the previous clock hour period, that lies befor the
397      * given <code>date</code>.
398      *
399      * Example: for the date 2004-09-03T11:52:03 this method will return the
400      * period 2004-09-03T10:00:00.000Z-2004-09-03T10:59:59.999Z.
401      *
402      * @param date The date to get the previous clock hour period.
403      *
404      * @return the previous clock hour period, that lies befor the
405      * given <code>date</code>.
406      */
407     public static Period previousHour (Date date)
408     {
409100       Assert.notNull(date, DATE_PARAMETER);
410100       final Calendar s = getCalendarInstance(date);
411100       s.add(Calendar.HOUR, -1);
412100       resetMinorFields(s);
413100       return createPeriod(s, Date.MILLIS_PER_HOUR);
414     }
415  
416     /**
417      * Returns the next clock hour period, that lies this this period.
418      * This method returns Period.previousHour(getSrartTime()).
419      *
420      * @return the next clock hour period, that lies before this period.
421      */
422     public Period previousHour ()
423     {
424100(4)      return Period.previousHour(mStartTime);
425     }
426  
427     /**
428      * Returns the day period, that lies after the given <code>date</code>.
429      *
430      * Example: for the date 2004-09-03T11:52:03 this method will return the
431      * period 2004-09-04T00:00:00.000Z-2004-09-04T23:59:59.999Z.
432      *
433      * @param date The date to get the next day period.
434      *
435      * @return The day period, that lies after the given <code>date</code>.
436      */
437     public static Period nextDay (Date date)
438     {
439100       Assert.notNull(date, DATE_PARAMETER);
440100       final Date nextDay = date.plus(Date.MILLIS_PER_DAY);
441100       return Period.createDayPeriod(nextDay, nextDay);
442     }
443  
444     /**
445      * Returns the day period, that lies after this period.
446      * This method returns Period.nextDay(getEndTime()).
447      * @see #nextDay(Date)
448      *
449      * @return The day period, that lies after the given <code>date</code>.
450      */
451     public Period nextDay ()
452     {
453100(5)      return Period.nextDay(mEndTime);
454     }
455  
456     /**
457      * Returns the day period, that lies before the given <code>date</code>.
458      *
459      * Example: for the date 2004-09-03T11:52:03 this method will return the
460      * period 2004-09-02T00:00:00.000Z-2004-09-02T23:59:59.999Z.
461      *
462      * @param date The date to get the previous day period.
463      *
464      * @return The day period, that lies before the given <code>date</code>.
465      */
466     public static Period previousDay (Date date)
467     {
468100       Assert.notNull(date, DATE_PARAMETER);
469100       final Date prevDay = date.minus(Date.MILLIS_PER_DAY);
470100       return Period.createDayPeriod(prevDay, prevDay);
471     }
472  
473     /**
474      * Returns the day period, that lies before this period.
475      * This method returns Period.previousDay(getStartTime()).
476      * @see #previousDay(Date)
477      *
478      * @return The the day period, that lies before this period.
479      */
480     public Period previousDay ()
481     {
482100(6)      return Period.previousDay(mStartTime);
483     }
484  
485     /**
486      * Returns the month period, that lies after the given <code>date</code>.
487      *
488      * Example: for the date 2004-09-03T11:52:03 this method will return the
489      * period 2004-10-01T00:00:00.000Z-2004-10-31T23:59:59.999Z.
490      *
491      * @param date The date to get the next month period.
492      *
493      * @return The the month period, that lies after the given <code>date</code>.
494      */
495     public static Period nextMonth (Date date)
496     {
497100       Assert.notNull(date, DATE_PARAMETER);
498100       final Calendar c = getCalendarInstance(date);
499100       c.add(Calendar.MONTH, 1);
500100       return Period.createMonthPeriod(new Date(c.getTimeInMillis()));
501     }
502  
503     /**
504      * Returns the month period, that lies after this period.
505      * This method returns Period.nextMonth(getEndTime()).
506      * @see #nextMonth(Date)
507      *
508      * @return The the month period, that lies after this period.
509      */
510     public Period nextMonth ()
511     {
512100(7)      return Period.nextMonth(mEndTime);
513     }
514  
515     /**
516      * Returns the month period, that lies before the given <code>date</code>.
517      *
518      * Example: for the date 2004-09-03T11:52:03 this method will return the
519      * period 2004-08-01T00:00:00.000Z-2004-08-31T23:59:59.999Z.
520      *
521      * @param date The date to get the previous month period.
522      *
523      * @return The the month period, that lies before the given
524      * <code>date</code>.
525      */
526     public static Period previousMonth (Date date)
527     {
528100       Assert.notNull(date, DATE_PARAMETER);
529100       final Calendar c = getCalendarInstance(date);
530100       c.add(Calendar.MONTH, -1);
531100       return Period.createMonthPeriod(new Date(c.getTimeInMillis()));
532     }
533  
534     /**
535      * Returns the month period, that lies before this period.
536      * This method returns Period.previousMonth(getStartTime()).
537      * @see #previousMonth(Date)
538      *
539      * @return The the month period, that lies before this period.
540      */
541     public Period previousMonth ()
542     {
543100(8)      return Period.previousMonth(mStartTime);
544     }
545  
546     /**
547      * Returns a Period object whose start/end time lies exactly
548      * <code>offset</code> milliseconds before the start/end time of this period.
549      *
550      * @param offset The offset in milliseconds.
551      *
552      * @return The Period object whose start/end time lies exactly
553      * <code>offset</code> milliseconds before the start/end time of this period.
554      */
555     public Period minus (long offset)
556     {
5570       return new Period(mStartTime.minus(offset), mEndTime.minus(offset));
558     }
559  
560     /**
561      * Checks if this period is before the given period.
562      * @param other the period to compare with.
563      * @return true, if this period is before the given period.
564      */
565     public boolean before (final Period other)
566     {
5670       Assert.notNull(other, "other");
568  
5690       return mEndTime.before(other.getStartTime());
570     }
571  
572     /**
573      * Checks if this period is after the given period.
574      * @param other the period to compare with.
575      * @return true, if this period is after the given period.
576      */
577     public boolean after (final Period other)
578     {
5790       Assert.notNull(other, "other");
580  
5810       return mStartTime.after(other.getEndTime());
582     }
583  
584     /** {@inheritDoc} */
585     public boolean equals (Object o)
586     {
587        final boolean result;
588100       if (o instanceof Period)
589        {
590100          final Period other = (Period) o;
59180          result = mStartTime.equals(other.mStartTime)
592                 && mEndTime.equals(other.mEndTime);
593100       }
594        else
595        {
5960          result = false;
597        }
598100       return result;
599     }
600  
601     /** {@inheritDoc} */
602     public int hashCode ()
603     {
6040       if (mHashCode == 0)
605        {
6060          mHashCode = HashCodeUtil.SEED;
6070          mHashCode = HashCodeUtil.hash(mHashCode, mStartTime);
6080          mHashCode = HashCodeUtil.hash(mHashCode, mEndTime);
609        }
6100       return mHashCode;
611     }
612  
613     /** {@inheritDoc} */
614     public String toString ()
615     {
616100       return mStartTime.toString() + "-" + mEndTime.toString();
617     }
618  
619     private static void resetMinorFields (final Calendar s)
620     {
621100       s.set(Calendar.MILLISECOND, s.getMinimum(Calendar.MILLISECOND));
622100       s.set(Calendar.SECOND, s.getMinimum(Calendar.SECOND));
623100       s.set(Calendar.MINUTE, s.getMinimum(Calendar.MINUTE));
624100    }
625  
626     private static Period createPeriod (final Calendar s,
627           final long periodDuration)
628     {
629100       final Date start = new Date(s.getTimeInMillis());
630100       return new Period(start, start.plus(periodDuration - 1));
631     }
632  
633     static Calendar getCalendarInstance (final Date date)
634     {
635100       final Calendar s = Calendar.getInstance(Date.TIME_ZONE);
636100       s.setLenient(false);
637100       s.clear();
638100       s.setTimeInMillis(date.getTime());
639100       return s;
640     }
641  }

Findings in this File

i (9) The field org.jcoderz.commons.types.Period.mHashCode is transient but isn't set by deserialization
i (1) 53 : 0 Comment matches to-do format '(TODO|FIXME|CHECKME)'.
i (2) 89 : 0 method new org.jcoderz.commons.types.Period(Date, Date) throws exception with static message string
w (3) 392 : 0 class org.jcoderz.commons.types.Period 'overloads' a method with both instance and static versions
w (4) 424 : 0 class org.jcoderz.commons.types.Period 'overloads' a method with both instance and static versions
w (5) 453 : 0 class org.jcoderz.commons.types.Period 'overloads' a method with both instance and static versions
w (6) 482 : 0 class org.jcoderz.commons.types.Period 'overloads' a method with both instance and static versions
w (7) 512 : 0 class org.jcoderz.commons.types.Period 'overloads' a method with both instance and static versions
w (8) 543 : 0 class org.jcoderz.commons.types.Period 'overloads' a method with both instance and static versions