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 }