KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > joda > time > field > ImpreciseDateTimeField


1 /*
2  * Copyright 2001-2005 Stephen Colebourne
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.joda.time.field;
17
18 import org.joda.time.DateTimeFieldType;
19 import org.joda.time.DurationField;
20 import org.joda.time.DurationFieldType;
21
22 /**
23  * Abstract datetime field class that defines its own DurationField, which
24  * delegates back into this ImpreciseDateTimeField.
25  * <p>
26  * This DateTimeField is useful for defining DateTimeFields that are composed
27  * of imprecise durations. If both duration fields are precise, then a
28  * {@link PreciseDateTimeField} should be used instead.
29  * <p>
30  * When defining imprecise DateTimeFields where a matching DurationField is
31  * already available, just extend BaseDateTimeField directly so as not to
32  * create redundant DurationField instances.
33  * <p>
34  * ImpreciseDateTimeField is thread-safe and immutable, and its subclasses must
35  * be as well.
36  *
37  * @author Brian S O'Neill
38  * @see PreciseDateTimeField
39  * @since 1.0
40  */

41 public abstract class ImpreciseDateTimeField extends BaseDateTimeField {
42
43     private static final long serialVersionUID = 7190739608550251860L;
44
45     final long iUnitMillis;
46     private final DurationField iDurationField;
47
48     /**
49      * Constructor.
50      *
51      * @param type the field type
52      * @param unitMillis the average duration unit milliseconds
53      */

54     public ImpreciseDateTimeField(DateTimeFieldType type, long unitMillis) {
55         super(type);
56         iUnitMillis = unitMillis;
57         iDurationField = new LinkedDurationField(type.getDurationType());
58     }
59
60     public abstract int get(long instant);
61
62     public abstract long set(long instant, int value);
63
64     public abstract long add(long instant, int value);
65
66     public abstract long add(long instant, long value);
67
68     /**
69      * Computes the difference between two instants, as measured in the units
70      * of this field. Any fractional units are dropped from the result. Calling
71      * getDifference reverses the effect of calling add. In the following code:
72      *
73      * <pre>
74      * long instant = ...
75      * int v = ...
76      * int age = getDifference(add(instant, v), instant);
77      * </pre>
78      *
79      * The value 'age' is the same as the value 'v'.
80      * <p>
81      * The default implementation call getDifferenceAsLong and converts the
82      * return value to an int.
83      *
84      * @param minuendInstant the milliseconds from 1970-01-01T00:00:00Z to
85      * subtract from
86      * @param subtrahendInstant the milliseconds from 1970-01-01T00:00:00Z to
87      * subtract off the minuend
88      * @return the difference in the units of this field
89      */

90     public int getDifference(long minuendInstant, long subtrahendInstant) {
91         return FieldUtils.safeToInt(getDifferenceAsLong(minuendInstant, subtrahendInstant));
92     }
93
94     /**
95      * Computes the difference between two instants, as measured in the units
96      * of this field. Any fractional units are dropped from the result. Calling
97      * getDifference reverses the effect of calling add. In the following code:
98      *
99      * <pre>
100      * long instant = ...
101      * long v = ...
102      * long age = getDifferenceAsLong(add(instant, v), instant);
103      * </pre>
104      *
105      * The value 'age' is the same as the value 'v'.
106      * <p>
107      * The default implementation performs a guess-and-check algorithm using
108      * getDurationField().getUnitMillis() and the add() method. Subclasses are
109      * encouraged to provide a more efficient implementation.
110      *
111      * @param minuendInstant the milliseconds from 1970-01-01T00:00:00Z to
112      * subtract from
113      * @param subtrahendInstant the milliseconds from 1970-01-01T00:00:00Z to
114      * subtract off the minuend
115      * @return the difference in the units of this field
116      */

117     public long getDifferenceAsLong(long minuendInstant, long subtrahendInstant) {
118         if (minuendInstant < subtrahendInstant) {
119             return -getDifferenceAsLong(subtrahendInstant, minuendInstant);
120         }
121         
122         long difference = (minuendInstant - subtrahendInstant) / iUnitMillis;
123         if (add(subtrahendInstant, difference) < minuendInstant) {
124             do {
125                 difference++;
126             } while (add(subtrahendInstant, difference) <= minuendInstant);
127             difference--;
128         } else if (add(subtrahendInstant, difference) > minuendInstant) {
129             do {
130                 difference--;
131             } while (add(subtrahendInstant, difference) > minuendInstant);
132         }
133         return difference;
134     }
135
136     public final DurationField getDurationField() {
137         return iDurationField;
138     }
139
140     public abstract DurationField getRangeDurationField();
141
142     public abstract long roundFloor(long instant);
143
144     protected final long getDurationUnitMillis() {
145         return iUnitMillis;
146     }
147
148     private final class LinkedDurationField extends BaseDurationField {
149         private static final long serialVersionUID = -203813474600094134L;
150
151         LinkedDurationField(DurationFieldType type) {
152             super(type);
153         }
154     
155         public boolean isPrecise() {
156             return false;
157         }
158     
159         public long getUnitMillis() {
160             return iUnitMillis;
161         }
162
163         public int getValue(long duration, long instant) {
164             return ImpreciseDateTimeField.this
165                 .getDifference(instant + duration, instant);
166         }
167
168         public long getValueAsLong(long duration, long instant) {
169             return ImpreciseDateTimeField.this
170                 .getDifferenceAsLong(instant + duration, instant);
171         }
172         
173         public long getMillis(int value, long instant) {
174             return ImpreciseDateTimeField.this.add(instant, value) - instant;
175         }
176
177         public long getMillis(long value, long instant) {
178             return ImpreciseDateTimeField.this.add(instant, value) - instant;
179         }
180
181         public long add(long instant, int value) {
182             return ImpreciseDateTimeField.this.add(instant, value);
183         }
184         
185         public long add(long instant, long value) {
186             return ImpreciseDateTimeField.this.add(instant, value);
187         }
188         
189         public int getDifference(long minuendInstant, long subtrahendInstant) {
190             return ImpreciseDateTimeField.this
191                 .getDifference(minuendInstant, subtrahendInstant);
192         }
193         
194         public long getDifferenceAsLong(long minuendInstant, long subtrahendInstant) {
195             return ImpreciseDateTimeField.this
196                 .getDifferenceAsLong(minuendInstant, subtrahendInstant);
197         }
198     }
199
200 }
201
Popular Tags