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 }