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