KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > prefuse > util > TimeLib


1 package prefuse.util;
2
3 import java.lang.reflect.Constructor JavaDoc;
4 import java.util.Calendar JavaDoc;
5 import java.util.Date JavaDoc;
6 import java.util.GregorianCalendar JavaDoc;
7
8 /**
9  * Library routines for dealing with times and time spans. All time values
10  * are given as long values, indicating the number of milliseconds since
11  * the epoch (January 1, 1970). This is the same time format returned
12  * by the {@link java.lang.System#currentTimeMillis()} method.
13  *
14  * @author jeffrey heer
15  */

16 public class TimeLib {
17
18     /** Represents a millenium, 1000 years. */
19     public static final int MILLENIUM = -1000;
20     /** Represents a century, 100 years */
21     public static final int CENTURY = -100;
22     /** Represents a decade, 10 years */
23     public static final int DECADE = -10;
24     
25     private static final double SECOND_MILLIS = 1000;
26     private static final double MINUTE_MILLIS = SECOND_MILLIS*60;
27     private static final double HOUR_MILLIS = MINUTE_MILLIS*60;
28     private static final double DAY_MILLIS = HOUR_MILLIS * 24.0015;
29     private static final double WEEK_MILLIS = DAY_MILLIS * 7;
30     private static final double MONTH_MILLIS = DAY_MILLIS * 30.43675;
31     private static final double YEAR_MILLIS = WEEK_MILLIS * 52.2;
32     private static final double DECADE_MILLIS = YEAR_MILLIS * 10;
33     private static final double CENTURY_MILLIS = DECADE_MILLIS * 10;
34     private static final double MILLENIUM_MILLIS = CENTURY_MILLIS * 10;
35     
36     private static final int[] CALENDAR_FIELDS = {
37         Calendar.YEAR, Calendar.MONTH, Calendar.DATE, Calendar.HOUR_OF_DAY,
38         Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND
39     };
40     
41     private TimeLib() {
42         // prevent instantiation
43
}
44     
45     /**
46      * Get the number of time units between the two given timestamps.
47      * @param t0 the first timestamp (as a long)
48      * @param t1 the second timestamp (as a long)
49      * @param field the time unit to use, one of the {@link java.util.Calendar}
50      * fields, or one of the extended fields provided by this class
51      * (MILLENIUM, CENTURY, or DECADE).
52      * @return the number of time units between the two timestamps
53      */

54     public static int getUnitsBetween(long t0, long t1, int field) {
55         boolean negative = false;
56         if ( t1 < t0 ) {
57             long tmp = t1; t1 = t0; t0 = tmp; // swap
58
negative = true;
59         }
60         GregorianCalendar JavaDoc gc1 = new GregorianCalendar JavaDoc();
61         GregorianCalendar JavaDoc gc2 = new GregorianCalendar JavaDoc();
62         gc1.setTimeInMillis(t0);
63         gc2.setTimeInMillis(t1);
64         
65         // add 2 units less than the estimate to 1st date,
66
// then serially add units till we exceed 2nd date
67
int est = estimateUnitsBetween(t0, t1, field);
68         boolean multiYear = isMultiYear(field);
69         if ( multiYear ) {
70             gc1.add(Calendar.YEAR, -field*(est-2));
71             est = -field*est;
72         } else {
73             gc1.add(field, est-2);
74         }
75         int f = multiYear ? Calendar.YEAR : field;
76         int inc = multiYear ? -field : 1;
77         for( int i=est-inc; ; i+=inc ) {
78             gc1.add(f, inc);
79             if( gc1.after(gc2) ) {
80                 return negative ? inc-i : i-inc;
81             }
82         }
83     }
84     
85     /**
86      * Based on code posted at
87      * http://forum.java.sun.com/thread.jspa?threadID=488676&messageID=2292012
88      */

89     private static int estimateUnitsBetween(long t0, long t1, int field) {
90         long d = t1-t0;
91         switch (field) {
92         case Calendar.MILLISECOND:
93             return (int)d; // this could be very inaccurate. TODO: use long instead of int?
94
case Calendar.SECOND:
95             return (int)(d / SECOND_MILLIS + .5);
96         case Calendar.MINUTE:
97             return (int)(d / MINUTE_MILLIS + .5);
98         case Calendar.HOUR_OF_DAY:
99         case Calendar.HOUR:
100             return (int)(d / HOUR_MILLIS + .5);
101         case Calendar.DAY_OF_WEEK_IN_MONTH :
102         case Calendar.DAY_OF_MONTH :
103         // case Calendar.DATE : // codes to same int as DAY_OF_MONTH
104
return (int) (d / DAY_MILLIS + .5);
105         case Calendar.WEEK_OF_YEAR :
106             return (int) (d / WEEK_MILLIS + .5);
107         case Calendar.MONTH :
108             return (int) (d / MONTH_MILLIS + .5);
109         case Calendar.YEAR :
110             return (int) (d / YEAR_MILLIS + .5);
111         case DECADE:
112             return (int) (d / DECADE_MILLIS + .5);
113         case CENTURY:
114             return (int) (d / CENTURY_MILLIS + .5);
115         case MILLENIUM:
116             return (int) (d / MILLENIUM_MILLIS + .5);
117         default:
118             return 0;
119         }
120     }
121         
122     /**
123      * Increment a calendar by a given number of time units.
124      * @param c the calendar to increment
125      * @param field the time unit to increment, one of the
126      * {@link java.util.Calendar} fields, or one of the extended fields
127      * provided by this class (MILLENIUM, CENTURY, or DECADE).
128      * @param val the number of time units to increment by
129      */

130     public static void increment(Calendar JavaDoc c, int field, int val) {
131         if ( isMultiYear(field) ) {
132             c.add(Calendar.YEAR, -field*val);
133         } else {
134             c.add(field, val);
135         }
136     }
137     
138     /**
139      * Get the value of the given time field for a Calendar. Just like the
140      * {@link java.util.Calendar#get(int)} method, but include support for
141      * the extended fields provided by this class (MILLENIUM, CENTURY, or
142      * DECADE).
143      * @param c the Calendar
144      * @param field the time field
145      * @return the value of the time field for the given calendar
146      */

147     public static int get(Calendar JavaDoc c, int field) {
148         if ( isMultiYear(field) ) {
149             int y = c.get(Calendar.YEAR);
150             return -field * (y/-field);
151         } else {
152             return c.get(field);
153         }
154     }
155     
156     // ------------------------------------------------------------------------
157
// Date Access
158

159     /**
160      * Get the timestamp for the given year, month, and, day.
161      * @param c a Calendar to use to help compute the result. The state of the
162      * Calendar will be overwritten.
163      * @param year the year to look up
164      * @param month the month to look up (months start at 0==January)
165      * @param day the day to look up
166      * @return the timestamp for the given date
167      */

168     public static long getDate(Calendar JavaDoc c, int year, int month, int day) {
169         c.clear(Calendar.MILLISECOND);
170         c.set(year, month, day, 0, 0, 0);
171         return c.getTimeInMillis();
172     }
173
174     /**
175      * Get a timestamp for the given hour, minute, and second. The date will
176      * be assumed to be January 1, 1970.
177      * @param c a Calendar to use to help compute the result. The state of the
178      * Calendar will be overwritten.
179      * @param hour the hour, on a 24 hour clock
180      * @param minute the minute value
181      * @param second the seconds value
182      * @return the timestamp for the given date
183      */

184     public static long getTime(Calendar JavaDoc c, int hour, int minute, int second) {
185         c.clear(Calendar.MILLISECOND);
186         c.set(1970, 0, 1, hour, minute, second);
187         return c.getTimeInMillis();
188     }
189     
190     /**
191      * Get a new Date instance of the specified subclass and given long value.
192      * @param type the concrete subclass of the Date instance, must be an
193      * instance of subclass of java.util.Date
194      * @param d the date/time value as a long
195      * @return the new Date instance, or null if the class type is not valid
196      */

197     public static Date JavaDoc getDate(Class JavaDoc type, long d) {
198         try {
199             Constructor JavaDoc c = type.getConstructor(new Class JavaDoc[] {long.class});
200             return (Date JavaDoc)c.newInstance(new Object JavaDoc[] {new Long JavaDoc(d)});
201         } catch ( Exception JavaDoc e ) {
202             e.printStackTrace();
203             return null;
204         }
205     }
206     
207     // ------------------------------------------------------------------------
208
// Date Normalization
209

210     /**
211      * Get the timestamp resulting from clearing (setting to zero) all time
212      * values less than or equal to that of the given field. For example,
213      * clearing to {@link Calendar#HOUR} will floor the time to nearest
214      * hour which occurred before or at the given time (e.g., 1:32
215      * --> 1:30).
216      * @param t the reference time
217      * @param c a Calendar instance used to help compute the value, the
218      * state of the Calendar will be overwritten.
219      * @param field the time field to clear to, one of the
220      * {@link java.util.Calendar} fields, or one of the extended fields
221      * provided by this class (MILLENIUM, CENTURY, or DECADE).
222      * @return the cleared time
223      */

224     public static long getClearedTime(long t, Calendar JavaDoc c, int field) {
225         c.setTimeInMillis(t);
226         TimeLib.clearTo(c, field);
227         return c.getTimeInMillis();
228     }
229     
230     /**
231      * Clear the given calendar, setting to zero all time
232      * values less than or equal to that of the given field. For example,
233      * clearing to {@link Calendar#HOUR} will floor the time to nearest
234      * hour which occurred before or at the given time (e.g., 1:32
235      * --> 1:30).
236      * @param c the Calendar to clear
237      * @param field the time field to clear to, one of the
238      * {@link java.util.Calendar} fields, or one of the extended fields
239      * provided by this class (MILLENIUM, CENTURY, or DECADE).
240      * @return the original Calendar reference, now set to the cleared time
241      */

242     public static Calendar JavaDoc clearTo(Calendar JavaDoc c, int field) {
243         int i = CALENDAR_FIELDS.length-1;
244         for ( ; i>=1 && field != CALENDAR_FIELDS[i]; i-- ) {
245             int val = (CALENDAR_FIELDS[i]==Calendar.DATE?1:0);
246             c.set(CALENDAR_FIELDS[i],val);
247         }
248         if ( isMultiYear(field) ) {
249             int y = c.get(Calendar.YEAR);
250             y = -field * (y/-field);
251             c.set(Calendar.YEAR, y);
252         }
253         return c;
254     }
255     
256     /**
257      * Indicates if a field value indicates a timespan greater than one
258      * year. These multi-year spans are the extended fields introduced by
259      * this class (MILLENIUM, CENTURY, and DECADE).
260      * @param field the time field
261      * @return true if the field is multi-year, false otherwise
262      */

263     public static boolean isMultiYear(int field) {
264         return ( field == DECADE || field == CENTURY || field == MILLENIUM );
265     }
266     
267 } // end of class TimeLib
268
Popular Tags