001 /* 002 * Copyright 2001-2010 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 org.joda.convert.FromString; 019 import org.joda.convert.ToString; 020 import org.joda.time.base.BaseSingleFieldPeriod; 021 import org.joda.time.field.FieldUtils; 022 import org.joda.time.format.ISOPeriodFormat; 023 import org.joda.time.format.PeriodFormatter; 024 025 /** 026 * An immutable time period representing a number of seconds. 027 * <p> 028 * <code>Seconds</code> is an immutable period that can only store seconds. 029 * It does not store years, months or hours for example. As such it is a 030 * type-safe way of representing a number of seconds in an application. 031 * <p> 032 * The number of seconds is set in the constructor, and may be queried using 033 * <code>getSeconds()</code>. Basic mathematical operations are provided - 034 * <code>plus()</code>, <code>minus()</code>, <code>multipliedBy()</code> and 035 * <code>dividedBy()</code>. 036 * <p> 037 * <code>Seconds</code> is thread-safe and immutable. 038 * 039 * @author Stephen Colebourne 040 * @since 1.4 041 */ 042 public final class Seconds extends BaseSingleFieldPeriod { 043 044 /** Constant representing zero seconds. */ 045 public static final Seconds ZERO = new Seconds(0); 046 /** Constant representing one second. */ 047 public static final Seconds ONE = new Seconds(1); 048 /** Constant representing two seconds. */ 049 public static final Seconds TWO = new Seconds(2); 050 /** Constant representing three seconds. */ 051 public static final Seconds THREE = new Seconds(3); 052 /** Constant representing the maximum number of seconds that can be stored in this object. */ 053 public static final Seconds MAX_VALUE = new Seconds(Integer.MAX_VALUE); 054 /** Constant representing the minimum number of seconds that can be stored in this object. */ 055 public static final Seconds MIN_VALUE = new Seconds(Integer.MIN_VALUE); 056 057 /** The paser to use for this class. */ 058 private static final PeriodFormatter PARSER = ISOPeriodFormat.standard().withParseType(PeriodType.seconds()); 059 /** Serialization version. */ 060 private static final long serialVersionUID = 87525275727380862L; 061 062 //----------------------------------------------------------------------- 063 /** 064 * Obtains an instance of <code>Seconds</code> that may be cached. 065 * <code>Seconds</code> is immutable, so instances can be cached and shared. 066 * This factory method provides access to shared instances. 067 * 068 * @param seconds the number of seconds to obtain an instance for 069 * @return the instance of Seconds 070 */ 071 public static Seconds seconds(int seconds) { 072 switch (seconds) { 073 case 0: 074 return ZERO; 075 case 1: 076 return ONE; 077 case 2: 078 return TWO; 079 case 3: 080 return THREE; 081 case Integer.MAX_VALUE: 082 return MAX_VALUE; 083 case Integer.MIN_VALUE: 084 return MIN_VALUE; 085 default: 086 return new Seconds(seconds); 087 } 088 } 089 090 //----------------------------------------------------------------------- 091 /** 092 * Creates a <code>Seconds</code> representing the number of whole seconds 093 * between the two specified datetimes. 094 * 095 * @param start the start instant, must not be null 096 * @param end the end instant, must not be null 097 * @return the period in seconds 098 * @throws IllegalArgumentException if the instants are null or invalid 099 */ 100 public static Seconds secondsBetween(ReadableInstant start, ReadableInstant end) { 101 int amount = BaseSingleFieldPeriod.between(start, end, DurationFieldType.seconds()); 102 return Seconds.seconds(amount); 103 } 104 105 /** 106 * Creates a <code>Seconds</code> representing the number of whole seconds 107 * between the two specified partial datetimes. 108 * <p> 109 * The two partials must contain the same fields, for example you can specify 110 * two <code>LocalTime</code> objects. 111 * 112 * @param start the start partial date, must not be null 113 * @param end the end partial date, must not be null 114 * @return the period in seconds 115 * @throws IllegalArgumentException if the partials are null or invalid 116 */ 117 public static Seconds secondsBetween(ReadablePartial start, ReadablePartial end) { 118 if (start instanceof LocalTime && end instanceof LocalTime) { 119 Chronology chrono = DateTimeUtils.getChronology(start.getChronology()); 120 int seconds = chrono.seconds().getDifference( 121 ((LocalTime) end).getLocalMillis(), ((LocalTime) start).getLocalMillis()); 122 return Seconds.seconds(seconds); 123 } 124 int amount = BaseSingleFieldPeriod.between(start, end, ZERO); 125 return Seconds.seconds(amount); 126 } 127 128 /** 129 * Creates a <code>Seconds</code> representing the number of whole seconds 130 * in the specified interval. 131 * 132 * @param interval the interval to extract seconds from, null returns zero 133 * @return the period in seconds 134 * @throws IllegalArgumentException if the partials are null or invalid 135 */ 136 public static Seconds secondsIn(ReadableInterval interval) { 137 if (interval == null) { 138 return Seconds.ZERO; 139 } 140 int amount = BaseSingleFieldPeriod.between(interval.getStart(), interval.getEnd(), DurationFieldType.seconds()); 141 return Seconds.seconds(amount); 142 } 143 144 /** 145 * Creates a new <code>Seconds</code> representing the number of complete 146 * standard length seconds in the specified period. 147 * <p> 148 * This factory method converts all fields from the period to hours using standardised 149 * durations for each field. Only those fields which have a precise duration in 150 * the ISO UTC chronology can be converted. 151 * <ul> 152 * <li>One week consists of 7 seconds. 153 * <li>One day consists of 24 hours. 154 * <li>One hour consists of 60 minutes. 155 * <li>One minute consists of 60 seconds. 156 * <li>One second consists of 1000 milliseconds. 157 * </ul> 158 * Months and Years are imprecise and periods containing these values cannot be converted. 159 * 160 * @param period the period to get the number of hours from, null returns zero 161 * @return the period in seconds 162 * @throws IllegalArgumentException if the period contains imprecise duration values 163 */ 164 public static Seconds standardSecondsIn(ReadablePeriod period) { 165 int amount = BaseSingleFieldPeriod.standardPeriodIn(period, DateTimeConstants.MILLIS_PER_SECOND); 166 return Seconds.seconds(amount); 167 } 168 169 /** 170 * Creates a new <code>Seconds</code> by parsing a string in the ISO8601 format 'PTnS'. 171 * <p> 172 * The parse will accept the full ISO syntax of PnYnMnWnDTnHnMnS however only the 173 * seconds component may be non-zero. If any other component is non-zero, an exception 174 * will be thrown. 175 * 176 * @param periodStr the period string, null returns zero 177 * @return the period in seconds 178 * @throws IllegalArgumentException if the string format is invalid 179 */ 180 @FromString 181 public static Seconds parseSeconds(String periodStr) { 182 if (periodStr == null) { 183 return Seconds.ZERO; 184 } 185 Period p = PARSER.parsePeriod(periodStr); 186 return Seconds.seconds(p.getSeconds()); 187 } 188 189 //----------------------------------------------------------------------- 190 /** 191 * Creates a new instance representing a number of seconds. 192 * You should consider using the factory method {@link #seconds(int)} 193 * instead of the constructor. 194 * 195 * @param seconds the number of seconds to represent 196 */ 197 private Seconds(int seconds) { 198 super(seconds); 199 } 200 201 /** 202 * Resolves singletons. 203 * 204 * @return the singleton instance 205 */ 206 private Object readResolve() { 207 return Seconds.seconds(getValue()); 208 } 209 210 //----------------------------------------------------------------------- 211 /** 212 * Gets the duration field type, which is <code>seconds</code>. 213 * 214 * @return the period type 215 */ 216 public DurationFieldType getFieldType() { 217 return DurationFieldType.seconds(); 218 } 219 220 /** 221 * Gets the period type, which is <code>seconds</code>. 222 * 223 * @return the period type 224 */ 225 public PeriodType getPeriodType() { 226 return PeriodType.seconds(); 227 } 228 229 //----------------------------------------------------------------------- 230 /** 231 * Converts this period in seconds to a period in weeks assuming a 232 * 7 day week, 24 hour day, 60 minute hour and 60 second minute. 233 * <p> 234 * This method allows you to convert between different types of period. 235 * However to achieve this it makes the assumption that all weeks are 7 days 236 * long, all days are 24 hours long, all hours are 60 minutes long and 237 * all minutes are 60 seconds long. 238 * This is not true when daylight savings time is considered, and may also 239 * not be true for some unusual chronologies. However, it is included as it 240 * is a useful operation for many applications and business rules. 241 * 242 * @return a period representing the number of whole weeks for this number of seconds 243 */ 244 public Weeks toStandardWeeks() { 245 return Weeks.weeks(getValue() / DateTimeConstants.SECONDS_PER_WEEK); 246 } 247 248 /** 249 * Converts this period in seconds to a period in days assuming a 250 * 24 hour day, 60 minute hour and 60 second minute. 251 * <p> 252 * This method allows you to convert between different types of period. 253 * However to achieve this it makes the assumption that all days are 24 hours 254 * long, all hours are 60 minutes long and all minutes are 60 seconds long. 255 * This is not true when daylight savings is considered and may also not 256 * be true for some unusual chronologies. However, it is included 257 * as it is a useful operation for many applications and business rules. 258 * 259 * @return a period representing the number of days for this number of seconds 260 */ 261 public Days toStandardDays() { 262 return Days.days(getValue() / DateTimeConstants.SECONDS_PER_DAY); 263 } 264 265 /** 266 * Converts this period in seconds to a period in hours assuming a 267 * 60 minute hour and 60 second minute. 268 * <p> 269 * This method allows you to convert between different types of period. 270 * However to achieve this it makes the assumption that all hours are 271 * 60 minutes long and all minutes are 60 seconds long. 272 * This may not be true for some unusual chronologies. However, it is included 273 * as it is a useful operation for many applications and business rules. 274 * 275 * @return a period representing the number of hours for this number of seconds 276 */ 277 public Hours toStandardHours() { 278 return Hours.hours(getValue() / DateTimeConstants.SECONDS_PER_HOUR); 279 } 280 281 /** 282 * Converts this period in seconds to a period in minutes assuming a 283 * 60 second minute. 284 * <p> 285 * This method allows you to convert between different types of period. 286 * However to achieve this it makes the assumption that all minutes are 287 * 60 seconds long. 288 * This may not be true for some unusual chronologies. However, it is included 289 * as it is a useful operation for many applications and business rules. 290 * 291 * @return a period representing the number of minutes for this number of seconds 292 */ 293 public Minutes toStandardMinutes() { 294 return Minutes.minutes(getValue() / DateTimeConstants.SECONDS_PER_MINUTE); 295 } 296 297 //----------------------------------------------------------------------- 298 /** 299 * Converts this period in seconds to a duration in milliseconds assuming a 300 * 24 hour day, 60 minute hour and 60 second minute. 301 * <p> 302 * This method allows you to convert from a period to a duration. 303 * However to achieve this it makes the assumption that all seconds are 24 hours 304 * long, all hours are 60 minutes and all minutes are 60 seconds. 305 * This is not true when daylight savings time is considered, and may also 306 * not be true for some unusual chronologies. However, it is included as it 307 * is a useful operation for many applications and business rules. 308 * 309 * @return a duration equivalent to this number of seconds 310 */ 311 public Duration toStandardDuration() { 312 long seconds = getValue(); // assign to a long 313 return new Duration(seconds * DateTimeConstants.MILLIS_PER_SECOND); 314 } 315 316 //----------------------------------------------------------------------- 317 /** 318 * Gets the number of seconds that this period represents. 319 * 320 * @return the number of seconds in the period 321 */ 322 public int getSeconds() { 323 return getValue(); 324 } 325 326 //----------------------------------------------------------------------- 327 /** 328 * Returns a new instance with the specified number of seconds added. 329 * <p> 330 * This instance is immutable and unaffected by this method call. 331 * 332 * @param seconds the amount of seconds to add, may be negative 333 * @return the new period plus the specified number of seconds 334 * @throws ArithmeticException if the result overflows an int 335 */ 336 public Seconds plus(int seconds) { 337 if (seconds == 0) { 338 return this; 339 } 340 return Seconds.seconds(FieldUtils.safeAdd(getValue(), seconds)); 341 } 342 343 /** 344 * Returns a new instance with the specified number of seconds added. 345 * <p> 346 * This instance is immutable and unaffected by this method call. 347 * 348 * @param seconds the amount of seconds to add, may be negative, null means zero 349 * @return the new period plus the specified number of seconds 350 * @throws ArithmeticException if the result overflows an int 351 */ 352 public Seconds plus(Seconds seconds) { 353 if (seconds == null) { 354 return this; 355 } 356 return plus(seconds.getValue()); 357 } 358 359 //----------------------------------------------------------------------- 360 /** 361 * Returns a new instance with the specified number of seconds taken away. 362 * <p> 363 * This instance is immutable and unaffected by this method call. 364 * 365 * @param seconds the amount of seconds to take away, may be negative 366 * @return the new period minus the specified number of seconds 367 * @throws ArithmeticException if the result overflows an int 368 */ 369 public Seconds minus(int seconds) { 370 return plus(FieldUtils.safeNegate(seconds)); 371 } 372 373 /** 374 * Returns a new instance with the specified number of seconds taken away. 375 * <p> 376 * This instance is immutable and unaffected by this method call. 377 * 378 * @param seconds the amount of seconds to take away, may be negative, null means zero 379 * @return the new period minus the specified number of seconds 380 * @throws ArithmeticException if the result overflows an int 381 */ 382 public Seconds minus(Seconds seconds) { 383 if (seconds == null) { 384 return this; 385 } 386 return minus(seconds.getValue()); 387 } 388 389 //----------------------------------------------------------------------- 390 /** 391 * Returns a new instance with the seconds multiplied by the specified scalar. 392 * <p> 393 * This instance is immutable and unaffected by this method call. 394 * 395 * @param scalar the amount to multiply by, may be negative 396 * @return the new period multiplied by the specified scalar 397 * @throws ArithmeticException if the result overflows an int 398 */ 399 public Seconds multipliedBy(int scalar) { 400 return Seconds.seconds(FieldUtils.safeMultiply(getValue(), scalar)); 401 } 402 403 /** 404 * Returns a new instance with the seconds divided by the specified divisor. 405 * The calculation uses integer division, thus 3 divided by 2 is 1. 406 * <p> 407 * This instance is immutable and unaffected by this method call. 408 * 409 * @param divisor the amount to divide by, may be negative 410 * @return the new period divided by the specified divisor 411 * @throws ArithmeticException if the divisor is zero 412 */ 413 public Seconds dividedBy(int divisor) { 414 if (divisor == 1) { 415 return this; 416 } 417 return Seconds.seconds(getValue() / divisor); 418 } 419 420 //----------------------------------------------------------------------- 421 /** 422 * Returns a new instance with the seconds value negated. 423 * 424 * @return the new period with a negated value 425 * @throws ArithmeticException if the result overflows an int 426 */ 427 public Seconds negated() { 428 return Seconds.seconds(FieldUtils.safeNegate(getValue())); 429 } 430 431 //----------------------------------------------------------------------- 432 /** 433 * Is this seconds instance greater than the specified number of seconds. 434 * 435 * @param other the other period, null means zero 436 * @return true if this seconds instance is greater than the specified one 437 */ 438 public boolean isGreaterThan(Seconds other) { 439 if (other == null) { 440 return getValue() > 0; 441 } 442 return getValue() > other.getValue(); 443 } 444 445 /** 446 * Is this seconds instance less than the specified number of seconds. 447 * 448 * @param other the other period, null means zero 449 * @return true if this seconds instance is less than the specified one 450 */ 451 public boolean isLessThan(Seconds other) { 452 if (other == null) { 453 return getValue() < 0; 454 } 455 return getValue() < other.getValue(); 456 } 457 458 //----------------------------------------------------------------------- 459 /** 460 * Gets this instance as a String in the ISO8601 duration format. 461 * <p> 462 * For example, "PT4S" represents 4 seconds. 463 * 464 * @return the value as an ISO8601 string 465 */ 466 @ToString 467 public String toString() { 468 return "PT" + String.valueOf(getValue()) + "S"; 469 } 470 471 }