1 /*
2 * Copyright 2001-2011 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.base;
17
18 import java.io.Serializable;
19
20 import org.joda.time.Chronology;
21 import org.joda.time.DateTimeUtils;
22 import org.joda.time.DateTimeZone;
23 import org.joda.time.ReadableDateTime;
24 import org.joda.time.chrono.ISOChronology;
25 import org.joda.time.convert.ConverterManager;
26 import org.joda.time.convert.InstantConverter;
27
28 /**
29 * BaseDateTime is an abstract implementation of ReadableDateTime that stores
30 * data in <code>long</code> and <code>Chronology</code> fields.
31 * <p>
32 * This class should generally not be used directly by API users.
33 * The {@link ReadableDateTime} interface should be used when different
34 * kinds of date/time objects are to be referenced.
35 * <p>
36 * BaseDateTime subclasses may be mutable and not thread-safe.
37 *
38 * @author Stephen Colebourne
39 * @author Kandarp Shah
40 * @author Brian S O'Neill
41 * @since 1.0
42 */
43 public abstract class BaseDateTime
44 extends AbstractDateTime
45 implements ReadableDateTime, Serializable {
46
47 /** Serialization lock */
48 private static final long serialVersionUID = -6728882245981L;
49
50 /** The millis from 1970-01-01T00:00:00Z */
51 private volatile long iMillis;
52 /** The chronology to use */
53 private volatile Chronology iChronology;
54
55 //-----------------------------------------------------------------------
56 /**
57 * Constructs an instance set to the current system millisecond time
58 * using <code>ISOChronology</code> in the default time zone.
59 */
60 public BaseDateTime() {
61 this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance());
62 }
63
64 /**
65 * Constructs an instance set to the current system millisecond time
66 * using <code>ISOChronology</code> in the specified time zone.
67 * <p>
68 * If the specified time zone is null, the default zone is used.
69 *
70 * @param zone the time zone, null means default zone
71 */
72 public BaseDateTime(DateTimeZone zone) {
73 this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance(zone));
74 }
75
76 /**
77 * Constructs an instance set to the current system millisecond time
78 * using the specified chronology.
79 * <p>
80 * If the chronology is null, <code>ISOChronology</code>
81 * in the default time zone is used.
82 *
83 * @param chronology the chronology, null means ISOChronology in default zone
84 */
85 public BaseDateTime(Chronology chronology) {
86 this(DateTimeUtils.currentTimeMillis(), chronology);
87 }
88
89 //-----------------------------------------------------------------------
90 /**
91 * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z
92 * using <code>ISOChronology</code> in the default time zone.
93 *
94 * @param instant the milliseconds from 1970-01-01T00:00:00Z
95 */
96 public BaseDateTime(long instant) {
97 this(instant, ISOChronology.getInstance());
98 }
99
100 /**
101 * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z
102 * using <code>ISOChronology</code> in the specified time zone.
103 * <p>
104 * If the specified time zone is null, the default zone is used.
105 *
106 * @param instant the milliseconds from 1970-01-01T00:00:00Z
107 * @param zone the time zone, null means default zone
108 */
109 public BaseDateTime(long instant, DateTimeZone zone) {
110 this(instant, ISOChronology.getInstance(zone));
111 }
112
113 /**
114 * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z
115 * using the specified chronology.
116 * <p>
117 * If the chronology is null, <code>ISOChronology</code>
118 * in the default time zone is used.
119 *
120 * @param instant the milliseconds from 1970-01-01T00:00:00Z
121 * @param chronology the chronology, null means ISOChronology in default zone
122 */
123 public BaseDateTime(long instant, Chronology chronology) {
124 super();
125 iChronology = checkChronology(chronology);
126 iMillis = checkInstant(instant, iChronology);
127 }
128
129 //-----------------------------------------------------------------------
130 /**
131 * Constructs an instance from an Object that represents a datetime,
132 * forcing the time zone to that specified.
133 * <p>
134 * If the object contains no chronology, <code>ISOChronology</code> is used.
135 * If the specified time zone is null, the default zone is used.
136 * <p>
137 * The recognised object types are defined in
138 * {@link org.joda.time.convert.ConverterManager ConverterManager} and
139 * include ReadableInstant, String, Calendar and Date.
140 *
141 * @param instant the datetime object
142 * @param zone the time zone
143 * @throws IllegalArgumentException if the instant is invalid
144 */
145 public BaseDateTime(Object instant, DateTimeZone zone) {
146 super();
147 InstantConverter converter = ConverterManager.getInstance().getInstantConverter(instant);
148 Chronology chrono = checkChronology(converter.getChronology(instant, zone));
149 iChronology = chrono;
150 iMillis = checkInstant(converter.getInstantMillis(instant, chrono), chrono);
151 }
152
153 /**
154 * Constructs an instance from an Object that represents a datetime,
155 * using the specified chronology.
156 * <p>
157 * If the chronology is null, ISO in the default time zone is used.
158 * <p>
159 * The recognised object types are defined in
160 * {@link org.joda.time.convert.ConverterManager ConverterManager} and
161 * include ReadableInstant, String, Calendar and Date.
162 *
163 * @param instant the datetime object
164 * @param chronology the chronology
165 * @throws IllegalArgumentException if the instant is invalid
166 */
167 public BaseDateTime(Object instant, Chronology chronology) {
168 super();
169 InstantConverter converter = ConverterManager.getInstance().getInstantConverter(instant);
170 iChronology = checkChronology(converter.getChronology(instant, chronology));
171 iMillis = checkInstant(converter.getInstantMillis(instant, chronology), iChronology);
172 }
173
174 //-----------------------------------------------------------------------
175 /**
176 * Constructs an instance from datetime field values
177 * using <code>ISOChronology</code> in the default time zone.
178 *
179 * @param year the year
180 * @param monthOfYear the month of the year
181 * @param dayOfMonth the day of the month
182 * @param hourOfDay the hour of the day
183 * @param minuteOfHour the minute of the hour
184 * @param secondOfMinute the second of the minute
185 * @param millisOfSecond the millisecond of the second
186 */
187 public BaseDateTime(
188 int year,
189 int monthOfYear,
190 int dayOfMonth,
191 int hourOfDay,
192 int minuteOfHour,
193 int secondOfMinute,
194 int millisOfSecond) {
195 this(year, monthOfYear, dayOfMonth, hourOfDay,
196 minuteOfHour, secondOfMinute, millisOfSecond, ISOChronology.getInstance());
197 }
198
199 /**
200 * Constructs an instance from datetime field values
201 * using <code>ISOChronology</code> in the specified time zone.
202 * <p>
203 * If the specified time zone is null, the default zone is used.
204 *
205 * @param year the year
206 * @param monthOfYear the month of the year
207 * @param dayOfMonth the day of the month
208 * @param hourOfDay the hour of the day
209 * @param minuteOfHour the minute of the hour
210 * @param secondOfMinute the second of the minute
211 * @param millisOfSecond the millisecond of the second
212 * @param zone the time zone, null means default time zone
213 */
214 public BaseDateTime(
215 int year,
216 int monthOfYear,
217 int dayOfMonth,
218 int hourOfDay,
219 int minuteOfHour,
220 int secondOfMinute,
221 int millisOfSecond,
222 DateTimeZone zone) {
223 this(year, monthOfYear, dayOfMonth, hourOfDay,
224 minuteOfHour, secondOfMinute, millisOfSecond, ISOChronology.getInstance(zone));
225 }
226
227 /**
228 * Constructs an instance from datetime field values
229 * using the specified chronology.
230 * <p>
231 * If the chronology is null, <code>ISOChronology</code>
232 * in the default time zone is used.
233 *
234 * @param year the year
235 * @param monthOfYear the month of the year
236 * @param dayOfMonth the day of the month
237 * @param hourOfDay the hour of the day
238 * @param minuteOfHour the minute of the hour
239 * @param secondOfMinute the second of the minute
240 * @param millisOfSecond the millisecond of the second
241 * @param chronology the chronology, null means ISOChronology in default zone
242 */
243 public BaseDateTime(
244 int year,
245 int monthOfYear,
246 int dayOfMonth,
247 int hourOfDay,
248 int minuteOfHour,
249 int secondOfMinute,
250 int millisOfSecond,
251 Chronology chronology) {
252 super();
253 iChronology = checkChronology(chronology);
254 long instant = iChronology.getDateTimeMillis(year, monthOfYear, dayOfMonth,
255 hourOfDay, minuteOfHour, secondOfMinute, millisOfSecond);
256 iMillis = checkInstant(instant, iChronology);
257 }
258
259 //-----------------------------------------------------------------------
260 /**
261 * Checks the specified chronology before storing it, potentially altering it.
262 * This method must not access any instance variables.
263 * <p>
264 * This implementation converts nulls to ISOChronology in the default zone.
265 *
266 * @param chronology the chronology to use, may be null
267 * @return the chronology to store in this datetime, not null
268 */
269 protected Chronology checkChronology(Chronology chronology) {
270 return DateTimeUtils.getChronology(chronology);
271 }
272
273 /**
274 * Checks the specified instant before storing it, potentially altering it.
275 * This method must not access any instance variables.
276 * <p>
277 * This implementation simply returns the instant.
278 *
279 * @param instant the milliseconds from 1970-01-01T00:00:00Z to round
280 * @param chronology the chronology to use, not null
281 * @return the instant to store in this datetime
282 */
283 protected long checkInstant(long instant, Chronology chronology) {
284 return instant;
285 }
286
287 //-----------------------------------------------------------------------
288 /**
289 * Gets the milliseconds of the datetime instant from the Java epoch
290 * of 1970-01-01T00:00:00Z.
291 *
292 * @return the number of milliseconds since 1970-01-01T00:00:00Z
293 */
294 public long getMillis() {
295 return iMillis;
296 }
297
298 /**
299 * Gets the chronology of the datetime.
300 *
301 * @return the Chronology that the datetime is using
302 */
303 public Chronology getChronology() {
304 return iChronology;
305 }
306
307 //-----------------------------------------------------------------------
308 /**
309 * Sets the milliseconds of the datetime.
310 * <p>
311 * All changes to the millisecond field occurs via this method.
312 * Override and block this method to make a subclass immutable.
313 *
314 * @param instant the milliseconds since 1970-01-01T00:00:00Z to set the datetime to
315 */
316 protected void setMillis(long instant) {
317 iMillis = checkInstant(instant, iChronology);
318 }
319
320 /**
321 * Sets the chronology of the datetime.
322 * <p>
323 * All changes to the chronology field occurs via this method.
324 * Override and block this method to make a subclass immutable.
325 *
326 * @param chronology the chronology to set
327 */
328 protected void setChronology(Chronology chronology) {
329 iChronology = checkChronology(chronology);
330 }
331
332 }