Coverage report

| %line | %branch
--- | --- | ---
org.apache.commons.net.ntp.TimeStamp |
56% |
86% |

1 |  |
     package org.apache.commons.net.ntp;
2 |  |
     /*
3 |  |
      * Copyright 2001-2005 The Apache Software Foundation
4 |  |
      *
5 |  |
      * Licensed under the Apache License, Version 2.0 (the "License");
6 |  |
      * you may not use this file except in compliance with the License.
7 |  |
      * You may obtain a copy of the License at
8 |  |
      *
9 |  |
      *     http://www.apache.org/licenses/LICENSE-2.0
10 |  |
      *
11 |  |
      * Unless required by applicable law or agreed to in writing, software
12 |  |
      * distributed under the License is distributed on an "AS IS" BASIS,
13 |  |
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 |  |
      * See the License for the specific language governing permissions and
15 |  |
      * limitations under the License.
16 |  |
      */
17 |  |
18 |  |
19 |  |
     import java.util.TimeZone;
20 |  |
     import java.util.Date;
21 |  |
     import java.util.Locale;
22 |  |
     import java.lang.ref.SoftReference;
23 |  |
     import java.text.SimpleDateFormat;
24 |  |
     import java.text.DateFormat;
25 |  |
26 |  |
     /***
27 |  |
      * TimeStamp class represents the Network Time Protocol (NTP) timestamp
28 |  |
      * as defined in RFC-1305 and SNTP (RFC-2030). It is represented as a
29 |  |
      * 64-bit unsigned fixed-point number in seconds relative to 0-hour on 1-January-1900.
30 |  |
      * The 32-bit low-order bits are the fractional seconds whose precision is
31 |  |
      * about 200 picoseconds. Assumes overflow date when date passes MAX_LONG
32 |  |
      * and reverts back to 0 is 2036 and not 1900. Test for most significant
33 |  |
      * bit: if MSB=0 then 2036 basis is used otherwise 1900 if MSB=1.
34 |  |
      * <p>
35 |  |
      * Methods exist to convert NTP timestamps to and from the equivalent Java date
36 |  |
      * representation, which is the number of milliseconds since the standard base
37 |  |
      * time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.
38 |  |
      * </p>
39 |  |
      *
40 |  |
      * @author Jason Mathews, MITRE Corp
41 |  |
      * @version $Revision: 165675 $ $Date: 2005-05-02 21:09:55 +0100 (Mon, 02 May 2005) $
42 |  |
      * @see java.util.Date
43 |  |
      */
44 |  |
     public class TimeStamp implements java.io.Serializable, Comparable
45 |  |
     {
46 |  |
47 |  |
         /**
48 |  |
          * baseline NTP time if bit-0=0 -> 7-Feb-2036 @ 06:28:16 UTC
49 |  |
          */
50 |  |
         protected static final long msb0baseTime = 2085978496000L;
51 |  |
52 |  |
         /**
53 |  |
          *  baseline NTP time if bit-0=1 -> 1-Jan-1900 @ 01:00:00 UTC
54 |  |
          */
55 |  |
         protected static final long msb1baseTime = -2208988800000L;
56 |  |
57 |  |
         /**
58 |  |
          * Default NTP date string format. E.g. Fri, Sep 12 2003 21:06:23.860.
59 |  |
          * See <code>java.text.SimpleDateFormat</code> for code descriptions.
60 |  |
          */
61 |  |
         public final static String NTP_DATE_FORMAT = "EEE, MMM dd yyyy HH:mm:ss.SSS";
62 |  |
63 |  |
         /*
64 |  |
          * Caches for the DateFormatters used by various toString methods.
65 |  |
          */
66 | 2 |
         private static SoftReference simpleFormatter = null;
67 | 2 |
         private static SoftReference utcFormatter = null;
68 |  |
69 |  |
         /**
70 |  |
          * NTP timestamp value: 64-bit unsigned fixed-point number as defined in RFC-1305
71 |  |
          * with high-order 32 bits the seconds field and the low-order 32-bits the
72 |  |
          * fractional field.
73 |  |
          */
74 |  |
         private long ntpTime;
75 |  |
76 |  |
         private static final long serialVersionUID = 8139806907588338737L;
77 |  |
78 |  |
         // initialization of static time bases
79 |  |
         /*
80 |  |
         static {
81 |  |
             TimeZone utcZone = TimeZone.getTimeZone("UTC");
82 |  |
             Calendar calendar = Calendar.getInstance(utcZone);
83 |  |
             calendar.set(1900, Calendar.JANUARY, 1, 0, 0, 0);
84 |  |
             calendar.set(Calendar.MILLISECOND, 0);
85 |  |
             msb1baseTime = calendar.getTime().getTime();
86 |  |
             calendar.set(2036, Calendar.FEBRUARY, 7, 6, 28, 16);
87 |  |
             calendar.set(Calendar.MILLISECOND, 0);
88 |  |
             msb0baseTime = calendar.getTime().getTime();
89 |  |
         }
90 |  |
         */
91 |  |
92 |  |
         /***
93 |  |
          * Constructs a newly allocated NTP timestamp object
94 |  |
          * that represents the native 64-bit long argument.
95 |  |
          */
96 |  |
         public TimeStamp(long ntpTime)
97 | 0 |
         {
98 | 0 |
             this.ntpTime = ntpTime;
99 | 0 |
         }
100 |  |
101 |  |
         /***
102 |  |
          * Constructs a newly allocated NTP timestamp object
103 |  |
          * that represents the value represented by the string
104 |  |
          * in hexdecimal form (e.g. "c1a089bd.fc904f6d").
105 |  |
          *
106 |  |
          * @throws NumberFormatException - if the string does not contain a parsable timestamp.
107 |  |
          */
108 |  |
         public TimeStamp(String s) throws NumberFormatException
109 | 10 |
         {
110 | 10 |
             ntpTime = decodeNtpHexString(s);
111 | 10 |
         }
112 |  |
113 |  |
         /***
114 |  |
          * Constructs a newly allocated NTP timestamp object
115 |  |
          * that represents the Java Date argument.
116 |  |
          *
117 |  |
          * @param d - the Date to be represented by the Timestamp object.
118 |  |
          */
119 |  |
         public TimeStamp(Date d)
120 | 2 |
         {
121 | 2 |
             ntpTime = (d == null) ? 0 : toNtpTime(d.getTime());
122 | 2 |
         }
123 |  |
124 |  |
         /***
125 |  |
          * Returns the value of this Timestamp as a long value.
126 |  |
          *
127 |  |
          * @return the 64-bit long value represented by this object.
128 |  |
          */
129 |  |
         public long ntpValue()
130 |  |
         {
131 | 16 |
             return ntpTime;
132 |  |
         }
133 |  |
134 |  |
         /***
135 |  |
          * Returns high-order 32-bits representing the seconds of this NTP timestamp.
136 |  |
          *
137 |  |
          * @return seconds represented by this NTP timestamp.
138 |  |
          */
139 |  |
         public long getSeconds()
140 |  |
         {
141 | 4 |
             return (ntpTime >>> 32) & 0xffffffffL;
142 |  |
         }
143 |  |
144 |  |
         /***
145 |  |
          * Returns low-order 32-bits representing the fractional seconds.
146 |  |
          *
147 |  |
          * @return fractional seconds represented by this NTP timestamp.
148 |  |
          */
149 |  |
         public long getFraction()
150 |  |
         {
151 | 4 |
             return ntpTime & 0xffffffffL;
152 |  |
         }
153 |  |
154 |  |
         /***
155 |  |
          * Convert NTP timestamp to Java standard time.
156 |  |
          *
157 |  |
          * @return NTP Timestamp in Java time
158 |  |
          */
159 |  |
         public long getTime()
160 |  |
         {
161 | 8 |
             return getTime(ntpTime);
162 |  |
         }
163 |  |
164 |  |
         /***
165 |  |
          * Convert NTP timestamp to Java Date object.
166 |  |
          *
167 |  |
          * @return NTP Timestamp in Java Date
168 |  |
          */
169 |  |
         public Date getDate()
170 |  |
         {
171 | 4 |
             long time = getTime(ntpTime);
172 | 4 |
             return new Date(time);
173 |  |
         }
174 |  |
175 |  |
         /***
176 |  |
          * Convert 64-bit NTP timestamp to Java standard time.
177 |  |
          *
178 |  |
          * Note that java time (milliseconds) by definition has less precision
179 |  |
          * then NTP time (picoseconds) so converting NTP timestamp to java time and back
180 |  |
          * to NTP timestamp loses precision. For example, Tue, Dec 17 2002 09:07:24.810 EST
181 |  |
          * is represented by a single Java-based time value of f22cd1fc8a, but its
182 |  |
          * NTP equivalent are all values ranging from c1a9ae1c.cf5c28f5 to c1a9ae1c.cf9db22c.
183 |  |
          *
184 |  |
          * @param ntpTimeValue
185 |  |
          * @return the number of milliseconds since January 1, 1970, 00:00:00 GMT
186 |  |
          * represented by this NTP timestamp value.
187 |  |
          */
188 |  |
         public static long getTime(class="keyword">long ntpTimeValue)
189 |  |
         {
190 | 12 |
             long seconds = (ntpTimeValue >>> 32) & 0xffffffffL;	// high-order 32-bits
191 | 12 |
             long fraction = ntpTimeValue & 0xffffffffL;		// low-order 32-bits
192 |  |
193 |  |
             // Use round-off on fractional part to preserve going to lower precision
194 | 12 |
             fraction = Math.round(1000D * fraction / 0x100000000L);
195 |  |
196 |  |
             /*
197 |  |
              * If the most significant bit (MSB) on the seconds field is set we use
198 |  |
              * a different time base. The following text is a quote from RFC-2030 (SNTP v4):
199 |  |
              *
200 |  |
              *  If bit 0 is set, the UTC time is in the range 1968-2036 and UTC time
201 |  |
              *  is reckoned from 0h 0m 0s UTC on 1 January 1900. If bit 0 is not set,
202 |  |
              *  the time is in the range 2036-2104 and UTC time is reckoned from
203 |  |
              *  6h 28m 16s UTC on 7 February 2036.
204 |  |
              */
205 | 12 |
             long msb = seconds & 0x80000000L;
206 | 12 |
             if (msb == 0) {
207 |  |
                 // use base: 7-Feb-2036 @ 06:28:16 UTC
208 | 0 |
                 return msb0baseTime + (seconds * 1000) + fraction;
209 |  |
             } else {
210 |  |
                 // use base: 1-Jan-1900 @ 01:00:00 UTC
211 | 12 |
                 return msb1baseTime + (seconds * 1000) + fraction;
212 |  |
             }
213 |  |
         }
214 |  |
215 |  |
         /***
216 |  |
          * Helper method to convert Java time to NTP timestamp object.
217 |  |
          * Note that Java time (milliseconds) by definition has less precision
218 |  |
          * then NTP time (picoseconds) so converting Ntptime to Javatime and back
219 |  |
          * to Ntptime loses precision. For example, Tue, Dec 17 2002 09:07:24.810
220 |  |
          * is represented by a single Java-based time value of f22cd1fc8a, but its
221 |  |
          * NTP equivalent are all values from c1a9ae1c.cf5c28f5 to c1a9ae1c.cf9db22c.
222 |  |
          * @param   date   the milliseconds since January 1, 1970, 00:00:00 GMT.
223 |  |
          * @return NTP timestamp object at the specified date.
224 |  |
          */
225 |  |
         public static TimeStamp getNtpTime(long date)
226 |  |
         {
227 | 0 |
             return new TimeStamp(toNtpTime(date));
228 |  |
         }
229 |  |
230 |  |
         /***
231 |  |
          * Constructs a NTP timestamp object and initializes it so that
232 |  |
          * it represents the time at which it was allocated, measured to the
233 |  |
          * nearest millisecond.
234 |  |
          * @return NTP timestamp object set to the current time.
235 |  |
          * @see     java.lang.System#currentTimeMillis()
236 |  |
          */
237 |  |
         public static TimeStamp getCurrentTime()
238 |  |
         {
239 | 0 |
             return getNtpTime(System.currentTimeMillis());
240 |  |
         }
241 |  |
242 |  |
         /***
243 |  |
          * Convert NTP timestamp hexstring (e.g. "c1a089bd.fc904f6d") to the NTP
244 |  |
          * 64-bit unsigned fixed-point number.
245 |  |
          *
246 |  |
          * @return NTP 64-bit timestamp value.
247 |  |
          * @throws NumberFormatException - if the string does not contain a parsable timestamp.
248 |  |
          */
249 |  |
         protected static long decodeNtpHexString(String s)
250 |  |
                 throws NumberFormatException
251 |  |
         {
252 | 10 |
             if (s == null) {
253 | 0 |
                 throw new NumberFormatException("null");
254 |  |
             }
255 | 10 |
             int ind = s.indexOf('.');
256 | 10 |
             if (ind == -1) {
257 | 0 |
                 if (s.length() == 0) return 0;
258 | 0 |
                 return Long.parseLong(s, 16) << 32; // no decimal
259 |  |
             }
260 |  |
261 | 10 |
             return Long.parseLong(s.substring(0, ind), 16) << 32 |
262 |  |
                     Long.parseLong(s.substring(ind + 1), 16);
263 |  |
         }
264 |  |
265 |  |
         /***
266 |  |
          * Parses the string argument as a NTP hexidecimal timestamp representation string
267 |  |
          * (e.g. "c1a089bd.fc904f6d").
268 |  |
          *
269 |  |
          * @param s - hexstring.
270 |  |
          * @return the Timestamp represented by the argument in hexidecimal.
271 |  |
          * @throws NumberFormatException - if the string does not contain a parsable timestamp.
272 |  |
          */
273 |  |
         public static TimeStamp parseNtpString(String s)
274 |  |
                 throws NumberFormatException
275 |  |
         {
276 | 0 |
             return new TimeStamp(decodeNtpHexString(s));
277 |  |
         }
278 |  |
279 |  |
         /***
280 |  |
          * Converts Java time to 64-bit NTP time representation.
281 |  |
          *
282 |  |
          * @param t Java time
283 |  |
          * @return NTP timestamp representation of Java time value.
284 |  |
          */
285 |  |
         protected static long toNtpTime(class="keyword">long t)
286 |  |
         {
287 | 2 |
             boolean useBase1 = t < msb0baseTime;	// time < Feb-2036
288 |  |
             long baseTime;
289 | 2 |
             if (useBase1) {
290 | 2 |
                 baseTime = t - msb1baseTime; // dates <= Feb-2036
291 |  |
             } else {
292 |  |
                 // if base0 needed for dates >= Feb-2036
293 | 0 |
                 baseTime = t - msb0baseTime;
294 |  |
             }
295 |  |
296 | 2 |
             long seconds = baseTime / 1000;
297 | 2 |
             long fraction = ((baseTime % 1000) * 0x100000000L) / 1000;
298 |  |
299 | 2 |
             if (useBase1) {
300 | 2 |
                 seconds |= 0x80000000L; // set high-order bit if msb1baseTime 1900 used
301 |  |
             }
302 |  |
303 | 2 |
             long time = seconds << 32 | fraction;
304 | 2 |
             return time;
305 |  |
         }
306 |  |
307 |  |
         /***
308 |  |
          * Computes a hashcode for this Timestamp. The result is the exclusive
309 |  |
          * OR of the two halves of the primitive <code>long</code> value
310 |  |
          * represented by this <code>TimeStamp</code> object. That is, the hashcode
311 |  |
          * is the value of the expression:
312 |  |
          * <blockquote><pre>
313 |  |
          * (int)(this.ntpValue()^(this.ntpValue() >>> 32))
314 |  |
          * </pre></blockquote>
315 |  |
          *
316 |  |
          * @return  a hash code value for this object.
317 |  |
          */
318 |  |
         public int hashCode()
319 |  |
         {
320 | 8 |
             return (int) (ntpTime ^ (ntpTime >>> 32));
321 |  |
         }
322 |  |
323 |  |
         /***
324 |  |
          * Compares this object against the specified object.
325 |  |
          * The result is <code>true</code> if and only if the argument is
326 |  |
          * not <code>null</code> and is a <code>Long</code> object that
327 |  |
          * contains the same <code>long</code> value as this object.
328 |  |
          *
329 |  |
          * @param   obj   the object to compare with.
330 |  |
          * @return  <code>true</code> if the objects are the same;
331 |  |
          *          <code>false</code> otherwise.
332 |  |
          */
333 |  |
         public boolean equals(Object obj)
334 |  |
         {
335 | 8 |
             if (obj instanceof TimeStamp) {
336 | 8 |
                 return ntpTime == ((TimeStamp) obj).ntpValue();
337 |  |
             }
338 | 0 |
             return false;
339 |  |
         }
340 |  |
341 |  |
         /***
342 |  |
          * Converts this <code>TimeStamp</code> object to a <code>String</code>.
343 |  |
          * The NTP timestamp 64-bit long value is represented as hex string with
344 |  |
          * seconds separated by fractional seconds by a decimal point;
345 |  |
          * e.g. c1a089bd.fc904f6d <=> Tue, Dec 10 2002 10:41:49.986
346 |  |
          *
347 |  |
          * @return NTP timestamp 64-bit long value as hex string with seconds
348 |  |
          * separated by fractional seconds.
349 |  |
          */
350 |  |
         public String toString()
351 |  |
         {
352 | 0 |
             return toString(ntpTime);
353 |  |
         }
354 |  |
355 |  |
         /***
356 |  |
          * Left-pad 8-character hex string with 0's
357 |  |
          *
358 |  |
          * @param buf - StringBuffer which is appended with leading 0's.
359 |  |
          * @param l - a long.
360 |  |
          */
361 |  |
         private static void appendHexString(StringBuffer buf, long l)
362 |  |
         {
363 | 0 |
             String s = Long.toHexString(l);
364 | 0 |
             for (int i = s.length(); i < 8; i++)
365 | 0 |
                 buf.append('0');
366 | 0 |
             buf.append(s);
367 | 0 |
         }
368 |  |
369 |  |
         /***
370 |  |
          * Converts 64-bit NTP timestamp value to a <code>String</code>.
371 |  |
          * The NTP timestamp value is represented as hex string with
372 |  |
          * seconds separated by fractional seconds by a decimal point;
373 |  |
          * e.g. c1a089bd.fc904f6d <=> Tue, Dec 10 2002 10:41:49.986
374 |  |
          *
375 |  |
          * @return NTP timestamp 64-bit long value as hex string with seconds
376 |  |
          * separated by fractional seconds.
377 |  |
          */
378 |  |
         public static String toString(long ntpTime)
379 |  |
         {
380 | 0 |
             StringBuffer buf = new StringBuffer();
381 |  |
             // high-order second bits (32..63) as hexstring
382 | 0 |
             appendHexString(buf, (ntpTime >>> 32) & 0xffffffffL);
383 |  |
384 |  |
             // low-order fractional seconds bits (0..31) as hexstring
385 | 0 |
             buf.append('.');
386 | 0 |
             appendHexString(buf, ntpTime & 0xffffffffL);
387 |  |
388 | 0 |
             return buf.toString();
389 |  |
         }
390 |  |
391 |  |
         /***
392 |  |
          * Converts this <code>TimeStamp</code> object to a <code>String</code>
393 |  |
          * of the form:
394 |  |
          * <blockquote><pre>
395 |  |
          * EEE, MMM dd yyyy HH:mm:ss.SSS</pre></blockquote>
396 |  |
          * See java.text.SimpleDataFormat for code descriptions.
397 |  |
          *
398 |  |
          * @return  a string representation of this date.
399 |  |
          */
400 |  |
         public String toDateString()
401 |  |
         {
402 | 0 |
             DateFormat formatter = null;
403 | 0 |
             if (simpleFormatter != null) {
404 | 0 |
                 formatter = (DateFormat) simpleFormatter.get();
405 |  |
             }
406 | 0 |
             if (formatter == null) {
407 |  |
                 // No cache yet, or cached formatter GC'd
408 | 0 |
                 formatter = new SimpleDateFormat(NTP_DATE_FORMAT, Locale.US);
409 | 0 |
                 formatter.setTimeZone(TimeZone.getDefault());
410 | 0 |
                 simpleFormatter = new SoftReference(formatter);
411 |  |
             }
412 | 0 |
             Date ntpDate = getDate();
413 | 0 |
             synchronized (formatter) {
414 | 0 |
                 return formatter.format(ntpDate);
415 | 0 |
             }
416 |  |
         }
417 |  |
418 |  |
         /***
419 |  |
          * Converts this <code>TimeStamp</code> object to a <code>String</code>
420 |  |
          * of the form:
421 |  |
          * <blockquote><pre>
422 |  |
          * EEE, MMM dd yyyy HH:mm:ss.SSS UTC</pre></blockquote>
423 |  |
          * See java.text.SimpleDataFormat for code descriptions.
424 |  |
          *
425 |  |
          * @return  a string representation of this date in UTC.
426 |  |
          */
427 |  |
         public String toUTCString()
428 |  |
         {
429 | 2 |
             DateFormat formatter = null;
430 | 2 |
             if (utcFormatter != null)
431 | 0 |
                 formatter = (DateFormat) utcFormatter.get();
432 | 2 |
             if (formatter == null) {
433 |  |
                 // No cache yet, or cached formatter GC'd
434 | 2 |
                 formatter = new SimpleDateFormat(NTP_DATE_FORMAT + " 'UTC'",
435 |  |
                         Locale.US);
436 | 2 |
                 formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
437 | 2 |
                 utcFormatter = new SoftReference(formatter);
438 |  |
             }
439 | 2 |
             Date ntpDate = getDate();
440 | 2 |
             synchronized (formatter) {
441 | 2 |
                 return formatter.format(ntpDate);
442 | 0 |
             }
443 |  |
         }
444 |  |
445 |  |
         /***
446 |  |
          * Compares two Timestamps numerically.
447 |  |
          *
448 |  |
          * @param   anotherTimeStamp - the <code>TimeStamp</code> to be compared.
449 |  |
          * @return  the value <code>0</code> if the argument TimeStamp is equal to
450 |  |
          *          this TimeStamp; a value less than <code>0</code> if this TimeStamp
451 |  |
          *          is numerically less than the TimeStamp argument; and a
452 |  |
          *          value greater than <code>0</code> if this TimeStamp is
453 |  |
          *          numerically greater than the TimeStamp argument
454 |  |
          *		(signed comparison).
455 |  |
          */
456 |  |
         public int compareTo(TimeStamp anotherTimeStamp)
457 |  |
         {
458 | 4 |
             long thisVal = this.ntpTime;
459 | 4 |
             long anotherVal = anotherTimeStamp.ntpTime;
460 | 4 |
             return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1));
461 |  |
         }
462 |  |
463 |  |
         /***
464 |  |
          * Compares this TimeStamp to another Object.  If the Object is a TimeStamp,
465 |  |
          * this function behaves like <code>compareTo(TimeStamp)</code>.  Otherwise,
466 |  |
          * it throws a <code>ClassCastException</code> (as TimeStamps are comparable
467 |  |
          * only to other TimeStamps).
468 |  |
          *
469 |  |
          * @param   o the <code>Object</code> to be compared.
470 |  |
          * @return  the value <code>0</code> if the argument is a TimeStamp
471 |  |
          *		numerically equal to this TimeStamp; a value less than
472 |  |
          *		<code>0</code> if the argument is a TimeStamp numerically
473 |  |
          *		greater than this TimeStamp; and a value greater than
474 |  |
          *		<code>0</code> if the argument is a TimeStamp numerically
475 |  |
          *		less than this TimeStamp.
476 |  |
          * @exception ClassCastException if the argument is not a
477 |  |
          *		  <code>TimeStamp</code>.
478 |  |
          * @see     java.lang.Comparable
479 |  |
          */
480 |  |
         public int compareTo(Object o)
481 |  |
         {
482 | 0 |
             return compareTo((TimeStamp) o);
483 |  |
         }
484 |  |
485 |  |
     }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.