View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  
21  package org.apache.directory.server.ntp.messages;
22  
23  
24  import java.nio.ByteBuffer;
25  import java.text.SimpleDateFormat;
26  import java.util.Date;
27  import java.util.Locale;
28  import java.util.TimeZone;
29  
30  
31  /**
32   * NTP timestamps are represented as a 64-bit unsigned fixed-point number,
33   * in seconds relative to 0h on 1 January 1900. The integer part is in the
34   * first 32 bits and the fraction part in the last 32 bits. In the fraction
35   * part, the non-significant low order can be set to 0.
36   * 
37   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
38   */
39  public class NtpTimeStamp
40  {
41      /**
42       * The number of milliseconds difference between the Java epoch and
43       * the NTP epoch ( January 1, 1900, 00:00:00 GMT ).
44       */
45      private static final long NTP_EPOCH_DIFFERENCE = -2208988800000L;
46  
47      private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS z", Locale.ROOT );
48  
49      private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" );
50      
51      static
52      {
53          DATE_FORMAT.setTimeZone( UTC_TIME_ZONE );
54      }
55  
56      private long seconds = 0;
57      private long fraction = 0;
58  
59  
60      /**
61       * Creates a new instance of NtpTimeStamp that represents the time "right now."
62       */
63      public NtpTimeStamp()
64      {
65          this( new Date() );
66      }
67  
68  
69      /**
70       * Creates a new instance of NtpTimeStamp that represents the given {@link Date}.
71       *
72       * @param date
73       */
74      public NtpTimeStamp( Date date )
75      {
76          long msSinceStartOfNtpEpoch = date.getTime() - NTP_EPOCH_DIFFERENCE;
77  
78          seconds = msSinceStartOfNtpEpoch / 1000;
79          fraction = ( ( msSinceStartOfNtpEpoch % 1000 ) * 0x100000000L ) / 1000;
80      }
81  
82  
83      /**
84       * Creates a new instance of NtpTimeStamp from encoded data in a {@link ByteBuffer}.
85       *
86       * @param data
87       */
88      public NtpTimeStamp( ByteBuffer data )
89      {
90          for ( int ii = 0; ii < 4; ii++ )
91          {
92              seconds = 256 * seconds + makePositive( data.get() );
93          }
94  
95          for ( int ii = 4; ii < 8; ii++ )
96          {
97              fraction = 256 * fraction + makePositive( data.get() );
98          }
99      }
100 
101 
102     /**
103      * Writes this {@link NtpTimeStamp} to the given {@link ByteBuffer}.
104      *
105      * @param buffer
106      */
107     public void writeTo( ByteBuffer buffer )
108     {
109         byte[] bytes = new byte[8];
110 
111         long temp = seconds;
112         for ( int ii = 3; ii >= 0; ii-- )
113         {
114             bytes[ii] = ( byte ) ( temp % 256 );
115             temp = temp / 256;
116         }
117 
118         temp = fraction;
119         for ( int ii = 7; ii >= 4; ii-- )
120         {
121             bytes[ii] = ( byte ) ( temp % 256 );
122             temp = temp / 256;
123         }
124 
125         buffer.put( bytes );
126     }
127 
128 
129     public String toString()
130     {
131         long msSinceStartOfNtpEpoch = seconds * 1000 + ( fraction * 1000 ) / 0x100000000L;
132         Date date = new Date( msSinceStartOfNtpEpoch + NTP_EPOCH_DIFFERENCE );
133 
134         synchronized ( DATE_FORMAT )
135         {
136             return "org.apache.ntp.message.NtpTimeStamp[ date = " + DATE_FORMAT.format( date ) + " ]";
137         }
138     }
139 
140 
141     /**
142      * {@inheritDoc}
143      */
144     @Override
145     public int hashCode()
146     {
147         int hash = 37;
148         hash = hash * 17 + Long.valueOf( seconds ).hashCode();
149         hash = hash * 17 + Long.valueOf( fraction ).hashCode();
150 
151         return hash;
152     }
153 
154 
155     /**
156      * {@inheritDoc}
157      */
158     @Override
159     public boolean equals( Object o )
160     {
161         if ( this == o )
162         {
163             return true;
164         }
165 
166         if ( !( o instanceof NtpTimeStamp ) )
167         {
168             return false;
169         }
170 
171         NtpTimeStamp/../../../../org/apache/directory/server/ntp/messages/NtpTimeStamp.html#NtpTimeStamp">NtpTimeStamp that = ( NtpTimeStamp ) o;
172         return ( this.seconds == that.seconds ) && ( this.fraction == that.fraction );
173     }
174 
175 
176     private int makePositive( byte b )
177     {
178         int byteAsInt = b;
179         return ( byteAsInt < 0 ) ? 256 + byteAsInt : byteAsInt;
180     }
181 }