View Javadoc

1   /**
2    * Copyright 2010-2012 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.common.util;
17  
18  import java.text.NumberFormat;
19  import java.text.ParseException;
20  import java.text.SimpleDateFormat;
21  import java.util.Date;
22  
23  /**
24   * Format time, bytes, counts, dates, and transfer rates into human friendly form
25   *
26   * @author Jeff Caddel
27   * @since May 27, 2010 6:46:17 PM
28   */
29  public class SimpleFormatter {
30  	private static final double SECOND = 1000;
31  	private static final double MINUTE = 60 * SECOND;
32  	private static final double HOUR = 60 * MINUTE;
33  	private static final double DAY = 24 * HOUR;
34  	private static final double YEAR = 365 * DAY;
35  	private static final double DECADE = 10 * YEAR;
36  	private static final double CENTURY = 10 * DECADE;
37  	private static final String DATE_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ";
38  
39  	NumberFormat largeSizeFormatter = NumberFormat.getInstance();
40  	NumberFormat sizeFormatter = NumberFormat.getInstance();
41  	NumberFormat timeFormatter = NumberFormat.getInstance();
42  	NumberFormat rateFormatter = NumberFormat.getInstance();
43  	NumberFormat countFormatter = NumberFormat.getInstance();
44  	SimpleDateFormat dateFormatter = new SimpleDateFormat(DATE_FORMAT);
45  
46  	public SimpleFormatter() {
47  		super();
48  		sizeFormatter.setGroupingUsed(false);
49  		sizeFormatter.setMaximumFractionDigits(1);
50  		sizeFormatter.setMinimumFractionDigits(1);
51  		largeSizeFormatter.setGroupingUsed(false);
52  		largeSizeFormatter.setMaximumFractionDigits(3);
53  		largeSizeFormatter.setMinimumFractionDigits(3);
54  		timeFormatter.setGroupingUsed(false);
55  		timeFormatter.setMaximumFractionDigits(3);
56  		timeFormatter.setMinimumFractionDigits(3);
57  		rateFormatter.setGroupingUsed(false);
58  		rateFormatter.setMaximumFractionDigits(3);
59  		rateFormatter.setMinimumFractionDigits(3);
60  		countFormatter.setGroupingUsed(true);
61  		countFormatter.setMaximumFractionDigits(0);
62  		countFormatter.setMinimumFractionDigits(0);
63  		dateFormatter.setLenient(false);
64  	}
65  
66  	/**
67  	 * Parse a date from the string. The string must be in the same format returned by the getDate() methods
68  	 */
69  	public Date parseDate(String date) {
70  		try {
71  			return dateFormatter.parse(date);
72  		} catch (ParseException e) {
73  			throw new IllegalArgumentException("Can't parse [" + date + "]", e);
74  		}
75  	}
76  
77  	/**
78  	 * Return a formatted date
79  	 */
80  	public String getDate(long millis) {
81  		return getDate(new Date(millis));
82  	}
83  
84  	/**
85  	 * Return a formatted date
86  	 */
87  	public String getDate(Date date) {
88  		return dateFormatter.format(date);
89  	}
90  
91  	/**
92  	 * Given a number of bytes and the number of milliseconds it took to transfer that number of bytes, return bytes/s, KB/s, MB/s, GB/s,
93  	 * TB/s, PB/s, or EB/s as appropriate
94  	 */
95  	public String getRate(long millis, long bytes) {
96  		double seconds = millis / SECOND;
97  		double bytesPerSecond = bytes / seconds;
98  		Size bandwidthLevel = getSizeEnum(bytesPerSecond);
99  		double transferRate = bytesPerSecond / bandwidthLevel.getValue();
100 		return rateFormatter.format(transferRate) + " " + bandwidthLevel.getRateLabel();
101 	}
102 
103 	/**
104 	 * Return a formatted <code>count</code>
105 	 */
106 	public String getCount(long count) {
107 		return countFormatter.format(count);
108 	}
109 
110 	/**
111 	 * Given milliseconds, return milliseconds, seconds, minutes, hours, days, years, decades, or centuries as appropriate. Note that years,
112 	 * decades, and centuries are approximations since the logic always assumes there are exactly 365 days per year.
113 	 */
114 	public String getTime(long millis) {
115 		long abs = Math.abs(millis);
116 		if (abs < SECOND) {
117 			return millis + "ms";
118 		} else if (abs < MINUTE) {
119 			return timeFormatter.format(millis / SECOND) + "s";
120 		} else if (abs < HOUR) {
121 			return timeFormatter.format(millis / MINUTE) + "m";
122 		} else if (abs < DAY) {
123 			return timeFormatter.format(millis / HOUR) + "h";
124 		} else if (abs < YEAR) {
125 			return timeFormatter.format(millis / DAY) + "d";
126 		} else if (abs < DECADE) {
127 			return timeFormatter.format(millis / YEAR) + "y";
128 		} else if (abs < CENTURY) {
129 			return timeFormatter.format(millis / DECADE) + " decades";
130 		} else {
131 			return timeFormatter.format(millis / CENTURY) + " centuries";
132 		}
133 	}
134 
135 	/**
136 	 * Given a number of bytes return bytes, kilobytes, megabytes, gigabytes, terabytes, petabytes, or exabytes as appropriate.
137 	 */
138 	public String getSize(long bytes) {
139 		return getSize(bytes, null);
140 	}
141 
142 	/**
143 	 * Given a number of bytes return a string formatted into the unit of measure indicated
144 	 */
145 	public String getSize(long bytes, Size unitOfMeasure) {
146 		unitOfMeasure = (unitOfMeasure == null) ? getSizeEnum(bytes) : unitOfMeasure;
147 		StringBuilder sb = new StringBuilder();
148 		sb.append(getFormattedSize(bytes, unitOfMeasure));
149 		if (unitOfMeasure.equals(Size.BYTE)) {
150 			sb.append(" ");
151 		}
152 		sb.append(unitOfMeasure.getSizeLabel());
153 		return sb.toString();
154 	}
155 
156 	public String getFormattedSize(long bytes, Size size) {
157 		switch (size) {
158 		case BYTE:
159 			return bytes + "";
160 		case KB:
161 		case MB:
162 		case GB:
163 			return sizeFormatter.format(bytes / (double) size.getValue());
164 		default:
165 			return largeSizeFormatter.format(bytes / (double) size.getValue());
166 		}
167 	}
168 
169 	public Size getSizeEnum(double bytes) {
170 		bytes = Math.abs(bytes);
171 		if (bytes < Size.KB.getValue()) {
172 			return Size.BYTE;
173 		} else if (bytes < Size.MB.getValue()) {
174 			return Size.KB;
175 		} else if (bytes < Size.GB.getValue()) {
176 			return Size.MB;
177 		} else if (bytes < Size.TB.getValue()) {
178 			return Size.GB;
179 		} else if (bytes < Size.PB.getValue()) {
180 			return Size.TB;
181 		} else if (bytes < Size.EB.getValue()) {
182 			return Size.PB;
183 		} else {
184 			return Size.EB;
185 		}
186 	}
187 
188 	public NumberFormat getLargeSizeFormatter() {
189 		return largeSizeFormatter;
190 	}
191 
192 	public void setLargeSizeFormatter(NumberFormat sizeFormatter) {
193 		this.largeSizeFormatter = sizeFormatter;
194 	}
195 
196 	public NumberFormat getTimeFormatter() {
197 		return timeFormatter;
198 	}
199 
200 	public void setTimeFormatter(NumberFormat timeFormatter) {
201 		this.timeFormatter = timeFormatter;
202 	}
203 
204 	public NumberFormat getRateFormatter() {
205 		return rateFormatter;
206 	}
207 
208 	public void setRateFormatter(NumberFormat rateFormatter) {
209 		this.rateFormatter = rateFormatter;
210 	}
211 
212 	public NumberFormat getSizeFormatter() {
213 		return sizeFormatter;
214 	}
215 
216 	public void setSizeFormatter(NumberFormat smallSizeFormatter) {
217 		this.sizeFormatter = smallSizeFormatter;
218 	}
219 
220 	public NumberFormat getCountFormatter() {
221 		return countFormatter;
222 	}
223 
224 	public void setCountFormatter(NumberFormat countFormatter) {
225 		this.countFormatter = countFormatter;
226 	}
227 
228 	public SimpleDateFormat getDateFormatter() {
229 		return dateFormatter;
230 	}
231 
232 	public void setDateFormatter(SimpleDateFormat dateFormatter) {
233 		this.dateFormatter = dateFormatter;
234 	}
235 }