001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 021package org.apache.directory.server.ntp.messages; 022 023 024import java.nio.ByteBuffer; 025import java.text.SimpleDateFormat; 026import java.util.Date; 027import java.util.Locale; 028import java.util.TimeZone; 029 030 031/** 032 * NTP timestamps are represented as a 64-bit unsigned fixed-point number, 033 * in seconds relative to 0h on 1 January 1900. The integer part is in the 034 * first 32 bits and the fraction part in the last 32 bits. In the fraction 035 * part, the non-significant low order can be set to 0. 036 * 037 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 038 */ 039public class NtpTimeStamp 040{ 041 /** 042 * The number of milliseconds difference between the Java epoch and 043 * the NTP epoch ( January 1, 1900, 00:00:00 GMT ). 044 */ 045 private static final long NTP_EPOCH_DIFFERENCE = -2208988800000L; 046 047 private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS z", Locale.ROOT ); 048 049 private static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone( "UTC" ); 050 051 static 052 { 053 DATE_FORMAT.setTimeZone( UTC_TIME_ZONE ); 054 } 055 056 private long seconds = 0; 057 private long fraction = 0; 058 059 060 /** 061 * Creates a new instance of NtpTimeStamp that represents the time "right now." 062 */ 063 public NtpTimeStamp() 064 { 065 this( new Date() ); 066 } 067 068 069 /** 070 * Creates a new instance of NtpTimeStamp that represents the given {@link Date}. 071 * 072 * @param date 073 */ 074 public NtpTimeStamp( Date date ) 075 { 076 long msSinceStartOfNtpEpoch = date.getTime() - NTP_EPOCH_DIFFERENCE; 077 078 seconds = msSinceStartOfNtpEpoch / 1000; 079 fraction = ( ( msSinceStartOfNtpEpoch % 1000 ) * 0x100000000L ) / 1000; 080 } 081 082 083 /** 084 * Creates a new instance of NtpTimeStamp from encoded data in a {@link ByteBuffer}. 085 * 086 * @param data 087 */ 088 public NtpTimeStamp( ByteBuffer data ) 089 { 090 for ( int ii = 0; ii < 4; ii++ ) 091 { 092 seconds = 256 * seconds + makePositive( data.get() ); 093 } 094 095 for ( int ii = 4; ii < 8; ii++ ) 096 { 097 fraction = 256 * fraction + makePositive( data.get() ); 098 } 099 } 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 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}