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
22   * expected, Joran (logback's configuration system) will automatically convert
23   * strings such as "20 seconds" "3.5 minutes" or "5 hours" into Duration
24   * instances.
25   *
26   * <p>
27   * The recognized units of time are the "millisecond", "second", "minute" "hour"
28   * and "day". The unit name may be followed by an "s". Thus, "2 day" and "2
29   * days" are equivalent. In the absence of a time unit specification,
30   * milliseconds are assumed.
31   * 
32   * <p>
33   * Note: the conversion magic is entirely due to the fact that this class
34   * follows the {@link #valueOf} convention.
35   *
36   * @author Ceki Gulcu
37   */
38  public class Duration {
39  
40      private final static String DOUBLE_PART = "([0-9]*(.[0-9]+)?)";
41      private final static int DOUBLE_GROUP = 1;
42  
43      private final static String UNIT_PART = "(|milli(second)?|second(e)?|minute|hour|day)s?";
44      private final static int UNIT_GROUP = 3;
45  
46      private static final Pattern DURATION_PATTERN = Pattern.compile(DOUBLE_PART + "\\s*" + UNIT_PART,
47              Pattern.CASE_INSENSITIVE);
48  
49      static final long SECONDS_COEFFICIENT = 1000;
50      static final long MINUTES_COEFFICIENT = 60 * SECONDS_COEFFICIENT;
51      static final long HOURS_COEFFICIENT = 60 * MINUTES_COEFFICIENT;
52      static final long DAYS_COEFFICIENT = 24 * HOURS_COEFFICIENT;
53  
54      final long millis;
55  
56      public Duration(long millis) {
57          this.millis = millis;
58      }
59  
60      public static Duration buildByMilliseconds(double value) {
61          return new Duration((long) (value));
62      }
63  
64      public static Duration buildBySeconds(double value) {
65          return new Duration((long) (SECONDS_COEFFICIENT * value));
66      }
67  
68      public static Duration buildByMinutes(double value) {
69          return new Duration((long) (MINUTES_COEFFICIENT * value));
70      }
71  
72      public static Duration buildByHours(double value) {
73          return new Duration((long) (HOURS_COEFFICIENT * value));
74      }
75  
76      public static Duration buildByDays(double value) {
77          return new Duration((long) (DAYS_COEFFICIENT * value));
78      }
79  
80      public static Duration buildUnbounded() {
81          return new Duration(Long.MAX_VALUE);
82      }
83  
84      public long getMilliseconds() {
85          return millis;
86      }
87  
88      public static Duration valueOf(String durationStr) {
89          Matcher matcher = DURATION_PATTERN.matcher(durationStr);
90  
91          if (matcher.matches()) {
92              String doubleStr = matcher.group(DOUBLE_GROUP);
93              String unitStr = matcher.group(UNIT_GROUP);
94  
95              double doubleValue = Double.valueOf(doubleStr);
96              if (unitStr.equalsIgnoreCase("milli") || unitStr.equalsIgnoreCase("millisecond") || unitStr.length() == 0) {
97                  return buildByMilliseconds(doubleValue);
98              } else if (unitStr.equalsIgnoreCase("second") || unitStr.equalsIgnoreCase("seconde")) {
99                  return buildBySeconds(doubleValue);
100             } else if (unitStr.equalsIgnoreCase("minute")) {
101                 return buildByMinutes(doubleValue);
102             } else if (unitStr.equalsIgnoreCase("hour")) {
103                 return buildByHours(doubleValue);
104             } else if (unitStr.equalsIgnoreCase("day")) {
105                 return buildByDays(doubleValue);
106             } else {
107                 throw new IllegalStateException("Unexpected " + unitStr);
108             }
109         } else {
110             throw new IllegalArgumentException("String value [" + durationStr + "] is not in the expected format.");
111         }
112     }
113 
114     @Override
115     public String toString() {
116         if (millis < SECONDS_COEFFICIENT) {
117             return millis + " milliseconds";
118         } else if (millis < MINUTES_COEFFICIENT) {
119             return millis / SECONDS_COEFFICIENT + " seconds";
120         } else if (millis < HOURS_COEFFICIENT) {
121             return millis / MINUTES_COEFFICIENT + " minutes";
122         } else {
123             return millis / HOURS_COEFFICIENT + " hours";
124         }
125 
126     }
127 }