View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.util;
15  
16  import java.util.regex.Matcher;
17  import java.util.regex.Pattern;
18  
19  /**
20   * Duration instances represent a lapse of time. Internally, the duration is
21   * stored in milliseconds. However, whenever a parameter of type Duration is expected, Joran
22   * (logback's configuration system) will automatically convert strings such as "20 seconds"
23   * "3.5 minutes" or "5 hours" into Duration instances.
24   *
25   * <p>The recognized units of time are the "millisecond", "second", "minute" "hour" and "day".
26   * The unit name may be followed by an "s". Thus, "2 day" and "2 days" are equivalent. In the
27   * absence of a time unit specification, milliseconds are assumed.
28   * 
29   * <p>Note: the conversion magic is entirely due to the fact that this class follows the
30   * {@link #valueOf} convention.
31   *
32   * @author Ceki Gulcu
33   */
34  public class Duration {
35  
36      private final static String DOUBLE_PART = "([0-9]*(.[0-9]+)?)";
37      private final static int DOUBLE_GROUP = 1;
38  
39      private final static String UNIT_PART = "(|milli(second)?|second(e)?|minute|hour|day)s?";
40      private final static int UNIT_GROUP = 3;
41  
42      private static final Pattern DURATION_PATTERN = Pattern.compile(DOUBLE_PART + "\\s*" + UNIT_PART, Pattern.CASE_INSENSITIVE);
43  
44      static final long SECONDS_COEFFICIENT = 1000;
45      static final long MINUTES_COEFFICIENT = 60 * SECONDS_COEFFICIENT;
46      static final long HOURS_COEFFICIENT = 60 * MINUTES_COEFFICIENT;
47      static final long DAYS_COEFFICIENT = 24 * HOURS_COEFFICIENT;
48  
49      final long millis;
50  
51      public Duration(long millis) {
52          this.millis = millis;
53      }
54  
55      public static Duration buildByMilliseconds(double value) {
56          return new Duration((long) (value));
57      }
58  
59      public static Duration buildBySeconds(double value) {
60          return new Duration((long) (SECONDS_COEFFICIENT * value));
61      }
62  
63      public static Duration buildByMinutes(double value) {
64          return new Duration((long) (MINUTES_COEFFICIENT * value));
65      }
66  
67      public static Duration buildByHours(double value) {
68          return new Duration((long) (HOURS_COEFFICIENT * value));
69      }
70  
71      public static Duration buildByDays(double value) {
72          return new Duration((long) (DAYS_COEFFICIENT * value));
73      }
74  
75      public static Duration buildUnbounded() {
76          return new Duration(Long.MAX_VALUE);
77      }
78  
79      public long getMilliseconds() {
80          return millis;
81      }
82  
83      public static Duration valueOf(String durationStr) {
84          Matcher matcher = DURATION_PATTERN.matcher(durationStr);
85  
86          if (matcher.matches()) {
87              String doubleStr = matcher.group(DOUBLE_GROUP);
88              String unitStr = matcher.group(UNIT_GROUP);
89  
90              double doubleValue = Double.valueOf(doubleStr);
91              if (unitStr.equalsIgnoreCase("milli") || unitStr.equalsIgnoreCase("millisecond") || unitStr.length() == 0) {
92                  return buildByMilliseconds(doubleValue);
93              } else if (unitStr.equalsIgnoreCase("second") || unitStr.equalsIgnoreCase("seconde")) {
94                  return buildBySeconds(doubleValue);
95              } else if (unitStr.equalsIgnoreCase("minute")) {
96                  return buildByMinutes(doubleValue);
97              } else if (unitStr.equalsIgnoreCase("hour")) {
98                  return buildByHours(doubleValue);
99              } else if (unitStr.equalsIgnoreCase("day")) {
100                 return buildByDays(doubleValue);
101             } else {
102                 throw new IllegalStateException("Unexpected " + unitStr);
103             }
104         } else {
105             throw new IllegalArgumentException("String value [" + durationStr + "] is not in the expected format.");
106         }
107     }
108 
109     @Override
110     public String toString() {
111         if (millis < SECONDS_COEFFICIENT) {
112             return millis + " milliseconds";
113         } else if (millis < MINUTES_COEFFICIENT) {
114             return millis / SECONDS_COEFFICIENT + " seconds";
115         } else if (millis < HOURS_COEFFICIENT) {
116             return millis / MINUTES_COEFFICIENT + " minutes";
117         } else {
118             return millis / HOURS_COEFFICIENT + " hours";
119         }
120 
121     }
122 }