1 /*
2  * Created on 27 juin 2003
3  * Copyright (C) Azureus Software, Inc, All Rights Reserved.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version.
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
16  *
17  */
18 package org.gudy.azureus2.core3.util;
19 
20 import java.text.SimpleDateFormat;
21 import java.util.Date;
22 import java.util.Locale;
23 import java.util.TimeZone;
24 
25 /**
26  * @author Olivier
27  *
28  */
29 public class TimeFormatter {
30   // XXX should be i18n'd
31 	static final String[] TIME_SUFFIXES = { "s", "m", "h", "d", "y" };
32 
33 	public static final String[] DATEFORMATS_DESC = new String[] {
34 		"EEEE, MMMM d, yyyy GG",
35 		"EEEE, MMMM d, yyyy",
36 		"EEE, MMMM d, yyyy",
37 		"MMMM d, ''yy",
38 		"EEE, MMM d, ''yy",
39 		"MMM d, yyyy",
40 		"MMM d, ''yy",
41 		"yyyy/MM/dd",
42 		"''yy/MM/dd",
43 		"MMM dd",
44 		"MM/dd",
45 	};
46 
47 	private static final SimpleDateFormat http_date_format =
48 		new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US );
49 
50 	static{
51 			// see http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1
52 
53 		http_date_format.setTimeZone(TimeZone.getTimeZone("GMT"));
54 	}
55 
56 	private static final SimpleDateFormat cookie_date_format =
57 		new SimpleDateFormat("EEE, dd-MMM-yyyy HH:mm:ss z", Locale.US );
58 
59 	static{
60 			// see http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1
61 
62 		cookie_date_format.setTimeZone(TimeZone.getTimeZone("GMT"));
63 	}
64 
65 	/**
66 	 * Format time into two time sections, the first chunk trimmed, the second
67 	 * with always with 2 digits.  Sections are *d, **h, **m, **s.  Section
68 	 * will be skipped if 0.
69 	 *
70 	 * @param time time in seconds
71 	 * @return Formatted time string
72 	 */
format(long time_secs)73 	public static String format(long time_secs) {
74 		if (time_secs == Constants.CRAPPY_INFINITY_AS_INT || time_secs >= Constants.CRAPPY_INFINITE_AS_LONG)
75 			return Constants.INFINITY_STRING;
76 
77 		if (time_secs < 0)
78 			return "";
79 
80 		// secs, mins, hours, days
81 		int[] vals = {
82 			(int) time_secs % 60,
83 			(int) (time_secs / 60) % 60,
84 			(int) (time_secs / 3600) % 24,
85 			(int) (time_secs / 86400) % 365,
86 			(int) (time_secs / 31536000)
87 			};
88 
89 		int end = vals.length - 1;
90 		while (vals[end] == 0 && end > 0) {
91 			end--;
92 		}
93 
94 		String result = vals[end] + TIME_SUFFIXES[end];
95 
96 		/* old logic removed to prefer showing consecutive units
97 		// skip until we have a non-zero time section
98 		do {
99 			end--;
100 		} while (end >= 0 && vals[end] == 0);
101 		*/
102 
103 		end--;
104 
105 		if (end >= 0)
106 			result += " " + twoDigits(vals[end]) + TIME_SUFFIXES[end];
107 
108 		return result;
109 	}
110 
111 	/**
112 	 * format seconds into significant y d h m s (e.g. 12d 02h 03m 23s) and drop secs if wanted
113 	 * @param time_secs
114 	 * @param do_seconds
115 	 * @return
116 	 */
117 	public static String
format2( long time_secs, boolean do_seconds )118 	format2(
119 		long 	time_secs,
120 		boolean do_seconds )
121 	{
122 		if (time_secs == Constants.CRAPPY_INFINITY_AS_INT || time_secs >= Constants.CRAPPY_INFINITE_AS_LONG)
123 			return Constants.INFINITY_STRING;
124 
125 		if (time_secs < 0)
126 			return "";
127 
128 		// secs, mins, hours, days
129 		int[] vals = {
130 			(int) time_secs % 60,
131 			(int) (time_secs / 60) % 60,
132 			(int) (time_secs / 3600) % 24,
133 			(int) (time_secs / 86400) % 365,
134 			(int) (time_secs / 31536000)
135 			};
136 
137 		int start = vals.length - 1;
138 		while (vals[start] == 0 && start > 0) {
139 			start--;
140 		}
141 
142 		int	end = do_seconds?0:1;
143 
144 		if ( start==0&&!do_seconds ){
145 			start=1;
146 		}
147 
148 		String result = "";
149 
150 		for ( int i=start;i>=end;i--){
151 
152 			result += (i==start?vals[i]:(" " + twoDigits(vals[i]))) + TIME_SUFFIXES[i];
153 		}
154 
155 		return result;
156 	}
157 
format100ths(long time_millis)158 	public static String format100ths(long time_millis) {
159 
160 		long time_secs = time_millis / 1000;
161 
162 		int  hundredths = (int)(time_millis - time_secs*1000)/10;
163 
164 		if ( time_millis == 0 || time_secs >= 60 ){
165 
166 			return( format( time_secs ));
167 		}
168 
169 		return( time_secs + "." + twoDigits( hundredths) + TIME_SUFFIXES[0]);
170 	}
171 
172 	/**
173 	 * @param time millis
174 	 */
175 
formatColonMillis( long time )176 	public static String formatColonMillis( long time )
177 	{
178 		if ( time > 0 ){
179 			if ( time < 1000 ){
180 				time = 1;
181 			}else{
182 				time = time / 1000;
183 			}
184 		}
185 
186 		String str = formatColon( time );
187 
188 		if ( str.startsWith( "00:" )){
189 
190 			str = str.substring( 3 );
191 		}
192 
193 		return( str );
194 	}
195 
196 	/**
197 	 * Format time into "[[# y] # d] 00:00:00" format
198 	 *
199 	 * @param time time in seconds
200 	 * @return
201 	 */
202 
formatColon(long time)203     public static String formatColon(long time)
204     {
205       if (time == Constants.CRAPPY_INFINITY_AS_INT || time >= Constants.CRAPPY_INFINITE_AS_LONG) return Constants.INFINITY_STRING;
206       if (time < 0) return "";
207 
208       int secs = (int) time % 60;
209       int mins = (int) (time / 60) % 60;
210       int hours = (int) (time /3600) % 24;
211       int days = (int) (time / 86400) % 365;
212       int years = (int) (time / 31536000);
213 
214       String result = "";
215       if (years > 0) result += years + "y ";
216       if (years > 0 || days > 0) result += days + "d ";
217       result += twoDigits(hours) + ":" + twoDigits(mins) + ":" + twoDigits(secs);
218 
219       return result;
220     }
221 
twoDigits(int i)222     private static String twoDigits(int i) {
223       return (i < 10) ? "0" + i : String.valueOf(i);
224     }
225 
226     	/**
227     	 * parse time in h:m:s format to SECONDS
228     	 * @param str
229     	 * @return
230     	 */
231 
232     public static int
parseColon( String str )233     parseColon(
234     	String	str )
235     {
236     	final int[]	multipliers = { 1, 60, 3600, 86400, 31536000 };
237 
238     	String[]	bits = str.split( ":" );
239 
240     	int	result = 0;
241 
242     	for (int i=0;i<bits.length;i++){
243 
244     		String bit = bits[bits.length-(i+1)].trim();
245 
246     		if ( bit.length() > 0 ){
247 
248     			result += multipliers[i] * Integer.parseInt( bit );
249     		}
250     	}
251 
252     	return( result );
253     }
254 
255     public static String
formatNanoAsMilli( long nanos )256     formatNanoAsMilli(
257     	long	nanos )
258     {
259     	final long truncator = 60*1000000000L;
260 
261     	nanos = nanos - ((nanos/truncator) * truncator);
262 
263     	return( String.valueOf(((double)nanos)/1000000) + " ms" );
264     }
265 
266     public static String
getHTTPDate( long millis )267     getHTTPDate(
268     	long		millis )
269     {
270 		synchronized( http_date_format ){
271 
272 			return( http_date_format.format(new Date( millis )));
273 		}
274     }
275 
276     public static long
parseHTTPDate( String date )277     parseHTTPDate(
278     	String		date )
279     {
280     	try{
281     		synchronized( http_date_format ){
282 
283     			return( http_date_format.parse( date ).getTime());
284     		}
285     	}catch( Throwable e ){
286 
287     		Debug.out("Failed to parse HTTP date '" + date + "'" );
288 
289     		return( 0 );
290     	}
291     }
292 
293     public static String
getCookieDate( long millis )294     getCookieDate(
295     	long		millis )
296     {
297 		synchronized( cookie_date_format ){
298 
299 			return( cookie_date_format.format(new Date( millis )));
300 		}
301     }
302 
303     public static String
milliStamp()304     milliStamp()
305     {
306     	long nanos = SystemTime.getHighPrecisionCounter();
307 
308     	final long truncator = 60*1000000000L;
309 
310     	nanos = nanos - ((nanos/truncator) * truncator);
311 
312     	String	str = String.valueOf( nanos/1000000 );
313 
314     	while( str.length() < 5 ){
315 
316     		str = "0" + str;
317     	}
318 
319     	return( str + ": " );
320     }
321 
322     public static void
milliTrace( String str )323     milliTrace(
324     	String	str )
325     {
326     	System.out.println( milliStamp() + str );
327     }
328 }
329