KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tools > ant > util > DateUtils


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */

18 package org.apache.tools.ant.util;
19
20 import java.text.ChoiceFormat JavaDoc;
21 import java.text.DateFormat JavaDoc;
22 import java.text.MessageFormat JavaDoc;
23 import java.text.ParseException JavaDoc;
24 import java.text.SimpleDateFormat JavaDoc;
25 import java.util.Calendar JavaDoc;
26 import java.util.Date JavaDoc;
27 import java.util.Locale JavaDoc;
28 import java.util.TimeZone JavaDoc;
29
30 /**
31  * Helper methods to deal with date/time formatting with a specific
32  * defined format (<a HREF="http://www.w3.org/TR/NOTE-datetime">ISO8601</a>)
33  * or a plurialization correct elapsed time in minutes and seconds.
34  *
35  * @since Ant 1.5
36  *
37  */

38 public final class DateUtils {
39
40     /**
41      * ISO8601-like pattern for date-time. It does not support timezone.
42      * <tt>yyyy-MM-ddTHH:mm:ss</tt>
43      */

44     public static final String JavaDoc ISO8601_DATETIME_PATTERN
45             = "yyyy-MM-dd'T'HH:mm:ss";
46
47     /**
48      * ISO8601-like pattern for date. <tt>yyyy-MM-dd</tt>
49      */

50     public static final String JavaDoc ISO8601_DATE_PATTERN
51             = "yyyy-MM-dd";
52
53     /**
54      * ISO8601-like pattern for time. <tt>HH:mm:ss</tt>
55      */

56     public static final String JavaDoc ISO8601_TIME_PATTERN
57             = "HH:mm:ss";
58
59     /**
60      * Format used for SMTP (and probably other) Date headers.
61      */

62     public static final DateFormat JavaDoc DATE_HEADER_FORMAT
63         = new SimpleDateFormat JavaDoc("EEE, dd MMM yyyy HH:mm:ss ", Locale.US);
64
65
66 // code from Magesh moved from DefaultLogger and slightly modified
67
private static final MessageFormat JavaDoc MINUTE_SECONDS
68             = new MessageFormat JavaDoc("{0}{1}");
69
70     private static final double[] LIMITS = {0, 1, 2};
71
72     private static final String JavaDoc[] MINUTES_PART = {"", "1 minute ", "{0,number} minutes "};
73
74     private static final String JavaDoc[] SECONDS_PART = {"0 seconds", "1 second", "{1,number} seconds"};
75
76     private static final ChoiceFormat JavaDoc MINUTES_FORMAT =
77             new ChoiceFormat JavaDoc(LIMITS, MINUTES_PART);
78
79     private static final ChoiceFormat JavaDoc SECONDS_FORMAT =
80             new ChoiceFormat JavaDoc(LIMITS, SECONDS_PART);
81
82     static {
83         MINUTE_SECONDS.setFormat(0, MINUTES_FORMAT);
84         MINUTE_SECONDS.setFormat(1, SECONDS_FORMAT);
85     }
86
87     /** private constructor */
88     private DateUtils() {
89     }
90
91
92     /**
93      * Format a date/time into a specific pattern.
94      * @param date the date to format expressed in milliseconds.
95      * @param pattern the pattern to use to format the date.
96      * @return the formatted date.
97      */

98     public static String JavaDoc format(long date, String JavaDoc pattern) {
99         return format(new Date JavaDoc(date), pattern);
100     }
101
102
103     /**
104      * Format a date/time into a specific pattern.
105      * @param date the date to format expressed in milliseconds.
106      * @param pattern the pattern to use to format the date.
107      * @return the formatted date.
108      */

109     public static String JavaDoc format(Date JavaDoc date, String JavaDoc pattern) {
110         DateFormat JavaDoc df = createDateFormat(pattern);
111         return df.format(date);
112     }
113
114
115     /**
116      * Format an elapsed time into a plurialization correct string.
117      * It is limited only to report elapsed time in minutes and
118      * seconds and has the following behavior.
119      * <ul>
120      * <li>minutes are not displayed when 0. (ie: "45 seconds")</li>
121      * <li>seconds are always displayed in plural form (ie "0 seconds" or
122      * "10 seconds") except for 1 (ie "1 second")</li>
123      * </ul>
124      * @param millis the elapsed time to report in milliseconds.
125      * @return the formatted text in minutes/seconds.
126      */

127     public static String JavaDoc formatElapsedTime(long millis) {
128         long seconds = millis / 1000;
129         long minutes = seconds / 60;
130         Object JavaDoc[] args = {new Long JavaDoc(minutes), new Long JavaDoc(seconds % 60)};
131         return MINUTE_SECONDS.format(args);
132     }
133
134     /**
135      * return a lenient date format set to GMT time zone.
136      * @param pattern the pattern used for date/time formatting.
137      * @return the configured format for this pattern.
138      */

139     private static DateFormat JavaDoc createDateFormat(String JavaDoc pattern) {
140         SimpleDateFormat JavaDoc sdf = new SimpleDateFormat JavaDoc(pattern);
141         TimeZone JavaDoc gmt = TimeZone.getTimeZone("GMT");
142         sdf.setTimeZone(gmt);
143         sdf.setLenient(true);
144         return sdf;
145     }
146
147     /**
148      * Calculate the phase of the moon for a given date.
149      *
150      * <p>Code heavily influenced by hacklib.c in <a
151      * HREF="http://www.nethack.org/">Nethack</a></p>
152      *
153      * <p>The Algorithm:
154      *
155      * <pre>
156      * moon period = 29.53058 days ~= 30, year = 365.2422 days
157      *
158      * days moon phase advances on first day of year compared to preceding year
159      * = 365.2422 - 12*29.53058 ~= 11
160      *
161      * years in Metonic cycle (time until same phases fall on the same days of
162      * the month) = 18.6 ~= 19
163      *
164      * moon phase on first day of year (epact) ~= (11*(year%19) + 18) % 30
165      * (18 as initial condition for 1900)
166      *
167      * current phase in days = first day phase + days elapsed in year
168      *
169      * 6 moons ~= 177 days
170      * 177 ~= 8 reported phases * 22
171      * + 11/22 for rounding
172      * </pre>
173      *
174      * @param cal the calander.
175      *
176      * @return The phase of the moon as a number between 0 and 7 with
177      * 0 meaning new moon and 4 meaning full moon.
178      *
179      * @since 1.2, Ant 1.5
180      */

181     public static int getPhaseOfMoon(Calendar JavaDoc cal) {
182         int dayOfTheYear = cal.get(Calendar.DAY_OF_YEAR);
183         int yearInMetonicCycle = ((cal.get(Calendar.YEAR) - 1900) % 19) + 1;
184         int epact = (11 * yearInMetonicCycle + 18) % 30;
185         if ((epact == 25 && yearInMetonicCycle > 11) || epact == 24) {
186             epact++;
187         }
188         return (((((dayOfTheYear + epact) * 6) + 11) % 177) / 22) & 7;
189     }
190
191     /**
192      * Returns the current Date in a format suitable for a SMTP date
193      * header.
194      * @return the current date.
195      * @since Ant 1.5.2
196      */

197     public static String JavaDoc getDateForHeader() {
198         Calendar JavaDoc cal = Calendar.getInstance();
199         TimeZone JavaDoc tz = cal.getTimeZone();
200         int offset = tz.getOffset(cal.get(Calendar.ERA),
201                                   cal.get(Calendar.YEAR),
202                                   cal.get(Calendar.MONTH),
203                                   cal.get(Calendar.DAY_OF_MONTH),
204                                   cal.get(Calendar.DAY_OF_WEEK),
205                                   cal.get(Calendar.MILLISECOND));
206         StringBuffer JavaDoc tzMarker = new StringBuffer JavaDoc(offset < 0 ? "-" : "+");
207         offset = Math.abs(offset);
208         int hours = offset / (60 * 60 * 1000);
209         int minutes = offset / (60 * 1000) - 60 * hours;
210         if (hours < 10) {
211             tzMarker.append("0");
212         }
213         tzMarker.append(hours);
214         if (minutes < 10) {
215             tzMarker.append("0");
216         }
217         tzMarker.append(minutes);
218         return DATE_HEADER_FORMAT.format(cal.getTime()) + tzMarker.toString();
219     }
220
221     /**
222      * Parse a string as a datetime using the ISO8601_DATETIME format which is
223      * <code>yyyy-MM-dd'T'HH:mm:ss</code>
224      *
225      * @param datestr string to be parsed
226      *
227      * @return a java.util.Date object as parsed by the format.
228      * @exception ParseException if the supplied string cannot be parsed by
229      * this pattern.
230      * @since Ant 1.6
231      */

232     public static Date JavaDoc parseIso8601DateTime(String JavaDoc datestr)
233         throws ParseException JavaDoc {
234         return new SimpleDateFormat JavaDoc(ISO8601_DATETIME_PATTERN).parse(datestr);
235     }
236
237     /**
238      * Parse a string as a date using the ISO8601_DATE format which is
239      * <code>yyyy-MM-dd</code>
240      *
241      * @param datestr string to be parsed
242      *
243      * @return a java.util.Date object as parsed by the format.
244      * @exception ParseException if the supplied string cannot be parsed by
245      * this pattern.
246      * @since Ant 1.6
247      */

248     public static Date JavaDoc parseIso8601Date(String JavaDoc datestr) throws ParseException JavaDoc {
249         return new SimpleDateFormat JavaDoc(ISO8601_DATE_PATTERN).parse(datestr);
250     }
251
252     /**
253      * Parse a string as a date using the either the ISO8601_DATETIME
254      * or ISO8601_DATE formats.
255      *
256      * @param datestr string to be parsed
257      *
258      * @return a java.util.Date object as parsed by the formats.
259      * @exception ParseException if the supplied string cannot be parsed by
260      * either of these patterns.
261      * @since Ant 1.6
262      */

263     public static Date JavaDoc parseIso8601DateTimeOrDate(String JavaDoc datestr)
264         throws ParseException JavaDoc {
265         try {
266             return parseIso8601DateTime(datestr);
267         } catch (ParseException JavaDoc px) {
268             return parseIso8601Date(datestr);
269         }
270     }
271 }
272
Popular Tags