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