001    /*
002     *  Copyright 2001-2005 Stephen Colebourne
003     *
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package org.joda.time.field;
017    
018    import org.joda.time.DurationFieldType;
019    
020    /**
021     * Duration field class representing a field with a fixed unit length.
022     * <p>
023     * PreciseDurationField is thread-safe and immutable.
024     * 
025     * @author Stephen Colebourne
026     * @author Brian S O'Neill
027     * @since 1.0
028     */
029    public class PreciseDurationField extends BaseDurationField {
030        
031        private static final long serialVersionUID = -8346152187724495365L;
032    
033        /** The size of the unit */
034        private final long iUnitMillis;
035    
036        /**
037         * Constructor.
038         * 
039         * @param type  the field type
040         * @param unitMillis  the unit milliseconds
041         */    
042        public PreciseDurationField(DurationFieldType type, long unitMillis) {
043            super(type);
044            iUnitMillis = unitMillis;
045        }
046        
047        //------------------------------------------------------------------------
048        /**
049         * This field is precise.
050         * 
051         * @return true always
052         */
053        public final boolean isPrecise() {
054            return true;
055        }
056        
057        /**
058         * Returns the amount of milliseconds per unit value of this field.
059         *
060         * @return the unit size of this field, in milliseconds
061         */
062        public final long getUnitMillis() {
063            return iUnitMillis;
064        }
065    
066        //------------------------------------------------------------------------
067        /**
068         * Get the value of this field from the milliseconds.
069         * 
070         * @param duration  the milliseconds to query, which may be negative
071         * @param instant  ignored
072         * @return the value of the field, in the units of the field, which may be
073         * negative
074         */
075        public long getValueAsLong(long duration, long instant) {
076            return duration / iUnitMillis;  // safe
077        }
078    
079        /**
080         * Get the millisecond duration of this field from its value.
081         * 
082         * @param value  the value of the field, which may be negative
083         * @param instant  ignored
084         * @return the milliseconds that the field represents, which may be
085         * negative
086         */
087        public long getMillis(int value, long instant) {
088            return value * iUnitMillis;  // safe
089        }
090    
091        /**
092         * Get the millisecond duration of this field from its value.
093         * 
094         * @param value  the value of the field, which may be negative
095         * @param instant  ignored
096         * @return the milliseconds that the field represents, which may be
097         * negative
098         */
099        public long getMillis(long value, long instant) {
100            return FieldUtils.safeMultiply(value, iUnitMillis);
101        }
102    
103        public long add(long instant, int value) {
104            long addition = value * iUnitMillis;  // safe
105            return FieldUtils.safeAdd(instant, addition);
106        }
107    
108        public long add(long instant, long value) {
109            long addition = FieldUtils.safeMultiply(value, iUnitMillis);
110            return FieldUtils.safeAdd(instant, addition);
111        }
112    
113        public long getDifferenceAsLong(long minuendInstant, long subtrahendInstant) {
114            long difference = FieldUtils.safeSubtract(minuendInstant, subtrahendInstant);
115            return difference / iUnitMillis;
116        }
117    
118        //-----------------------------------------------------------------------
119        /**
120         * Compares this duration field to another.
121         * Two fields are equal if of the same type and duration.
122         * 
123         * @param obj  the object to compare to
124         * @return if equal
125         */
126        public boolean equals(Object obj) {
127            if (this == obj) {
128                return true;
129            } else if (obj instanceof PreciseDurationField) {
130                PreciseDurationField other = (PreciseDurationField) obj;
131                return (getType() == other.getType()) && (iUnitMillis == other.iUnitMillis);
132            }
133            return false;
134        }
135    
136        /**
137         * Gets a hash code for this instance.
138         * 
139         * @return a suitable hashcode
140         */
141        public int hashCode() {
142            long millis = iUnitMillis;
143            int hash = (int) (millis ^ (millis >>> 32));
144            hash += getType().hashCode();
145            return hash;
146        }
147    
148    }