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 15:09:55 -0500 (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  1
     private static SoftReference simpleFormatter = null;
 67  1
     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  5
     {
 110  5
         ntpTime = decodeNtpHexString(s);
 111  5
     }
 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  1
     {
 121  1
         ntpTime = (d == null) ? 0 : toNtpTime(d.getTime());
 122  1
     }
 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  8
         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  2
         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  2
         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  4
         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  2
         long time = getTime(ntpTime);
 172  2
         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  6
         long seconds = (ntpTimeValue >>> 32) & 0xffffffffL;	// high-order 32-bits
 191  6
         long fraction = ntpTimeValue & 0xffffffffL;		// low-order 32-bits
 192  
 
 193  
         // Use round-off on fractional part to preserve going to lower precision
 194  6
         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  6
         long msb = seconds & 0x80000000L;
 206  6
         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  6
             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  5
         if (s == null) {
 253  0
             throw new NumberFormatException("null");
 254  
         }
 255  5
         int ind = s.indexOf('.');
 256  5
         if (ind == -1) {
 257  0
             if (s.length() == 0) return 0;
 258  0
             return Long.parseLong(s, 16) << 32; // no decimal
 259  
         }
 260  
 
 261  5
         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  1
         boolean useBase1 = t < msb0baseTime;	// time < Feb-2036
 288  
         long baseTime;
 289  1
         if (useBase1) {
 290  1
             baseTime = t - msb1baseTime; // dates <= Feb-2036
 291  
         } else {
 292  
             // if base0 needed for dates >= Feb-2036
 293  0
             baseTime = t - msb0baseTime;
 294  
         }
 295  
 
 296  1
         long seconds = baseTime / 1000;
 297  1
         long fraction = ((baseTime % 1000) * 0x100000000L) / 1000;
 298  
 
 299  1
         if (useBase1) {
 300  1
             seconds |= 0x80000000L; // set high-order bit if msb1baseTime 1900 used
 301  
         }
 302  
 
 303  1
         long time = seconds << 32 | fraction;
 304  1
         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  4
         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  4
         if (obj instanceof TimeStamp) {
 336  4
             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  1
         DateFormat formatter = null;
 430  1
         if (utcFormatter != null)
 431  0
             formatter = (DateFormat) utcFormatter.get();
 432  1
         if (formatter == null) {
 433  
             // No cache yet, or cached formatter GC'd
 434  1
             formatter = new SimpleDateFormat(NTP_DATE_FORMAT + " 'UTC'",
 435  
                     Locale.US);
 436  1
             formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
 437  1
             utcFormatter = new SoftReference(formatter);
 438  
         }
 439  1
         Date ntpDate = getDate();
 440  1
         synchronized (formatter) {
 441  1
             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  2
         long thisVal = this.ntpTime;
 459  2
         long anotherVal = anotherTimeStamp.ntpTime;
 460  2
         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.