001 /* 002 * Copyright 2001-2005 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; 017 018 import java.io.Serializable; 019 020 import org.joda.time.base.BaseInterval; 021 import org.joda.time.field.FieldUtils; 022 import org.joda.time.format.ISODateTimeFormat; 023 import org.joda.time.format.ISOPeriodFormat; 024 025 /** 026 * MutableInterval is the standard implementation of a mutable time interval. 027 * <p> 028 * A time interval represents a period of time between two instants. 029 * Intervals are inclusive of the start instant and exclusive of the end. 030 * The end instant is always greater than or equal to the start instant. 031 * <p> 032 * Intervals have a fixed millisecond duration. 033 * This is the difference between the start and end instants. 034 * The duration is represented separately by {@link ReadableDuration}. 035 * As a result, intervals are not comparable. 036 * To compare the length of two intervals, you should compare their durations. 037 * <p> 038 * An interval can also be converted to a {@link ReadablePeriod}. 039 * This represents the difference between the start and end points in terms of fields 040 * such as years and days. 041 * <p> 042 * If performing significant calculations on an interval, it may be faster to 043 * convert an Interval object to a MutableInterval one. 044 * <p> 045 * MutableInterval is mutable and not thread-safe, unless concurrent threads 046 * are not invoking mutator methods. 047 * 048 * @author Stephen Colebourne 049 * @author Brian S O'Neill 050 * @since 1.0 051 */ 052 public class MutableInterval 053 extends BaseInterval 054 implements ReadWritableInterval, Cloneable, Serializable { 055 056 /** Serialization version */ 057 private static final long serialVersionUID = -5982824024992428470L; 058 059 //----------------------------------------------------------------------- 060 /** 061 * Parses a {@code MutableInterval} from the specified string. 062 * <p> 063 * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()} 064 * and {@link ISOPeriodFormat#standard()}, and may be 'datetime/datetime', 065 * 'datetime/period' or 'period/datetime'. 066 * 067 * @param str the string to parse, not null 068 * @since 2.0 069 */ 070 public static MutableInterval parse(String str) { 071 return new MutableInterval(str); 072 } 073 074 //----------------------------------------------------------------------- 075 /** 076 * Constructs a zero length time interval from 1970-01-01 to 1970-01-01. 077 */ 078 public MutableInterval() { 079 super(0L, 0L, null); 080 } 081 082 /** 083 * Constructs an interval from a start and end instant with the ISO default chronology. 084 * 085 * @param startInstant start of this interval, as milliseconds from 1970-01-01T00:00:00Z. 086 * @param endInstant end of this interval, as milliseconds from 1970-01-01T00:00:00Z. 087 * @throws IllegalArgumentException if the end is before the start 088 */ 089 public MutableInterval(long startInstant, long endInstant) { 090 super(startInstant, endInstant, null); 091 } 092 093 /** 094 * Constructs an interval from a start and end instant with a chronology. 095 * 096 * @param chronology the chronology to use, null is ISO default 097 * @param startInstant start of this interval, as milliseconds from 1970-01-01T00:00:00Z. 098 * @param endInstant end of this interval, as milliseconds from 1970-01-01T00:00:00Z. 099 * @throws IllegalArgumentException if the end is before the start 100 */ 101 public MutableInterval(long startInstant, long endInstant, Chronology chronology) { 102 super(startInstant, endInstant, chronology); 103 } 104 105 /** 106 * Constructs an interval from a start and end instant. 107 * <p> 108 * The chronology used is that of the start instant. 109 * 110 * @param start start of this interval, null means now 111 * @param end end of this interval, null means now 112 * @throws IllegalArgumentException if the end is before the start 113 */ 114 public MutableInterval(ReadableInstant start, ReadableInstant end) { 115 super(start, end); 116 } 117 118 /** 119 * Constructs an interval from a start instant and a duration. 120 * 121 * @param start start of this interval, null means now 122 * @param duration the duration of this interval, null means zero length 123 * @throws IllegalArgumentException if the end is before the start 124 * @throws ArithmeticException if the end instant exceeds the capacity of a long 125 */ 126 public MutableInterval(ReadableInstant start, ReadableDuration duration) { 127 super(start, duration); 128 } 129 130 /** 131 * Constructs an interval from a millisecond duration and an end instant. 132 * 133 * @param duration the duration of this interval, null means zero length 134 * @param end end of this interval, null means now 135 * @throws IllegalArgumentException if the end is before the start 136 * @throws ArithmeticException if the start instant exceeds the capacity of a long 137 */ 138 public MutableInterval(ReadableDuration duration, ReadableInstant end) { 139 super(duration, end); 140 } 141 142 /** 143 * Constructs an interval from a start instant and a time period. 144 * <p> 145 * When forming the interval, the chronology from the instant is used 146 * if present, otherwise the chronology of the period is used. 147 * 148 * @param start start of this interval, null means now 149 * @param period the period of this interval, null means zero length 150 * @throws IllegalArgumentException if the end is before the start 151 * @throws ArithmeticException if the end instant exceeds the capacity of a long 152 */ 153 public MutableInterval(ReadableInstant start, ReadablePeriod period) { 154 super(start, period); 155 } 156 157 /** 158 * Constructs an interval from a time period and an end instant. 159 * <p> 160 * When forming the interval, the chronology from the instant is used 161 * if present, otherwise the chronology of the period is used. 162 * 163 * @param period the period of this interval, null means zero length 164 * @param end end of this interval, null means now 165 * @throws IllegalArgumentException if the end is before the start 166 * @throws ArithmeticException if the start instant exceeds the capacity of a long 167 */ 168 public MutableInterval(ReadablePeriod period, ReadableInstant end) { 169 super(period, end); 170 } 171 172 /** 173 * Constructs a time interval by converting or copying from another object. 174 * <p> 175 * The recognised object types are defined in 176 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 177 * include ReadableInterval and String. 178 * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()} 179 * and {@link ISOPeriodFormat#standard()}, and may be 'datetime/datetime', 180 * 'datetime/period' or 'period/datetime'. 181 * 182 * @param interval the time interval to copy 183 * @throws IllegalArgumentException if the interval is invalid 184 */ 185 public MutableInterval(Object interval) { 186 super(interval, null); 187 } 188 189 /** 190 * Constructs a time interval by converting or copying from another object, 191 * overriding the chronology. 192 * <p> 193 * The recognised object types are defined in 194 * {@link org.joda.time.convert.ConverterManager ConverterManager} and 195 * include ReadableInterval and String. 196 * The String formats are described by {@link ISODateTimeFormat#dateTimeParser()} 197 * and {@link ISOPeriodFormat#standard()}, and may be 'datetime/datetime', 198 * 'datetime/period' or 'period/datetime'. 199 * 200 * @param interval the time interval to copy 201 * @param chronology the chronology to use, null means ISO default 202 * @throws IllegalArgumentException if the interval is invalid 203 */ 204 public MutableInterval(Object interval, Chronology chronology) { 205 super(interval, chronology); 206 } 207 208 //----------------------------------------------------------------------- 209 /** 210 * Sets this interval from two millisecond instants retaining the chronology. 211 * 212 * @param startInstant the start of the time interval 213 * @param endInstant the start of the time interval 214 * @throws IllegalArgumentException if the end is before the start 215 */ 216 public void setInterval(long startInstant, long endInstant) { 217 super.setInterval(startInstant, endInstant, getChronology()); 218 } 219 220 /** 221 * Sets this interval to be the same as another. 222 * 223 * @param interval the interval to copy 224 * @throws IllegalArgumentException if the interval is null 225 */ 226 public void setInterval(ReadableInterval interval) { 227 if (interval == null) { 228 throw new IllegalArgumentException("Interval must not be null"); 229 } 230 long startMillis = interval.getStartMillis(); 231 long endMillis = interval.getEndMillis(); 232 Chronology chrono = interval.getChronology(); 233 super.setInterval(startMillis, endMillis, chrono); 234 } 235 236 /** 237 * Sets this interval from two instants, replacing the chronology with 238 * that from the start instant. 239 * 240 * @param start the start of the time interval 241 * @param end the start of the time interval 242 * @throws IllegalArgumentException if the end is before the start 243 */ 244 public void setInterval(ReadableInstant start, ReadableInstant end) { 245 if (start == null && end == null) { 246 long now = DateTimeUtils.currentTimeMillis(); 247 setInterval(now, now); 248 } else { 249 long startMillis = DateTimeUtils.getInstantMillis(start); 250 long endMillis = DateTimeUtils.getInstantMillis(end); 251 Chronology chrono = DateTimeUtils.getInstantChronology(start); 252 super.setInterval(startMillis, endMillis, chrono); 253 } 254 } 255 256 //----------------------------------------------------------------------- 257 /** 258 * Sets the chronology of this time interval. 259 * 260 * @param chrono the chronology to use, null means ISO default 261 */ 262 public void setChronology(Chronology chrono) { 263 super.setInterval(getStartMillis(), getEndMillis(), chrono); 264 } 265 266 /** 267 * Sets the start of this time interval. 268 * 269 * @param startInstant the start of the time interval, 270 * millisecond instant from 1970-01-01T00:00:00Z 271 * @throws IllegalArgumentException if the end is before the start 272 */ 273 public void setStartMillis(long startInstant) { 274 super.setInterval(startInstant, getEndMillis(), getChronology()); 275 } 276 277 /** 278 * Sets the start of this time interval as an Instant. 279 * 280 * @param start the start of the time interval, null means now 281 * @throws IllegalArgumentException if the end is before the start 282 */ 283 public void setStart(ReadableInstant start) { 284 long startMillis = DateTimeUtils.getInstantMillis(start); 285 super.setInterval(startMillis, getEndMillis(), getChronology()); 286 } 287 288 /** 289 * Sets the end of this time interval. 290 * 291 * @param endInstant the end of the time interval, 292 * millisecond instant from 1970-01-01T00:00:00Z 293 * @throws IllegalArgumentException if the end is before the start 294 */ 295 public void setEndMillis(long endInstant) { 296 super.setInterval(getStartMillis(), endInstant, getChronology()); 297 } 298 299 /** 300 * Sets the end of this time interval as an Instant. 301 * 302 * @param end the end of the time interval, null means now 303 * @throws IllegalArgumentException if the end is before the start 304 */ 305 public void setEnd(ReadableInstant end) { 306 long endMillis = DateTimeUtils.getInstantMillis(end); 307 super.setInterval(getStartMillis(), endMillis, getChronology()); 308 } 309 310 //----------------------------------------------------------------------- 311 /** 312 * Sets the duration of this time interval, preserving the start instant. 313 * 314 * @param duration new duration for interval 315 * @throws IllegalArgumentException if the end is before the start 316 * @throws ArithmeticException if the end instant exceeds the capacity of a long 317 */ 318 public void setDurationAfterStart(long duration) { 319 setEndMillis(FieldUtils.safeAdd(getStartMillis(), duration)); 320 } 321 322 /** 323 * Sets the duration of this time interval, preserving the end instant. 324 * 325 * @param duration new duration for interval 326 * @throws IllegalArgumentException if the end is before the start 327 * @throws ArithmeticException if the start instant exceeds the capacity of a long 328 */ 329 public void setDurationBeforeEnd(long duration) { 330 setStartMillis(FieldUtils.safeAdd(getEndMillis(), -duration)); 331 } 332 333 //----------------------------------------------------------------------- 334 /** 335 * Sets the duration of this time interval, preserving the start instant. 336 * 337 * @param duration new duration for interval, null means zero length 338 * @throws IllegalArgumentException if the end is before the start 339 * @throws ArithmeticException if the end instant exceeds the capacity of a long 340 */ 341 public void setDurationAfterStart(ReadableDuration duration) { 342 long durationMillis = DateTimeUtils.getDurationMillis(duration); 343 setEndMillis(FieldUtils.safeAdd(getStartMillis(), durationMillis)); 344 } 345 346 /** 347 * Sets the duration of this time interval, preserving the end instant. 348 * 349 * @param duration new duration for interval, null means zero length 350 * @throws IllegalArgumentException if the end is before the start 351 * @throws ArithmeticException if the start instant exceeds the capacity of a long 352 */ 353 public void setDurationBeforeEnd(ReadableDuration duration) { 354 long durationMillis = DateTimeUtils.getDurationMillis(duration); 355 setStartMillis(FieldUtils.safeAdd(getEndMillis(), -durationMillis)); 356 } 357 358 //----------------------------------------------------------------------- 359 /** 360 * Sets the period of this time interval, preserving the start instant 361 * and using the ISOChronology in the default zone for calculations. 362 * 363 * @param period new period for interval, null means zero length 364 * @throws IllegalArgumentException if the end is before the start 365 * @throws ArithmeticException if the end instant exceeds the capacity of a long 366 */ 367 public void setPeriodAfterStart(ReadablePeriod period) { 368 if (period == null) { 369 setEndMillis(getStartMillis()); 370 } else { 371 setEndMillis(getChronology().add(period, getStartMillis(), 1)); 372 } 373 } 374 375 /** 376 * Sets the period of this time interval, preserving the end instant 377 * and using the ISOChronology in the default zone for calculations. 378 * 379 * @param period new period for interval, null means zero length 380 * @throws IllegalArgumentException if the end is before the start 381 * @throws ArithmeticException if the start instant exceeds the capacity of a long 382 */ 383 public void setPeriodBeforeEnd(ReadablePeriod period) { 384 if (period == null) { 385 setStartMillis(getEndMillis()); 386 } else { 387 setStartMillis(getChronology().add(period, getEndMillis(), -1)); 388 } 389 } 390 391 //----------------------------------------------------------------------- 392 /** 393 * Clone this object without having to cast the returned object. 394 * 395 * @return a clone of the this object. 396 */ 397 public MutableInterval copy() { 398 return (MutableInterval) clone(); 399 } 400 401 /** 402 * Clone this object. 403 * 404 * @return a clone of this object. 405 */ 406 public Object clone() { 407 try { 408 return super.clone(); 409 } catch (CloneNotSupportedException ex) { 410 throw new InternalError("Clone error"); 411 } 412 } 413 414 }