001 /*
002 * Copyright 2001-2011 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.base;
017
018 import java.io.Serializable;
019
020 import org.joda.time.Chronology;
021 import org.joda.time.DateTimeUtils;
022 import org.joda.time.DateTimeZone;
023 import org.joda.time.ReadableDateTime;
024 import org.joda.time.chrono.ISOChronology;
025 import org.joda.time.convert.ConverterManager;
026 import org.joda.time.convert.InstantConverter;
027
028 /**
029 * BaseDateTime is an abstract implementation of ReadableDateTime that stores
030 * data in <code>long</code> and <code>Chronology</code> fields.
031 * <p>
032 * This class should generally not be used directly by API users.
033 * The {@link ReadableDateTime} interface should be used when different
034 * kinds of date/time objects are to be referenced.
035 * <p>
036 * BaseDateTime subclasses may be mutable and not thread-safe.
037 *
038 * @author Stephen Colebourne
039 * @author Kandarp Shah
040 * @author Brian S O'Neill
041 * @since 1.0
042 */
043 public abstract class BaseDateTime
044 extends AbstractDateTime
045 implements ReadableDateTime, Serializable {
046
047 /** Serialization lock */
048 private static final long serialVersionUID = -6728882245981L;
049
050 /** The millis from 1970-01-01T00:00:00Z */
051 private volatile long iMillis;
052 /** The chronology to use */
053 private volatile Chronology iChronology;
054
055 //-----------------------------------------------------------------------
056 /**
057 * Constructs an instance set to the current system millisecond time
058 * using <code>ISOChronology</code> in the default time zone.
059 */
060 public BaseDateTime() {
061 this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance());
062 }
063
064 /**
065 * Constructs an instance set to the current system millisecond time
066 * using <code>ISOChronology</code> in the specified time zone.
067 * <p>
068 * If the specified time zone is null, the default zone is used.
069 *
070 * @param zone the time zone, null means default zone
071 */
072 public BaseDateTime(DateTimeZone zone) {
073 this(DateTimeUtils.currentTimeMillis(), ISOChronology.getInstance(zone));
074 }
075
076 /**
077 * Constructs an instance set to the current system millisecond time
078 * using the specified chronology.
079 * <p>
080 * If the chronology is null, <code>ISOChronology</code>
081 * in the default time zone is used.
082 *
083 * @param chronology the chronology, null means ISOChronology in default zone
084 */
085 public BaseDateTime(Chronology chronology) {
086 this(DateTimeUtils.currentTimeMillis(), chronology);
087 }
088
089 //-----------------------------------------------------------------------
090 /**
091 * Constructs an instance set to the milliseconds from 1970-01-01T00:00:00Z
092 * using <code>ISOChronology</code> in the default time zone.
093 *
094 * @param instant the milliseconds from 1970-01-01T00:00:00Z
095 */
096 public BaseDateTime(long instant) {
097 this(instant, ISOChronology.getInstance());
098 }
099
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 }