001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.config.types;
031:
032: import com.caucho.config.ConfigException;
033: import com.caucho.util.L10N;
034: import com.caucho.util.QDate;
035:
036: /**
037: * Representations of time in milliseconds.
038: */
039: public class Period {
040: static L10N L = new L10N(Period.class);
041:
042: public static final long SECOND = 1000L;
043: public static final long MINUTE = 60L * SECOND;
044: public static final long HOUR = 60L * MINUTE;
045: public static final long DAY = 24L * HOUR;
046: /** 30 days */
047: public static final long MONTH = DAY * 30L;
048: /** 365 days */
049: public static final long YEAR = DAY * 365L;
050: public static final long INFINITE = (Long.MAX_VALUE / 2 / 1000) * 1000;
051: public static final long FOREVER = INFINITE;
052:
053: private static final QDate _localCalendar = QDate.createLocal();
054:
055: private long _period;
056:
057: public Period() {
058: }
059:
060: public Period(long period) {
061: _period = period;
062: }
063:
064: /**
065: * Returns the default units (default is 1000)
066: */
067: public long getDefaultUnits() {
068: return 1000;
069: }
070:
071: /**
072: * Sets the text.
073: */
074: public void addText(String text) throws ConfigException {
075: _period = toPeriod(text, getDefaultUnits());
076: }
077:
078: /**
079: * Replace with the real path.
080: */
081: public long getPeriod() {
082: return _period;
083: }
084:
085: /**
086: * Converts a period string to a time.
087: *
088: * <table>
089: * <tr><td>ms<td>milliseconds
090: * <tr><td>s<td>seconds
091: * <tr><td>m<td>minutes
092: * <tr><td>h<td>hours
093: * <tr><td>D<td>days
094: * <tr><td>W<td>weeks
095: * <tr><td>M<td>months
096: * <tr><td>Y<td>years
097: * </table>
098: */
099: public static long toPeriod(String value) throws ConfigException {
100: return toPeriod(value, 1000);
101: }
102:
103: /**
104: * Converts a period string to a time.
105: *
106: * <table>
107: * <tr><td>ms<td>milliseconds
108: * <tr><td>s<td>seconds
109: * <tr><td>m<td>minutes
110: * <tr><td>h<td>hours
111: * <tr><td>D<td>days
112: * <tr><td>W<td>weeks
113: * <tr><td>M<td>months
114: * <tr><td>Y<td>years
115: * </table>
116: */
117: public static long toPeriod(String value, long defaultUnits)
118: throws ConfigException {
119: if (value == null)
120: return 0;
121:
122: long sign = 1;
123: long period = 0;
124:
125: int i = 0;
126: int length = value.length();
127:
128: if (length > 0 && value.charAt(i) == '-') {
129: sign = -1;
130: i++;
131: }
132:
133: while (i < length) {
134: long delta = 0;
135: char ch;
136:
137: for (; i < length && (ch = value.charAt(i)) >= '0'
138: && ch <= '9'; i++)
139: delta = 10 * delta + ch - '0';
140:
141: if (length <= i)
142: period += defaultUnits * delta;
143: else {
144: ch = value.charAt(i++);
145: switch (ch) {
146: case 's':
147: period += 1000 * delta;
148: break;
149:
150: case 'm':
151: if (i < value.length() && value.charAt(i) == 's') {
152: i++;
153: period += delta;
154: } else
155: period += 60 * 1000 * delta;
156: break;
157:
158: case 'h':
159: period += 60L * 60 * 1000 * delta;
160: break;
161:
162: case 'D':
163: period += DAY * delta;
164: break;
165:
166: case 'W':
167: period += 7L * DAY * delta;
168: break;
169:
170: case 'M':
171: period += 30L * DAY * delta;
172: break;
173:
174: case 'Y':
175: period += 365L * DAY * delta;
176: break;
177:
178: default:
179: throw new ConfigException(
180: L
181: .l(
182: "Unknown unit `{0}' in period `{1}'. Valid units are:\n '10ms' milliseconds\n '10s' seconds\n '10m' minutes\n '10h' hours\n '10D' days\n '10W' weeks\n '10M' months\n '10Y' years",
183: String.valueOf(ch), value));
184: }
185: }
186: }
187:
188: period = sign * period;
189:
190: // server/137w
191: /*
192: if (period < 0)
193: return INFINITE;
194: else
195: return period;
196: */
197:
198: return period;
199: }
200:
201: /**
202: * Calculates the next period end. The calculation is in local time.
203: *
204: * @param now the current time in GMT ms since the epoch
205: *
206: * @return the time of the next period in GMT ms since the epoch
207: */
208: public static long periodEnd(long now, long period) {
209: return periodEnd(now, period, _localCalendar);
210: }
211:
212: /**
213: * Calculates the next period end. The calculation is in local time.
214: *
215: * @param now the current time in GMT ms since the epoch
216: *
217: * @return the time of the next period in GMT ms since the epoch
218: */
219: public static long periodEnd(long now, long period, QDate cal) {
220: if (period < 0)
221: return Long.MAX_VALUE;
222: else if (period == 0)
223: return now;
224:
225: if (period < 30 * DAY) {
226: synchronized (cal) {
227: cal.setGMTTime(now);
228:
229: long localTime = cal.getLocalTime();
230:
231: localTime = localTime
232: + (period - (localTime + 4 * DAY) % period);
233:
234: cal.setLocalTime(localTime);
235:
236: return cal.getGMTTime();
237: }
238: }
239:
240: if (period % (30 * DAY) == 0) {
241: int months = (int) (period / (30 * DAY));
242:
243: synchronized (cal) {
244: cal.setGMTTime(now);
245: long year = cal.getYear();
246: int month = cal.getMonth();
247:
248: cal.setLocalTime(0);
249:
250: cal.setDate(year, month + months, 1);
251:
252: return cal.getGMTTime();
253: }
254: }
255:
256: if (period % (365 * DAY) == 0) {
257: long years = (period / (365 * DAY));
258:
259: synchronized (cal) {
260: cal.setGMTTime(now);
261: long year = cal.getYear();
262:
263: cal.setLocalTime(0);
264:
265: long newYear = year + (years - year % years);
266:
267: cal.setDate(newYear, 0, 1);
268:
269: return cal.getGMTTime();
270: }
271: }
272:
273: synchronized (cal) {
274: cal.setGMTTime(now);
275:
276: long localTime = cal.getLocalTime();
277:
278: localTime = localTime
279: + (period - (localTime + 4 * DAY) % period);
280:
281: cal.setLocalTime(localTime);
282:
283: return cal.getGMTTime();
284: }
285: }
286:
287: public String toString() {
288: return "Period[" + _period + "]";
289: }
290: }
|