blob: 01bf41681b7ca5011c369f76ff800fe65dfb7f14 [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
2
3package org.xbill.DNS;
4
5/**
6 * Routines for parsing BIND-style TTL values. These values consist of
7 * numbers followed by 1 letter units of time (W - week, D - day, H - hour,
8 * M - minute, S - second).
9 *
10 * @author Brian Wellington
11 */
12
13public final class TTL {
14
15public static final long MAX_VALUE = 0x7FFFFFFFL;
16
17private
18TTL() {}
19
20static void
21check(long i) {
22 if (i < 0 || i > MAX_VALUE)
23 throw new InvalidTTLException(i);
24}
25
26/**
27 * Parses a TTL-like value, which can either be expressed as a number or a
28 * BIND-style string with numbers and units.
29 * @param s The string representing the numeric value.
30 * @param clamp Whether to clamp values in the range [MAX_VALUE + 1, 2^32 -1]
31 * to MAX_VALUE. This should be donw for TTLs, but not other values which
32 * can be expressed in this format.
33 * @return The value as a number of seconds
34 * @throws NumberFormatException The string was not in a valid TTL format.
35 */
36public static long
37parse(String s, boolean clamp) {
38 if (s == null || s.length() == 0 || !Character.isDigit(s.charAt(0)))
39 throw new NumberFormatException();
40 long value = 0;
41 long ttl = 0;
42 for (int i = 0; i < s.length(); i++) {
43 char c = s.charAt(i);
44 long oldvalue = value;
45 if (Character.isDigit(c)) {
46 value = (value * 10) + Character.getNumericValue(c);
47 if (value < oldvalue)
48 throw new NumberFormatException();
49 } else {
50 switch (Character.toUpperCase(c)) {
51 case 'W': value *= 7;
52 case 'D': value *= 24;
53 case 'H': value *= 60;
54 case 'M': value *= 60;
55 case 'S': break;
56 default: throw new NumberFormatException();
57 }
58 ttl += value;
59 value = 0;
60 if (ttl > 0xFFFFFFFFL)
61 throw new NumberFormatException();
62 }
63 }
64 if (ttl == 0)
65 ttl = value;
66
67 if (ttl > 0xFFFFFFFFL)
68 throw new NumberFormatException();
69 else if (ttl > MAX_VALUE && clamp)
70 ttl = MAX_VALUE;
71 return ttl;
72}
73
74/**
75 * Parses a TTL, which can either be expressed as a number or a BIND-style
76 * string with numbers and units.
77 * @param s The string representing the TTL
78 * @return The TTL as a number of seconds
79 * @throws NumberFormatException The string was not in a valid TTL format.
80 */
81public static long
82parseTTL(String s) {
83 return parse(s, true);
84}
85
86public static String
87format(long ttl) {
88 TTL.check(ttl);
89 StringBuffer sb = new StringBuffer();
90 long secs, mins, hours, days, weeks;
91 secs = ttl % 60;
92 ttl /= 60;
93 mins = ttl % 60;
94 ttl /= 60;
95 hours = ttl % 24;
96 ttl /= 24;
97 days = ttl % 7;
98 ttl /= 7;
99 weeks = ttl;
100 if (weeks > 0)
101 sb.append(weeks + "W");
102 if (days > 0)
103 sb.append(days + "D");
104 if (hours > 0)
105 sb.append(hours + "H");
106 if (mins > 0)
107 sb.append(mins + "M");
108 if (secs > 0 || (weeks == 0 && days == 0 && hours == 0 && mins == 0))
109 sb.append(secs + "S");
110 return sb.toString();
111}
112
113}