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 }
123